ansible☞模板

阅读量: zyh 2020-05-20 20:42:44
Categories: > Tags:

前言

当你用ansible进行多机器的配置调整,且调整的东西都一模一样,此时你不会拒绝模板的诱惑。

ansible的模板是jinja2,所以jinja2的特性,在这里都可以用。

模板中,不要出现任何你觉得模板会忽略的东西,包括但不限于空格

模块 template

参数:

牵扯到目的路径,必然有权限参数

覆盖与备份

---
- hosts: localhost
  remote_user: zyh
  gather_facts: no
  tasks:
    - template:
        src: ~/test.j2
        dest: ~/test.info

模板分隔符

{{ }} 一般用来填充变量,可以是过滤器,也可以填充表达式,从而返回相应的值,例如 {{ 1==1 }} 返回 True
{% %} 一般用来填充控制语句
{# #} 模板注释语句,并非渲染后会出现
#  ... ## 这一种 ansible 貌似不支持,所以可以忽略

分隔符1

# {{ }}
{# 普通变量 #}
{{ foo.bar }}
{{ foo['bar'] }}
{# 以过滤器 lookup 为例 #}
{{ lookup('file', '~/test.file') }}
{{ lookup('env', 'PATH' )}}

最终目的文件,会输出~/test.file 内容和 $PATH 内容

字符串拼接需要使用~,例如 "name:"~name

分隔符2

# {% %}
# 官网所有的控制列表
https://jinja.palletsprojects.com/en/master/templates/#list-of-control-structures

条件控制语句 if

{% if 条件1 %}
  pass
{% elif 条件2 %}
  pass
{% else %}
  pass 
{% endif %}

循环语句 for

{% for i in 可迭代对象 %}
  {{ i }}
{% endfor %}

默认循环后,每一个循环单体独占一行,如果需要删除独占,则需要给第二个%}和第三个控制符{%加减号,最终变为-%}和{%-。

关于字典类型,可以使用 iteritems() 函数,从而方便的获取到字典的 k 和 v。例如

{% for k,v in {'name':'zhangsan', 'gender':'male'}.iteritems() %}
  {{ k }}:{{ v }}
{% endfor %}
# 渲染后
name:zhangsan
gender:male

条件和循环组合语句

{% for i in 可迭代对象 if 条件 %}
  满足条件语句
{% else %}
  不满足条件语句
{% endfor %}

例如

{% for i in [1,2,3,4] if i>2 %}
{{ i }}'s index is {{ loop.index }}
{% endfor %}
# 渲染后
3's index is 1
4's index is 2

loop.index 是循环体索引,这里可能会有个疑问。

正常情况下,3和4的索引应该就是3和4,之所以是1和2,原因在于当条件控制和循环控制位于同一行的时候,先行运算的是 [1,2,3,4] if i>2,之后才开始走for循环。

如果你想输出原始循环体,则需要将条件控制语句另起一行,放在for循环内部

{% for i in [1,2,3,4] %}
{% if i>2 %}
{{ i }}'s index is {{ loop.index }}
{% endif %}
{% endfor %}
# 渲染后
3's index is 3
4's index is 4

上述的 loop.index 只是jinja2的一种使用方式,其它方式具体可见官网文档

https://jinja.palletsprojects.com/en/master/templates/#list-of-control-structures

宏 macro

宏就是类似于函数的一个东西。

{# 编写宏 #}
{% macro func() %}
函数体
{% endmacro %}
{# 调用宏 #}
{{ func() }}

例如:

{% macro func(a,b,c=3,d=4) %}
{# 宏编写的时候,宏参数,要遵循默认参数在后
{{ a }}
{{ b }}
{{ c }}
{{ d }}
{% endmacro %}
{{ func(1,2,5) }}
# 渲染后
1
2
5
4

当给出参数超出了宏所定义的参数时,根据情况,宏会将多余的参数存在变量中,即:

超出的为非关键字参数,则存放在一个叫varargs的元组中

超出的为关键字参数,则存放在一个叫kwargs的字典中

call 方法

如同当前函数的装饰器,可以扩展当前宏的功能

{# 编写宏 func,并调用 caller #}
{% macro func(a) %}
我有一个{{ a }}。
{{ caller(a) }}
{% endmacro %}
{# 编写宏 func_ext #}
{% macro func_ext(a,b) %}
但{{ b }}比{{ a }}好吃。
{% endmacro %}
{# 通过 call 关联 func,加载 func_ext #}
{% call(a) func('汉堡') %}
{{ func_ext(a,'三明治') }}
{% endcall %}

caller是call的对象,因此caller也是可以给call传参

# 渲染后
我有一个汉堡。
但三明治比汉堡好吃

扩展

扩展官方文档,可见 https://jinja.palletsprojects.com/en/master/extensions/

这里我只简单的说一下如何启动 for 循环中的 breakcontinue

ansible 中添加 jinja2 扩展,需要修改主配置文件 /etc/ansible/ansible.cfg,找到 jinja2_extensions ,在后面追加扩展配置即可,每一个扩展用逗号,分割。

breakcontinue 的扩展名叫:jinja2.ext.loopcontrols