一、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. 毕业生想学习web前端,应该怎么学才能最快找到工作?

    首先无论你要学习任何技能,必须有一个清晰的版图,什么是清晰的版图呢?首先了解你学的技术将来要从事什么工作,这个工作的条件是哪些? 然后你要有一个非常清晰的学习大纲,切记学习任何东西都要系统,不可胡乱的 ...

  2. ‎Cocos2d-x 学习笔记(3.3) Layer

    1.简介 Layer直接继承了Node.Layer类似Ps里图层的概念,也可以理解成一块透明玻璃.Scene类似Ps里的一张图像,也可以理解成堆放玻璃的箱子. Layer能接收触摸事件.键盘事件.加速 ...

  3. 解决连接oracle报错 尝试加载Oracle客户端库时引发BadImageFomatException。如果在安装64位Oracle客户端组件的情况下以32位模式运行,将出现此问题的报错。

    最近遇到一个.NET连接Oracle的一个错误,其主要原因是换了一台电脑,在新电脑上运行以前的项目出现了的一个错误,工作环境为vs2017+Oracle 64位,win10系统 这个错误头疼了一天,找 ...

  4. vue MD5 加密

    确保vue项目中有MD5的依赖,当然没有的可以安装crypto模块. npm安装: npm install --save crypto 在main.js文件中将md5引入,可以全局使用的 import ...

  5. C# 关于config文件中的usersettings

    在调整app.config的时候遇到了一点问题,把这个问题记录下来,可能我只是没有找到解决方案,问题本身也许并不复杂. 在VS中通过Properties中的Settings.settings来设置作用 ...

  6. 面试必问:ACID/CAP

    转载: https://www.jdon.com/artichect/acid-cap.html ACID和CAP的详尽比较 事务机制ACID和CAP理论是数据管理和分布式系统中两个重要的概念,很不巧 ...

  7. 从零开始把项目发布到maven仓库中心

    sonatype准备操作 注册账号 https://issues.sonatype.org 1. 密码符号规范,并且工记住 新建项目 1. group id 如果你有com域名的所有权可以直接使用,如 ...

  8. 关于ESET占用CPU严重 的解决方案||ESET CPU 100%||用迅雷时ESET占用CPU(6月22日再次更新)

    关于ESET占用CPU严重 的解决方案 本文根据原帖有适量删改. ESET 的杀毒软件历来以占用资源少,CPU消耗少著称,可是很多朋友(特别是中国大陆的朋友)反应ESS & EAV 间歇性占用 ...

  9. Leetcode Tags(1)Linked List

    1.知识点回顾 https://www.cnblogs.com/BigJunOba/p/9174206.html https://www.cnblogs.com/BigJunOba/p/9174217 ...

  10. python编译器的安装和pycharm的安装

    python编译器的安装 进入官网https://www.python.org/,根据提示安装 安装python编译器 pychram安装 下载地址: https://www.jetbrains.co ...