ansible11:jinja2模板
简单介绍
比如现在有需求安装10台redis,结合前面的知识,简单,写一个ansible-playnook配合inventory就可以实现,但是redis启动后端口默认是监听在127.0.0.1上面的,这样使得其他主机的程序无法调用redis,但是又不能一台一台修改配置文件中的bind吧,这种情况就有了模板的解决方案,大致可以分为三步:
-
从别的redis程序中或者网上找一份配置文件,作为“模板”文件。
-
修改模板文件,将bind配置项中的IP设为变量。
-
使用ansible调用“template”模块,对模板文件进行渲染,根据模板生成每个主机对应的配置文件,并将最终生成的配置文件拷贝至目标主机中,启动redis。
# 举例对比理解。 0 15:16:32 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat /etc/ansible/hosts ck-master ansible_host=172.16.2.9 ck-node1 ansible_host=172.16.15.21 ck-node2 ansible_host=172.16.15.22 ck-node3 ansible_host=172.16.15.23 0 15:16:39 root@ck-ansible,172.16.2.9:/server/ops_ansible # grep bind redis.conf bind {{ansible_host}} 0 15:16:42 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat redis.yaml --- - hosts: ck-node1 tasks: - name: deploy redis yum: name: redis - name: copy template template: src: /server/ops_ansible/redis.conf dest: /etc/redis.conf backup: yes 0 15:16:48 root@ck-ansible,172.16.2.9:/server/ops_ansible # ansible-playbook redis.yaml # 在目标主机上验证一下。 0 15:15:15 root@ck-node1,172.16.15.21:~ # grep bind /etc/redis.conf bind 172.16.15.21
语法说明
{{ }}
-
说明:用来装载表达式,比如变量、运算、比较等,前面文章已经用的很多了哈。
-
举例:
0 15:47:04 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test.j2 # test jinja2 var The value of this variable is {{ var1 }} # test jinja2 compare and operation {{ 1 == 1 }} {{ 2 != 2 }} {{ 2 > 1 }} {{ 2 >= 1 }} {{ 2 < 1 }} {{ 2 <= 1 }} {{ (2 > 1) or (1 > 2) }} {{ (2 > 1) and (1 > 2) }} {{ not true }} {{ not True }} {{ not false }} {{ not False }} {{ 3 + 2 }} {{ 3 - 4 }} {{ 3 * 5 }} {{ 2 ** 3 }} {{ 7 / 5 }} {{ 7 // 5 }} {{ 17 % 5 }} # python data type ## str {{ 'testString' }} {{ "testString" }} ## num {{ 15 }} {{ 18.8 }} ## list {{ ['Aa','Bb','Cc','Dd'] }} {{ ['Aa','Bb','Cc','Dd'].1 }} {{ ['Aa','Bb','Cc','Dd'][1] }} ## tuple {{ ('Aa','Bb','Cc','Dd') }} {{ ('Aa','Bb','Cc','Dd').0 }} {{ ('Aa','Bb','Cc','Dd')[0] }} ## dic {{ {'name':'bob','age':18} }} {{ {'name':'bob','age':18}.name }} {{ {'name':'bob','age':18}['name'] }} ## bool {{ True }} {{ true }} {{ False }} {{ false }} 0 15:41:44 root@ck-ansible,172.16.2.9:/server/ops_ansible # ansible ck-node1 -m template -e 'var1=wula' -a 'src=test.j2 dest=/opt/test' # jinja2本身是基于python的模板引擎,所以python的基础数据类型都可以包含在”{{ }}”中。 # 前文中讲的tests判断、lookup插件、过滤器也可以在{{ }}中使用。
-
说明:用来装载注释信息。模板文件被渲染后,注释不会包含在最终生成的文件中。
-
举例:
# 把第一例中的注释修改为{# #}写法。 0 15:54:19 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test.j2 {#test jinja2 var#} The value of this variable is {{ var1 }} {# 注释1 注释2 注释3 #}
if控制语句
-
语法。
# 语法一 {% if 条件 %} ... {% endif %} # 语法二 {% if 条件一 %} ... {% elif 条件N %} ... {% endif %} # 语法三 {% if 条件 %} ... {% else %} ... {% endif %} # 语法四 {% if 条件一 %} ... {% elif 条件N %} ... {% else %} ... {% endif %}
-
举例。
# 举例1 0 16:13:07 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test.j2 {% if testnum > 3 %} greater than 3 {% endif %} 0 16:13:10 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test.yaml --- - hosts: ck-node1 vars: testnum: 5 tasks: - template: src: test.j2 dest: /opt/test 0 16:13:15 root@ck-ansible,172.16.2.9:/server/ops_ansible # ansible-playbook test.yaml
if表达式
-
说明:可以实现类似三元运算的效果。条件成立输出a,不成立输出b。
-
举例。
0 16:16:05 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test.j2 {{ 'a' if 2>1 else 'b' }} 0 16:16:08 root@ck-ansible,172.16.2.9:/server/ops_ansible # ansible ck-node1 -m template -a 'src=test.j2 dest=/opt/test'
for循环
-
语法:
{% for 迭代变量 in 可迭代对象 %} {{ 迭代变量 }} {% endfor %}
-
for循环指定分隔符。
# 例1:循环操作列表 0 16:28:47 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test1.j2 {% for n in [3,1,7,8,2] %} {{ n }} # 这里空两个空格,结果中也会空两个空格。 {% endfor %} 0 16:28:53 root@ck-ansible,172.16.2.9:/server/ops_ansible # ansible ck-node1 -m template -a 'src=test1.j2 dest=/opt/test' # 例2: 取消例1执行结果的自动换行。 0 16:31:02 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test2.j2 {% for n in [3,1,7,8,2] -%} {{ n }} {%- endfor %}、 # 例3:取消例1执行结果的自动换行,并指定分隔符 0 16:37:03 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test3.j2 {% for n in [3,1,7,8,2] -%} {{ n ~ ',' }} # ~作为连接符。 {%- endfor %} # 例4:循环操作字典。 0 16:40:53 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test4.j2 {% for k,v in {'name': 'zoe','age': 18}.iteritems() %} # 字典需要调用iteritems函数处理。 {{ k ~ ': ' ~ v }} {% endfor %}
-
loop.index:打印整个循环的第几次循环,从序号1开始。
0 16:45:55 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test5.j2 {% for n in [3,1,7,8,2] %} {{ n ~ '--' ~ loop.index }} {% endfor %}
-
loop.index0:打印整个循环的第几次循环,从序号0开始。
-
loop.revindex:打印当前循环次距离整个循环结束还剩几次,到序号1结束。
0 17:07:05 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test6.j2 {% for n in [3,1,7,8,2] %} {{ n ~ '--' ~ loop.revindex }} {% endfor %}
-
loop.revindex0:打印当前循环次距离整个循环结束还剩几次,到序号0结束。
-
range:范围取值(顾头不顾尾,不会取最后一个数值)。
# 例1: {% for n in range(5) %} {{ n }} {% endfor %} # 例2: 0 17:20:45 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test8.j2 {% for n in range(1,5,2) %} # 前面有说过,三个数值分别是起始、结束、步长。 {{ n }} {% endfor %}
-
for结合if实现过滤。
# 写法1: 0 17:24:00 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test9.j2 {% for n in [1,5,2,8,6] if n>5 %} {{ n }} {% endfor %} # 写法2: 0 17:26:37 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test10.j2 {% for n in [1,5,2,8,6] %} {% if n>5 %} {{ n }} {% endif %} {% endfor %} # 从表面上看两种写法的结果一样,但是执行过程是有区别的,我们可以用loop.index查看一下。 0 18:11:57 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test11.j2 {% for n in [1,5,2,8,6] if n>5 %} {{ n ~ '--' ~ loop.index }} {% endfor %} {% for n in [1,5,2,8,6] %} {% if n>5 %} {{ n ~ '--' ~ loop.index }} {% endif %} {% endfor %} 0 18:13:01 root@ck-ansible,172.16.2.9:/server/ops_ansible # ansible ck-node1 -m template -a 'src=test11.j2 dest=/opt/test' 0 18:13:17 root@ck-node1,172.16.15.21:~ # cat /opt/test 8--1 6--2 8--4 6--5 # 从结果可以看出,当第一种for循环内联if表达式时,不满足条件时loop.index是不会计算的;而第二种在for循环中单独使用if表达式时,不满足条件也会被loop.index计算。
-
for+if else
0 18:17:57 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test12.j2 {% for n in [1,5,2,8,6] if n>9 %} {{ n }} {% else %} no one is greater than 9 {% endfor %}
-
for else
# 当列表为空时,才会渲染else的内容。 0 18:23:55 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test13.j2 {% set userlist=[] %} # 定义变量。 {% for u in userlist %} {{ u }} {% else %} no one {% endfor %}
-
for循环递归。
0 18:38:13 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test14.j2 {% set userinfo={'name': 'zoe','son': {'name': 'bob','son': {'name': 'tom'}}} %} {% for k,v in userinfo.iteritems() recursive %} {% if k == 'name' %} {% set fathername=v %} {% endif %} {% if k == 'son' %} {{ fathername ~ "'s son is " ~ v.name}} {{ loop( v.iteritems() ) }} {% endif %} {% endfor %}
-
loop.cycle:与指定的值轮询结合。
0 18:46:43 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test15.j2 {% set userlist=['bob','zoe','selina','tom'] %} {% for u in userlist %} {{ u ~ '--' ~ loop.cycle('team1','team2') }} {% endfor %}
-
默认情况下,jinja2中的for循环无法使用break或continue,是因为jinja2把这种操作归纳在了一些扩展中,启用相应扩展即可使用相应功能。
# 修改配置文件启用jinja2扩展,添加loopcontrols扩展即可在循环中使用break和continue。 0 18:57:37 root@ck-ansible,172.16.2.9:/server/ops_ansible # vim /etc/ansible/ansible.cfg jinja2_extensions = jinja2.ext.do,jinja2.ext.i18n,jinja2.ext.loopcontrols 0 19:13:56 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test16.j2 {% for n in [1,5,2,8,6] %} {% if loop.index>4 %} {% break %} {% endif %} {{ n ~ '--' ~ loop.index }} {% endfor %}
-
for+continue:跳过偶数次的循环
0 19:34:41 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test16.j2 {% for n in [1,5,2,8,6] %} {% if loop.index is even %} {% continue %} {% endif %} {{ n ~ '--' ~ loop.index }} {% endfor %}
-
for+break。
# 3次迭代以后的元素不再处理。 0 19:36:12 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test17.j2 {% for n in [1,5,2,8,6] %} {% if loop.index>3 %} {% break %} {% endif %} {{ n ~ '--' ~ loop.index }} {% endfor %}
-
for+do扩展:修改列表内容。ansible.cfg默认就包含do扩展,启用即可。
0 19:43:31 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test18.j2 {% set numlist=[1,3,5] %} {% for n in numlist %} {{ n }} {% endfor %} {%do numlist.append(7)%} # append:追加到末尾。 {% for n in numlist %} {{n}} {% endfor %}
转义相关
-
raw:上面有说{{}}、{##}、{%%}都会被jinja2引擎识别并处理,但有些场景就需要结果中包含这些特殊符号呢?那就需要借助raw转义了。
0 19:51:33 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test1.j2 {% raw %} {{ test }} {% test %} {# test #} {% if %} {% endfor %} {% endraw %}
-
variable_start_string和variable_end_string:替换{{ }}中的“{{”和“}}”。
0 20:07:54 root@ck-ansible,172.16.2.9:/server/ops_ansible # ll 总用量 8 -rw-r--r-- 1 root root 78 10月 26 19:51 test1.j2 -rw-r--r-- 1 root root 85 10月 26 20:07 test2.j2 0 20:07:55 root@ck-ansible,172.16.2.9:/server/ops_ansible # ansible ck-node1 -m template -a 'src=test2.j2 dest=/opt/test variable_start_string="((" variable_end_string="))"'
-
block_start_string和block_start_string:替换{% %}中的“{%”和“%}”
宏相关
jinja2中的函数也成为宏,利用宏可以重复利用一段内容,jinja2宏也可以传入参数,一些涉及到的概念说明(我不确定ansible中是不是有如下概念,只是拿了python的概念到这来方便理解):
- 形参:在宏(函数)定义阶段括号内定义的参数,称之为形式参数,简称形参。形参的本质是变量名。
- 位置形参:在宏定义阶段,按从左到右的顺序依次定义的形参,称之为位置形参。但凡是按照位置定义的形参,都必须被传值,而且一定数量对等。
- 默认形参:在函数定义阶段就为形参赋值,该形参称为默认形参。
- 实参:在函数调用阶段括号内传入的值,称之为实际参数,简称实参。实参的本质是变量值。
- 位置实参:在函数调用阶段,按从左到右的顺序依次定义的实参,称之为位置实参。按照位置为对应的形参依次传值。
- 关键字实参:在调用函数时,按照key=value形式为指定的参数传值,称为关键字实参。
-
定义一个简单的宏。
0 20:15:31 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test1.j2 {% macro testfunc() %} # 定义宏 test string # 宏内容 {% endmacro %} # 定义宏 {{ testfunc() }} # 调用宏
-
传参宏。
0 20:19:31 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test2.j2 {% macro testfunc(v1=111) %} # 定义宏时设置默认形参是111。 test string {{ v1 }} {% endmacro %} {{ testfunc() }} # 不传参打印默认形参。 {{ testfunc(666) }} # 打印传参。
-
多个传参时,位置实参必须放在关键字实参的前面,与位置形参一一对应,否则会打印错误结果。
0 20:29:27 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test3.j2 {% macro testfunc(v1,v2,v3=3,v5=5) %} test string {{ v1 }} {{ v2 }} {{ v3 }} {{ v5 }} {% endmacro %} {{ testfunc('a','b') }} # 可见:调用宏时传入的值会按照参数顺序进行对应赋值。
-
指定传参:位置实参必须放在关键字实参的前面,与位置形参一一对应。
0 21:35:19 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test4.j2 {% macro testfunc(v1,v2,v3=3,v5=5) %} test string {{ v1 }} {{ v2 }} {{ v3 }} {{ v5 }} {% endmacro %} {{ testfunc('a','b',v5=777) }}
内置变量
-
varargs:将溢出的非关键字传参全部接收,以元组类型存储在varargs变量中(类似python的*args)。
# 例1 0 21:51:53 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test1.j2 {% macro testfunc(testarg1=1,testarg2=2) %} test string {{testarg1}} {{testarg2}} {{varargs}} {% endmacro %} {{ testfunc('a','b','c','d','e') }} # 例2:没有定义参数,使用宏时可以传入任意值。 0 22:09:05 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test2.j2 {% macro testfunc() %} test string {%for i in varargs%} {{i}} {%endfor%} {{ '--------' }} {% endmacro %} {{ testfunc() }} {{ testfunc(1,2,3) }}
-
kwargs:将溢出的关键字传参全部接收,以字典类型存储在wkargs变量中(类似python的*kwargs)。
0 11:28:11 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test3.j2 {% macro testfunc(v1=555) %} test string {{kwargs}} {% endmacro %} {{ testfunc(666,testvar='abc') }}
-
caller:说是caller变量,不如说是caller方法。使用caller方法可以替换宏中的内容。
0 11:30:55 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test4.j2 {% macro testfunc() %} test string {{caller()}} {% endmacro %} {%call testfunc() %} wula {% endcall %} # 可以理解为把caller空变量放在testfunc函数中,在下面使用call方法重新复制给了caller变量,实现改变宏内容的操作。
-
使用caller在一个宏中调用另外一个宏。
0 13:24:29 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test5.j2 {% macro testfunc1() %} test string {{caller()}} {% endmacro %} {% macro testfunc2() %} {% for i in range(3) %} {{i}} {% endfor %} {% endmacro %} {%call testfunc1()%} {{testfunc2()}} {%endcall%}
-
caller传参。
0 13:35:58 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test6.j2 {% macro testfunc() %} test string {{caller('wula')}} {% endmacro %} {% call(var1) testfunc() %} {{var1}} {% endcall %}
宏属性
-
name:宏的名称。
-
arguments:在宏定义阶段,所有参数的参数名组成一个元组存放在arguments属性中。
-
defaults:在宏定义阶段,所有的默认形参组成了一个元组存放在defaults中。
-
catch_varargs:如果宏中使用了varargs变量,此属性的值为true。
-
catch_kwargs: 如果宏中使用了kwargs变量,此属性的值为true。
-
caller:如果宏中使用了caller变量,此属性值为true。
0 13:39:50 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test7.j2 {% macro foo(v1,v2,v3=5,v5=5) %} test string {{ v1 }} {{ v2 }} {{ v3 }} {{ v5 }} {% endmacro %} {{ foo.name }} {{ foo.arguments }} {{ foo.defaults }} {{ foo.catch_varargs }} {{ foo.catch_kwargs }} {{ foo.caller }}
{% include % }包含
-
jinja2中也可以使用“include”去加载包含其它j2文件。比如在test2.j2中引用test1.j2。
0 13:50:12 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test1.j2 test1.j2 info start {% for n in range(3) %} {{ n }} {% endfor %} test1.j2 info end 0 13:50:16 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test2.j2 test2.j2 info start {% include 'test1.j2' %} test2.j2 info end 0 13:50:18 root@ck-ansible,172.16.2.9:/server/ops_ansible # ansible ck-node1 -m template -a 'src=test2.j2 dest=/opt/test'
-
默认情况下,被包含文件是可以使用主文件中定义的变量的。
# 例1: 0 13:52:56 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test3.j2 test3.j2 info start {{ var1 | default('natasha',boolean=true) }} test3.j2 info end 0 13:53:00 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test4.j2 test4.j2 info start {% set var1='wula' %} {% include 'test3.j2' %} test4.j2 info end 0 14:39:55 root@ck-ansible,172.16.2.9:/server/ops_ansible # ansible ck-node1 -m template -a 'src=test4.j2 dest=/opt/test'
-
include一个不存在j2文件时,忽略报错。
0 14:45:45 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test5.j2 test5.j2 info start {{ var1 | default('natasha',boolean=true) }} test5.j2 info end 0 14:45:51 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test6.j2 test6.j2 info start {% set var1='wula' %} {% include 'test5.j2' %} {% include 'test7.j2' ignore missing %} test6.j2 info end 0 14:45:53 root@ck-ansible,172.16.2.9:/server/ops_ansible # ansible ck-node1 -m template -a 'src=test6.j2 dest=/opt/test'
{% import %}导入
-
include的作用是在模板中包含另一个模板文件,而import的作用是在一个文件中导入其它文件中的宏。下面举例:使用import..as方式导入宏文件中的全部宏。
0 16:56:12 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat funclib.j2 {% macro foo1(v1) %} {{ v1 }} {% endmacro %} {% macro foo2(v2) %} {{ v2 }} {% endmacro %} 0 16:56:14 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test1.j2 test1.j2 info start {% import 'funclib.j2' as funclib %} # 将funclib.j2文件中的宏导入到funclib变量中,方便后续调用。 {{ funclib.foo1('wula') }} {{ funclib.foo2('natasha') }} test1.j2 info end
-
使用from..import..方式导入宏文件中的指定宏。
0 16:57:55 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat funclib.j2 {% macro foo1(v1) %} {{ v1 }} {% endmacro %} {% macro foo2(v2) %} {{ v2 }} {% endmacro %} 0 16:57:58 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test2.j2 test1.j2 info start {% from 'funclib.j2' import foo1 as f1,foo2 as f2 %} {{ f1('wula') }} {{ f2('bobosha') }} test1.j2 info end
-
如果宏的名字是以一个或多个下划线开头,则表示这个宏为私有宏,私有宏不能被导入到其他文件中使用。
0 17:01:56 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat funclib.j2 {% macro _foo(v1) %} {{ v1 }} {% endmacro %} {{ _foo('wula') }}
继承
模板继承:将通用的配置写在主模板的公共区域,将可能需要修改或者动态填充的部分写在主模板的块(block)中,后续使用如果涉及到修改配置,可以编写一个子模板直接继承主模板的公共区域配置,只覆盖需要修改的块(block)即可。
-
使用子模板去继承主模板。
0 17:49:59 root@ck-ansible,172.16.2.9:/server/ops_ansible # ll 总用量 8 -rw-r--r-- 1 root root 92 10月 27 17:49 subtem.j2 -rw-r--r-- 1 root root 161 10月 27 17:49 tem.j2 0 17:50:01 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat tem.j2 fixed configuration1 # 相对固定的配置 fixed configuration2 fixed configuration3 {% block bt1 %} # 把相对不固定的配置写在bt1块中。 Unfixed configuration1 # 相对不固定的配置 Unfixed configuration2 {% endblock %} fixed configurationN 0 17:50:03 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat subtem.j2 {% extends 'tem.j2' %} # 继承主模板 {% block bt1 %} new configuration1 # 编写bt1块中的新配置去替换主模板中的旧配置。 new configuration2 {% endblock %}
-
存在块嵌套的情况下使用继承,会覆盖掉该块下的所有内容,包括子块。
0 18:14:05 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat tem.j2 fixed configuration1 fixed configuration2 fixed configuration3 {% block bt1 %} Unfixed configuration1 in bt1 Unfixed configuration2 in bt1 {% block bt2 %} Unfixed configuration1 in bt2 Unfixed configuration2 in bt2 {% endblock bt2 %} {% endblock bt1 %} # endblock后的bt1可省略,这里是为了与bt2作区分,多个块存在的时候建议加上。 fixed configurationN 0 18:14:07 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat subtem.j2 {% extends 'tem.j2' %} {% block bt1 %} new configuration1 in bt1 new configuration2 in bt1 {% endblock bt1 %}
-
不修改主模板文件,只新增主模板文件中某个块的内容。
0 18:24:25 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat tem.j2 fixed configuration1 fixed configuration2 fixed configuration3 {% block bt1 %} Unfixed configuration1 in bt1 Unfixed configuration2 in bt1 {% block bt2 %} Unfixed configuration1 in bt2 Unfixed configuration2 in bt2 {% endblock bt2 %} {% endblock bt1 %} fixed configurationN 0 18:24:26 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat subtem.j2 {% extends 'tem.j2' %} {% block bt2 %} {{ super() -}} # 利用super()获取到父块中的所有内容,并新增下面两行内容。利用-取消自动换行(前面说过的)。 new configuration1 in bt2 new configuration2 in bt2 {% endblock bt2 %}
-
for循环+block:默认情况下,for循环内的块是无法获取for循环的变量的(会报变量未定义),想要获取到需要借助scoped修饰符。
0 18:39:52 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat test1.j2 something in test1.j2 ... {% for n in range(3) %} {% block bt1 scoped %} something in block bt1 ---- {{n}} {% endblock bt1 %} {% endfor %} something in test1.j2 ...
写作不易,转载请注明出处,谢谢~~