ansible jinja2 (python基础)
ansible调用”template”模块,对”模板文件”进行渲染,根据模板生成每个主机对应的配置文件,并将最终生成的配置文件拷贝到目标主机中。
一、jinja2 基础语法
{{ }} :用来装载表达式,比如变量、运算表达式、比较表达式等。
{% %} :用来装载控制语句,比如 if 控制结构,for循环控制结构。
{# #} :用来装载注释,模板文件被渲染后,注释不会包含在最终生成的文件中。
1、{{ }} 的使用
案例1
字符串、数值、列表、元组、字典、布尔值等数据类型均可在”{{ }}”使用,通常会通过变量将对应的数据传入,而不是将数据直接写在”{{ }}”中,即使直接将数据写在”{{ }}”中,也会配合其他表达式或者函数进行处理。
template文件以*.j2命名
cat var.j2 {{ teststr }} {{ testnum }} {{ testlist[1] }} {{ testlist1[1] }} {{ testdic['name'] }} {{ zjz | upper }}
yml文件
--- - hosts: ip remote_user: root gather_facts: no vars: teststr: 'tstr' testnum: 18 zjz: jingzhiz testlist: ['aA','bB','cC'] testlist1: - AA - BB - CC testdic: name: bob age: 18 tasks: - template: src: /root/ansible_work/var.j2 dest: /opt/test
渲染结果
cat /opt/test tstr 18 bB BB bob JINGZHIZ
案例2
做数字运算、布尔判断、大小比较,如
模版:
cat panduan.j2 jinja2 test {{ testvar1 is defined }} {{ testvar1 is undefined }} {{ '/opt' is exists }} {{ '/opt' is file }} {{ '/opt' is directory }}
执行语句
ansible 10.1.1.145 -m template -e "testvar1=1 testvar2=2" -a "src=panduan.j2 dest=/opt/test"
渲染结果
cat /opt/test jinja2 test True False True False True
案例3
lookup查找
模版文件
cat lookup.j2 jinja2 test {{ lookup('file','/root/ansible_work/testfile') }} {{ lookup('env','PATH') }} test jinja2
执行语句
ansible 10.1.1.145 -m template -a "src=lookup.j2 dest=/opt/test"
渲染效果
cat /opt/test jinja2 test testfissss in ansible These are for testing purposes only /usr/share/Modules/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin test jinja2
2、{% %}的使用
使用”{% %}”对控制语句进行包含,比如”if”控制语句、”for”循环控制语句等都需要包含在”{% %}”。
{% if 条件一 %} ... {% elif 条件N %} ... {% else %} ... {% endif %}
案例1
多条件语句判断
模版
cat if.j2 {% if 70 <= testnum <= 80 %} num == 70--80 {% elif testnum == 40 %} num == 40 {% elif testnum <= 60 %} num less than 60 {% else %} num 不是所需的数字 {% endif %}
执行yml
--- - hosts: 10.1.1.145 remote_user: root gather_facts: no tasks: - template: src: /root/ansible_work/if.j2 dest: /opt/test vars: testnum: 45
渲染效果
cat /opt/test num less than 60
案例2
三元运算
模版
cat if2.j2 jinja2 test {{ 'a' if 2>1 else 'b' }}
执行语句
ansible ip -m template -a "src=./if2.j2 dest=/opt/test"
渲染效果
cat /opt/test jinja2 test a
if表达式的含义为,如果2>1这个条件为真,则使用’a’,如果2>1这个条件不成立,则使用’b’,而2必定大于1,所以条件成立,最终使用’a’,在jinja2中,if表达式的语法如下:
<do something> if <something is true> else <do something else>
案例3
for循环
{% for 迭代变量 in 可迭代对象 %} {{ 迭代变量 }} {% endfor %}
执行语句
ansible ip -m template -a "src=./for.j2 dest=/opt/test"
渲染效果
cat /opt/test 3 1 7 8 2
去除自动换行写法
cat for1.j2 {% for i in [3,1,7,8,2] -%} {{ i }} {%- endfor %}
效果
cat /opt/test 31782
空白控制
默认配置中,模板引擎不会对空白做进一步修改,所以每个空白(空格、制表符、换行符 等等)都会原封不动返回。如果应用配置了 Jinja 的 trim_blocks ,模板标签后的 第一个换行符会被自动移除(像 PHP 中一样)。
此外,你也可以手动剥离模板中的空白。当你在块(比如一个 for 标签、一段注释或变 量表达式)的开始或结束放置一个减号( - ),可以移除块前或块后的空白:
jinja2 test {% for i in [3,1,7,8,2] -%} {{ i }}{{ ' ' }} {%- endfor %} {% for i in [3,1,7,8,2] -%} {{ i~' ' }} {%- endfor %}
效果
# cat test jinja2 test 3 1 7 8 2
循环操作字典
{% for key,val in {'name':'bob','age':18}.iteritems() %} {{ key ~ ':' ~ val }} {% endfor %}
在使用for循环时,有一些内置的特殊变量可以使用,比如,如果想要知道当前循环操作为整个循环的第几次操作,则可以借助”loop.index”特殊变量,示例如下:
# cat test.j2 jinja2 test {% for i in [3,1,7,8,2] %} {{ i ~ '----' ~ loop.index }} {% endfor %}
效果
cat /opt/test # cat test.j2 jinja2 test 3----1 1----2 7----3 8----4 2----5
除了内置特殊变量”loop.index”,还有一些其他的内置变量,它们的作用如下
loop.index 当前循环操作为整个循环的第几次循环,序号从1开始 loop.index0 当前循环操作为整个循环的第几次循环,序号从0开始 loop.revindex 当前循环操作距离整个循环结束还有几次,序号到1结束 loop.revindex0 当前循环操作距离整个循环结束还有几次,序号到0结束 loop.first 当操作可迭代对象中的第一个元素时,此变量的值为true loop.last 当操作可迭代对象中的最后一个元素时,此变量的值为true loop.length 可迭代对象的长度 loop.depth 当使用递归的循环时,当前迭代所在的递归中的层级,层级序号从1开始 loop.depth0 当使用递归的循环时,当前迭代所在的递归中的层级,层级序号从0开始 loop.cycle() 这是一个辅助函数,通过这个函数我们可以在指定的一些值中进行轮询取值,具体参考之后的示例
for 嵌套 if
{% for i in [7,1,5,3,9] if i>3 %} {{ i ~'----'~ loop.index }} {% endfor %} {% for i in [7,1,5,3,9] %} {% if i>3 %} {{ i ~'----'~ loop.index}} {% endif %} {% endfor %}
效果
# cat test 7----1 5----2 9----3 7----1 5----3 9----5
for循环中使用了if内联表达式时,还可以与else控制语句结合使用。没有if语句也能搭配使用else
{% for i in [7,1,5,3,9] if i>10 %} {{ i }} {%else%} no one is greater than 10 {% endfor %}
3、{% raw %}和{# #}的使用
如果有较多这样的符号都需要保持原样(不被jinja2解析),可以借助”{% raw %}”块,来实现刚才的需求。
# cat test.j2 {% raw %} {{ test }} {% test %} {# test #} {% if %} {% for %} {% endraw %}
二、 jinja的过滤器
1、官网链接
https://jinja.palletsprojects.com/en/3.1.x/templates/#filters https://jinja.palletsprojects.com/en/3.0.x/templates/#list-of-builtin-filters
2、50个 jinja过滤器
注意与ansible的过滤器进行区分
abs(): 返回一个数的绝对值 float(): 将输入转换为浮点数 lower(): 将字符串转为小写字母 round(): 对输入进行四舍五入 tojson(): 对输入进行JSON格式化 attr(): 获取对象的属性 forceescape(): 强制转义输入 map(): 对序列应用一个函数 safe(): 标记一个字符串为安全的,不进行转义 trim(): 去除字符串前后的空格 batch(): 将列表划分为等长度的小块 format(): 应用Python的字符串format操作 max(): 返回序列中的最大值 select(): 对序列应用测试函数并取得通过测试的元素 truncate(): 截断一个字符串到指定长度 capitalize(): 将字符串的首字母大写,其余字母小写 groupby(): 对序列按照指定属性进行分组 min(): 返回序列中的最小值 selectattr(): 对序列进行过滤,并返回指定属性为真的对象 unique(): 返回序列中的独特元素 center(): 将文本居中并使用指定字符进行填充 indent(): 缩进字符串的每一行 pprint(): 对输入进行美观打印 slice(): 将序列切分为指定数目的块 upper(): 将字符串转为大写字母 default(): 如果输入为undefined,使用默认值 int(): 将输入转换为整数 random(): 从序列中随机选择一个元素 sort(): 对序列进行排序 urlencode(): 对字符串进行URL编码 dictsort(): 对字典进行排序 join(): 将序列连接成一个字符串 reject(): 对序列应用测试函数并取得未通过测试的元素 string(): 将输入转换为字符串 urlize(): 将URLs和电子邮件地址转换为链接 escape(): 对输入进行转义 last(): 获取序列的最后一个元素 rejectattr(): 对序列进行过滤,并返回指定属性为假的对象 striptags(): 移除文本中的HTML标签 wordcount(): 计算字符串中的单词数量 filesizeformat(): 对文件大小进行格式化 length(): 对输入的长度进行计算 replace(): 将字符串中的某个值替换为另一个值 sum(): 计算序列中所有元素的和 wordwrap(): 将文本换行,以适应给定字符数的宽度 first(): 获取序列的第一个元素 list(): 将输入转换为列表 reverse(): 将序列反转 title(): 将字符串的每个词首字母大写,其余小写 xmlattr(): 将字典转换为XML属性字符串。
https://www.kancloud.cn/manual/jinja2/70455 jinja2的中文文档
ansible笔记(40):jinja2模板(三)-朱双印博客 (zsythink.net) 大佬的ansible专辑