一、jinja2简介解

  Jinja2是Python下一个被广泛应用的模版引擎,他的设计思想来源于Djanjo的模板引擎,并扩展了其语法和一系列强大的功能。ansible的模板配置文件就是用jinja2这种模板编程语言写的,其中jinja2使用字面量有如下形式

  1)字符串:使用单引号或双引号引起来的部分

  2)数字:支持整数,浮点数(小数)

  3)列表:和python里的列表一样,用中括号括起来,每个元素之间用逗号隔开,如[item1,item2,....]

  4)元组:和python里的元组一样,小括号括起来,每个元素之间用逗号隔开,如(item1,item2,....)

  5)字典:同python里的字典一样,大括号括起来,每个k/v(键值对)用逗号隔开,键和值用":"冒号隔开,如{key1:value1,key2:value2,....}

  6)布尔型:同其他语言布尔型一样,ture/false

  7)支持算数运算:+,-,*,/,//(整除,地板除),%(取模,取余数),**(幂运算)

  8)支持比较操作:==(比较两个值是否相等),!=(不等),>,>=(大于等于),<,<=(小于等于)

  9)支持逻辑运算:and(与),or(或),not(非)

  10)支持for(循环) ,if(判断),when(当某一条件满足才开始执行when所在的代码块,作用类似if)

  除此以外,jinja2还支持“test”测试语句,比如我们要判断某个变量是否定义,可以使用defined来判断,如 vars is defined ,如果vars定义则表达式返回true,相反返回false。类似的还有undefined(与defined相反),equalto(与“==”作用等效),even(判断对象是否是偶数),iterable(判断对象是否可迭代)

  二、jinja2语法

jinja2有如下语法:

  1)控制结构,它和我们写别的语言的控制结构类似,唯一不同的是它的for循环要用”{%%}“给括起来,且必须写在两个百分号之间,后面结束有一个{%endfor$}来表示for循环的结束,同样if语句也是,必须写在"{%%}" 两个百分号之间,后面结束也有个{%endif%}来表示if语句的结束,当然if语句支持elif ,else  这个同python里的if用法一样。

  2)变量引用,jinja2的变量引用同ansible的变量应用类似,都是用"{{}}" 双大括号来表示中间括起来的内容表示变量

  3)注释用"{#"开始,中间部分表示注释,以"#}"结束表示注释结束,支持多行注释和当行注释

示例:

  1)for循环使用

{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen }}
}
{% endfor %}

  说明:以上模板表示,从nginx_vhosts列表里去循环,nginx_vhosts里有几个元素,它将循环几次,每次循环取的值用vhost变量代替,它的用法类型shell里的for循环和python里的for循环

  2)if单分支选择使用

{% if vhost.server_name is defined %}
server_name {{ vhost.server_name }}
{% endif %}

  3)if多分支选择使用

{%if vhost.port is undefined %}
http_port=80
{%elif vhost.port == 81%}
http_port=81
{%else%}
http_port = 83
{%endif%}

  4)单行注释

{#% for i in list %#}

  5)多行注释

{#
{% for i in list %}
i+=i
{% endfor %}
#}

  三、playbook中使用模板

templates是ansible的一个模块,其功能是根据模板文件动态生成配置文件,templates文件必须存放于templates目录下,且命名为".j2"结尾,yaml/yml文件需要和templates目录平级,这样我们在yml文件中调用模板的时候,就不需要写模板文件的路径,否则需要描述模板文件的路径,因为template模块会自动去找templates目录下的模板文件。目录结构如下

.
├── temnginx.yml
└── templates
   └── nginx.conf.j2

示例:playbook中template变量替换

  利用tamplates同步nginx配置文件,其中修改nginx.conf.j2(worker_processes {{ ansible_processor_vcpus }};)指定其worker进程的个数由远程主机的cpu个数决定

[root@test ~]#ll
总用量 4
-rw-r--r-- 1 root root 212 11月 18 14:08 temnginx.yml
drwxr-xr-x 2 root root 27 11月 18 14:05 templates
[root@test ~]#tree
.
├── temnginx.yml
└── templates
└── nginx.conf.j2 1 directory, 2 files
[root@test ~]#head templates/nginx.conf.j2
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/ user nginx;
worker_processes {{ ansible_processor_vcpus }};
error_log /var/log/nginx/error.log;
pid /run/nginx.pid; # Load dynamic modules. See /usr/share/nginx/README.dynamic.
[root@test ~]#cat temnginx.yml
---
- hosts: websers
remote_user: root tasks:
- name: install nginx
yum: name=nginx
- name: template config to remote hosts
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf [root@test ~]#

  说明:以上playbook里是使用template模板去动态生成的配置文件,不是拷贝,拷贝是将文件原封不动的拷贝过去,还需要注意的是template模块不能在ad-hoc命令行里使用,只能在playbook里使用,且模板文件必须是".j2"结尾的

示例:playbook中template算数运算

还是以上的示例,我们可以这样写

vim nginx.conf.j2
worker_processes {{ ansible_processor_vcpus**2 }};

  说明:我们可以用ansible内置变量做算术运算后的值作为模板文件的值,在playbook中还是用template模块去调用就好了

示例:模板文件中 for循环的用法

[root@test ~]#tree
.
├── temnginx.yml
└── templates
└── nginx.conf.j2 1 directory, 2 files
[root@test ~]#cat templates/nginx.conf.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen }}
}
{% endfor %}
[root@test ~]#cat temnginx.yml
---
- hosts: websers
remote_user: root
vars:
nginx_vhosts:
- listen: 8080
tasks:
- name: install nginx
yum: name=nginx
- name: template config to remote hosts
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf [root@test ~]#  

生成结果:

[root@test ~]#ansible-playbook  temnginx.yml   

PLAY [websers] ******************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.128]
ok: [192.168.0.218] TASK [install nginx] ************************************************************************************************
changed: [192.168.0.128]
changed: [192.168.0.218] TASK [template config to remote hosts] ******************************************************************************
changed: [192.168.0.128]
changed: [192.168.0.218] PLAY RECAP **********************************************************************************************************
192.168.0.128 : ok=3 changed=2 unreachable=0 failed=0
192.168.0.218 : ok=3 changed=2 unreachable=0 failed=0 [root@test ~]#ansible websers -m shell -a 'cat /etc/nginx/nginx.conf'
192.168.0.128 | SUCCESS | rc=0 >>
server {
listen 8080
} 192.168.0.218 | SUCCESS | rc=0 >>
server {
listen 8080
} [root@test ~]#

  示例:模板文件中if的用法

[root@test ~]#tree
.
├── temnginx.yml
└── templates
└── nginx.conf.j2 1 directory, 2 files
[root@test ~]#cat temnginx.yml
---
- hosts: websers
remote_user: root
vars:
nginx_vhosts:
- web1:
listen: 8080
server_name: "web1.test.com"
root: "/var/www/nginx/web1/"
- web2:
listen: 8080
root: "/var/www/nginx/web2/"
- web3:
listen: 8080
server_name: "web2.test.com"
root: "var/www/nginx/web3/"
tasks:
- name: template config to remote hosts
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf [root@test ~]#cat templates/nginx.conf.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen }}
{% if vhost.server_name is defined %}
server_name {{ vhost.server_name }}
{% endif %}
root {{ vhost.root }}
}
{% endfor %}
[root@test ~]#

生成结果:

[root@test ~]#ansible-playbook temnginx.yml 

PLAY [websers] ******************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.128]
ok: [192.168.0.218] TASK [template config to remote hosts] ******************************************************************************
changed: [192.168.0.128]
changed: [192.168.0.218] PLAY RECAP **********************************************************************************************************
192.168.0.128 : ok=2 changed=1 unreachable=0 failed=0
192.168.0.218 : ok=2 changed=1 unreachable=0 failed=0 [root@test ~]#ansible websers -m shell -a 'cat /etc/nginx/nginx.conf'
192.168.0.128 | SUCCESS | rc=0 >>
server {
listen 8080
server_name web1.test.com
root /var/www/nginx/web1/
}
server {
listen 8080
root /var/www/nginx/web2/
}
server {
listen 8080
server_name web2.test.com
root var/www/nginx/web3/
} 192.168.0.218 | SUCCESS | rc=0 >>
server {
listen 8080
server_name web1.test.com
root /var/www/nginx/web1/
}
server {
listen 8080
root /var/www/nginx/web2/
}
server {
listen 8080
server_name web2.test.com
root var/www/nginx/web3/
} [root@test ~]#

  说明:可以看到第二个server里是没有server_name,因为定义的变量列表里web2没有定义server_name

  四、playbook中使用when条件测试

  条件测试:如果需要根据变量、facts或此前任务的执行结果来作为某task执行与否的前提时需要用到条件测试,通过when语句实现,在task中使用jinja2的语法格式,when语句支持jinja2表达式语法;

示例:

[root@test ~]#cat test.yml
---
- hosts: all
remote_user: root tasks:
- name: set hostname centos6
hostname: name=ansible_centos6
when: ansible_distribution_major_version == "6"
- name: set hostname centos7
hostname: name=ansible_centos7
when: ansible_distribution_major_version == "7"
[root@test ~]#ansible all -m shell -a 'hostname'
192.168.0.128 | SUCCESS | rc=0 >>
localhost 192.168.0.218 | SUCCESS | rc=0 >>
localhost.localdomain 192.168.0.217 | SUCCESS | rc=0 >>
centos7 [root@test ~]#ansible-playbook test.yml PLAY [all] ********************************************************************************************************** TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.128]
ok: [192.168.0.218]
ok: [192.168.0.217] TASK [set hostname centos6] *****************************************************************************************
skipping: [192.168.0.217]
changed: [192.168.0.218]
changed: [192.168.0.128] TASK [set hostname centos7] *****************************************************************************************
skipping: [192.168.0.128]
skipping: [192.168.0.218]
changed: [192.168.0.217] PLAY RECAP **********************************************************************************************************
192.168.0.128 : ok=2 changed=1 unreachable=0 failed=0
192.168.0.217 : ok=2 changed=1 unreachable=0 failed=0
192.168.0.218 : ok=2 changed=1 unreachable=0 failed=0 [root@test ~]#ansible all -m shell -a 'hostname'
192.168.0.128 | SUCCESS | rc=0 >>
ansible_centos6 192.168.0.218 | SUCCESS | rc=0 >>
ansible_centos6 192.168.0.217 | SUCCESS | rc=0 >>
ansible_centos7 [root@test ~]#

  说明:以上playbook利用when语句判断系统版本号,实现了通过不同的系统版本号,设置不同的主机名。

  五、playbook迭代with_items

  迭代:当有需要重复性执行的任务时,可使用迭代机制;对迭代项的引用,ansible有固定不变的变量,名为“item”;要在task中使用with_items给定要迭代的元素列表,列表格式可以为字符串、字典。

示例:批量创建用户

[root@test ~]#cat adduser.yml
---
- hosts: websers
remote_user: root tasks:
- name: add users
user: name={{ item }} state=present home=/home/{{ item }} groups=root,bin,wheel
with_items:
- user1
- user2
- user3
[root@test ~]#ansible-playbook adduser.yml PLAY [websers] ****************************************************************************************************** TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.128]
ok: [192.168.0.218] TASK [add users] ****************************************************************************************************
changed: [192.168.0.128] => (item=user1)
changed: [192.168.0.218] => (item=user1)
changed: [192.168.0.128] => (item=user2)
changed: [192.168.0.218] => (item=user2)
changed: [192.168.0.128] => (item=user3)
changed: [192.168.0.218] => (item=user3) PLAY RECAP **********************************************************************************************************
192.168.0.128 : ok=2 changed=1 unreachable=0 failed=0
192.168.0.218 : ok=2 changed=1 unreachable=0 failed=0 [root@test ~]#ansible websers -m shell -a 'tail -3 /etc/passwd'
192.168.0.128 | SUCCESS | rc=0 >>
user1:x:503:503::/home/user1:/bin/bash
user2:x:504:504::/home/user2:/bin/bash
user3:x:505:505::/home/user3:/bin/bash 192.168.0.218 | SUCCESS | rc=0 >>
user1:x:1213:1213::/home/user1:/bin/bash
user2:x:1214:1214::/home/user2:/bin/bash
user3:x:1215:1215::/home/user3:/bin/bash [root@test ~]#ansible websers -m shell -a 'id user1'
192.168.0.218 | SUCCESS | rc=0 >>
uid=1213(user1) gid=1213(user1) 组=1213(user1),0(root),1(bin),10(wheel) 192.168.0.128 | SUCCESS | rc=0 >>
uid=503(user1) gid=503(user1) 组=503(user1),0(root),1(bin),10(wheel) [root@test ~]# 

示例:迭代嵌套子变量

[root@test ~]#cat adduser2.yml
---
- hosts: websers
remote_user: root tasks:
- name: create groups
group: name={{ item }}
with_items:
- group1
- group2
- group3
- name: create users
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- {name: 'test1',group: 'group1'}
- {name: 'test2',group: 'group2'}
- {name: 'test3',group: 'group3'}
[root@test ~]#ansible-playbook adduser2.yml PLAY [websers] ****************************************************************************************************** TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.128]
ok: [192.168.0.218] TASK [create groups] ************************************************************************************************
changed: [192.168.0.128] => (item=group1)
changed: [192.168.0.218] => (item=group1)
changed: [192.168.0.128] => (item=group2)
changed: [192.168.0.218] => (item=group2)
changed: [192.168.0.128] => (item=group3)
changed: [192.168.0.218] => (item=group3) TASK [create users] *************************************************************************************************
changed: [192.168.0.128] => (item={u'group': u'group1', u'name': u'test1'})
changed: [192.168.0.218] => (item={u'group': u'group1', u'name': u'test1'})
changed: [192.168.0.128] => (item={u'group': u'group2', u'name': u'test2'})
changed: [192.168.0.218] => (item={u'group': u'group2', u'name': u'test2'})
changed: [192.168.0.128] => (item={u'group': u'group3', u'name': u'test3'})
changed: [192.168.0.218] => (item={u'group': u'group3', u'name': u'test3'}) PLAY RECAP **********************************************************************************************************
192.168.0.128 : ok=3 changed=2 unreachable=0 failed=0
192.168.0.218 : ok=3 changed=2 unreachable=0 failed=0 [root@test ~]#ansible websers -m shell -a 'tail -3 /etc/passwd'
192.168.0.128 | SUCCESS | rc=0 >>
test1:x:506:506::/home/test1:/bin/bash
test2:x:507:507::/home/test2:/bin/bash
test3:x:508:508::/home/test3:/bin/bash 192.168.0.218 | SUCCESS | rc=0 >>
test1:x:1216:1216::/home/test1:/bin/bash
test2:x:1217:1217::/home/test2:/bin/bash
test3:x:1218:1218::/home/test3:/bin/bash [root@test ~]#ansible websers -m shell -a 'id test1'
192.168.0.218 | SUCCESS | rc=0 >>
uid=1216(test1) gid=1216(group1) 组=1216(group1) 192.168.0.128 | SUCCESS | rc=0 >>
uid=506(test1) gid=506(group1) 组=506(group1) [root@test ~]#ansible websers -m shell -a 'id test2'
192.168.0.128 | SUCCESS | rc=0 >>
uid=507(test2) gid=507(group2) 组=507(group2) 192.168.0.218 | SUCCESS | rc=0 >>
uid=1217(test2) gid=1217(group2) 组=1217(group2) [root@test ~]#ansible websers -m shell -a 'id test3'
192.168.0.128 | SUCCESS | rc=0 >>
uid=508(test3) gid=508(group3) 组=508(group3) 192.168.0.218 | SUCCESS | rc=0 >>
uid=1218(test3) gid=1218(group3) 组=1218(group3) [root@test ~]#

  说明:以上playbook实现了对应用户创建时加入对应的组里

Ansible之templates模板的更多相关文章

  1. Templates 模板:

    Templates 模板: ########################温金 $template wj-flow01,"/data01/applog_backup/winfae_log/ ...

  2. python测试开发django-2.templates模板与html页

    前言 Django 中的视图的概念是一类具有相同功能和模板的网页的集合.通俗一点来说,就是你平常打开浏览器,看到浏览器窗口展示出来的页面内容,那就是视图.前面一章通过浏览器访问http://127.0 ...

  3. django templates模板

    Django templates模板 HTML代码可以被直接硬编码在views视图代码中,虽然这样很容易看出视图是怎么工作的,但直接将HTML硬编码到视图里却并不是一个好主意. 让我们来看一下为什么: ...

  4. python测试开发django-69.templates模板过滤器filter

    前言 templates 模板里面过滤器 filter 的作用是对变量的出来,比如小写转大写,替换一些特殊字符,对列表取值,排序等操作. 内置的过滤器有很多,本篇拿几个常用的过滤器做案例讲解下相关的功 ...

  5. python测试开发django-67.templates模板变量取值

    前言 django 的模板里面变量取值是通过句点语法来取值,就是一个点(.)符号.取值的对象也可以是字符串,int类型,list列表,字典键值对,也可以是一个类的实例对象. views视图 比如我在 ...

  6. 自动化运维工具-Ansible之6-Jinja2模板

    自动化运维工具-Ansible之6-Jinja2模板 目录 自动化运维工具-Ansible之6-Jinja2模板 Ansible Jinja2模板概述 Ansible Jinja2模板使用 Ansib ...

  7. Django web框架-----Django templates模板

    说明:mytestsite是django框架下的项目,quicktool是mytestsite项目中的应用 一般的变量之类的用 {{ }}(变量),功能类的比如循环.条件判断是用 {% %}(标签) ...

  8. 11、Django实战第11天:templates模板继承

    Django模板的继承,它首先定义一个整体的框架(父类),然后动态的部分(子类)只需要重写自己本身的代码就可以了. 1.在templates目录下创建base.html 2.把org-list.htm ...

  9. Django之templates模板

    模板渲染: 官方文档:https://docs.djangoproject.com/en/1.11/ref/templates/builtins/#std:templatetag-for 模板渲染两种 ...

随机推荐

  1. VMware workstation Windows 10虚拟机安装步骤

    1. 在首页点击创建新的虚拟机 2. 选择典型,下一步 3.选择稍后安装操做系统,下一步. 4. 选择第一个Microsoft Windows,版本选择如图. 5. 选择安装位置,我放在D盘. 7. ...

  2. 不该背的锅也要背,Gitee.com被停止域名解析

    1.Gitee.com被停止域名解析 今天下午发现码云打不开了,打开是这样的 350万的男性交友平台说挂就挂,简直惨无人道!目前已有超过 350 万的开发者选择码云,不为啥,,就冲这个私有.免费这两个 ...

  3. Ubuntu16.04换源

    换成国内最快的阿里云源 第一步:备份原来的源文件 cd /etc/apt/ 然后会显示下面的源文件sources.list 输入命令 sudo cp sources.list sources.list ...

  4. vi/vim编辑器使用方法详解

    vi编辑器是所有Unix及Linux系统下标准的编辑器,他就相当于windows系统中的记事本一样,它的强大不逊色于任何最新的文本编辑器.他是我们使用Linux系统不能缺少的工具.由于对Unix及li ...

  5. Cocos2d-x 学习笔记(9) Action 运行原理

    1. 从一个Action开始 1.1 创建 在Scene里写一个Sprite,并添加Action: Sprite *sp = Sprite::create("m1.png"); M ...

  6. opencv::霍夫圆变换

    霍夫圆检测原理 从平面坐标到极坐标转换三个参数 假设平面坐标的任意一个圆上的点,转换到极坐标中: 处有最大值,霍夫变换正是利用这个原理实现圆的检测. cv::HoughCircles 因为霍夫圆检测对 ...

  7. Ubuntu8.04::扩容(LVM)磁盘

    .扩容 sudo lvextend -l +%FREE /dev/mapper/ubuntu--vg-ubuntu--lv .重新计算磁盘大小 sudo resize2fs /dev/mapper/u ...

  8. 《Java并发编程实战》读书笔记-第4章 对象的组合

    设计线程安全的类 三个基本要素: 找出构成对象状态的所有变量 找出约束状态变量的不变性条件 建立对象状态的并发访问管理策略 实例封闭 将数据封装在对象内部,可以将数据的访问限制在对象的方法上,从而更容 ...

  9. Ubuntu 14.04风扇不停转,风扇狂转 的解决办法,亲测有效。

    Ubuntu 14.04风扇不停转,风扇狂转 的解决办法,亲测有效. 原文  http://ubuntuforums.org/showthread.php?t=2218367 楼主说:ubuntu 1 ...

  10. OptimalSolution(5)--数组和矩阵问题(2)2

    一.找到无序数组中最小的k个数 二.在数组中找到出现次数大于N/K的数 三.最长的可整合子数组的长度 四.不重复打印排序数组中相加和为给定值的所有二元组和三元组 五.未排序正数数组中累加和为给定值的最 ...