日常ansible playbook编写过程中,会涉及到很多变量的解析与替换,解析并替换模板表达式的过程称为渲染。
ansibles使用Jinja2
来完成渲染工作,它是Python的一种模板引擎。
Jinja2模板引擎提供了三种特殊符号来包围模板表达式:
- {{xxx}}:双大括号包围变量或表达式(Ansible中的变量就是它包围的)
- {#xxx#}:Jinja2的注释符号
- {%xxx%}:Jinja2的一些特殊关键字标签,比如if语句、for循环语句等等
Jinja2条件判断
Jinja2中可以使用if语句进行条件判断。
语法如下:
1 | {% if CONDITION1 %} |
其中elif和else分支都是可省略的。CONDITION部分是条件表达式
例如:
当前结构如下
1 | [root@slions_pc1 ansible_poc]# tree |
其中模板文件my.j2内容是:
1 | {% if whatday == "0" %} |
上面判断变量whatday的值,然后输出对应的星期几。因为whatday变量的值是字符串,所以让它和字符串形式的数值进行等值比较。当然,也可以使用筛选器将字符串转换为数值后进行数值比较:whatday|int == 0。
roles/first/tasks中的main.yml内容为:
1 |
|
任务入口文件test.yml内容为:
1 | - hosts: localhost |
执行后可以在/tmp/dayfile中查看到替换后的对应字符。
如果if语句的分支比较简单(没有elif逻辑),那么可以使用行内if表达式。
其语法格式为:
1 | string_or_expr1 if CONDITION else string_or_expr2 |
因为行内if是表达式而不是语句块,所以不使用 {%%} 符号,而使用{{}} 。
例如:
1 | - debug: |
for循环迭代
for迭代列表
for循环的语法:
1 | {% for i in LIST %} |
还支持直接条件判断筛选要参与迭代的元素:
1 | {% for i in LIST if CONDITION %} |
此外,Jinja2的for语句还允许使用else分支,如果for所迭代的列表LIST是空列表(或没有元素可迭代),则会执行else分支。
1 | {% for i in LIST %} |
例如,在模板文件a.txt.j2中有如下内容:
1 | {% for file in files %} |
playbook文件内容如下:
1 | --- |
执行playbook之后,将生成包含如下内容的/tmp/a.txt文件:
1 | </tmp/a1> |
如果将playbook中的files变量设置为空列表,则会执行else分支,所以生成的/tmp/a.txt的内容为:
1 | no file in files |
如果files变量未定义或变量类型不是list,则默认会报错。针对未定义变量,可采用如下策略提供默认空列表:
1 | {% for file in (files|default([])) %} |
如果不想迭代文件列表中的/tmp/a3,则可以加上条件判断:
1 | {% for file in (files|default([])) if file != "/tmp/a3" %} |
Jinja2的for循环没有提供break和continue的功能,所以只能通过{% for…if…%}来间接实现类似功能。