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专辑

 

posted @ 2022-09-16 15:39  凡人半睁眼  阅读(300)  评论(0编辑  收藏  举报