Ansible playbook常用到模板驱动jinja2
都是python编写的。Jinja2 需要至少 Python 2.4 版本来运行。
jinja2过滤器
Jinja2中的过滤器可以把一个模板表达式转换为另一个.Jinja2附带了很多这样的功能。
jinja2源码
https://github.com/pallets/jinja/blob/main/
基本 API 使用
>>> from jinja2 import Template
>>> template = Template('Hello {{ name }}!')
>>> template.render(name='John Doe')
u'Hello John Doe!'
通过创建一个 Template 的实例,你会得到一个新的模板对象,提供一 个名为 render() 的方法
该方法在有字典或关键字参数时调用 扩充模板。字典或关键字参数会被传递到模板,即模板“上下文”。
渲染一个html
from jinja2 import PackageLoader,Environment
env = Environment(loader=PackageLoader('python_project','templates')) # 创建一个包加载器对
#PackageLoader()的两个参数为:python包的名称,以及模板目录名称。
template = env.get_template('bast.html') # 获取一个模板文件
template.render(name='daxin',age=18) # 渲染
jinja2是如何直接使用过滤器? 只需要在变量后面使用管道(|)分割,多个过滤器可以链式调用,前一个过滤器的输出会作为后一个过滤器的输入。
{{ 'abc' | captialize }}
# Abc{{ 'abc' | upper }}
# ABC{{ 'hello world' | title }}
# Hello World{{ "hello world" | replace('world','daxin') | upper }}
# HELLO DAXIN{{ 18.18 | round | int }}
# 18
对列表和字典进行递归,生成模板
<ul>
{% for user in users %}
<li>{{ user.username|title }}</li>
{% endfor %}
</ul><dl>
{% for key, value in my_dict.iteritems() %}
<dt>{{ key }}</dt>
<dd>{{ value}}</dd>
{% endfor %}
</dl>
cat for-if.yml
- hosts: myhostsremote_user: rootvars:hosts:- {listen_port: 8080,web: nginx1,name: web1.fz.com}- {listen_port: 8081,web: nginx2,name: web2.fz.com}- {listen_port: 8082,web: nginx3}tasks:- name: for-iftemplate: src=for-if.j2 dest=/root/for-if
cat templates/for-if.j2
{% for host in hosts %}server{listen: {{host.listen_port}};{%if host.name is defined%}name: {{host.name}};{%endif%}web: {{host.web}};}{%endfor%}
#defined是找到的意思,也可以添加else
{% if variable is defined %}value of variable: {{ variable }}
{% else %}variable is not defined
{% endif %}
在vars.yml文件中定义变量
hi: hello
wd: world
编写playbook:
- hosts: myhostsremote_user: rootvars_files:- vars.ymltasks:- name: create filefile: name=/root/{{ hi }}-{{ wd }}.log state=touch
Ansible提供了notify指令和handlers功能。
如果在某个task中定义了notify指令,当Ansible在监控到该任务 changed=1时,会触发该notify指令所定义的handler,然后去执行handler。所谓handler,其实就是task
cat httpd.yml
---
- name: play1hosts: allremote_user: rootgather_facts: falsetasks:- name: install httpdyum: name=httpd state=installed- name: copy httpd configcopy: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/httpd.confnotify:- restart httpd- name: start httpdservice: name=httpd state=started enabled=truehandlers:- name: restart httpdservice: name=httpd state=restarted
#这里只要对httpd.conf配置文件作出了修改,修改后需要重启生效,在tasks中定义了restart httpd这个action,然后在handlers中引用上面tasks中定义的notify。
ansible实现循环
[root@ansible-test1 ansible]# cat while.ymlhosts: testhost
user: root
tasks:name: change mode for filesfile: path=/tmp/{{ item }} mode=600with_items:1.txt2.txt3.txt执行while.yml。
[root@ansible-test1 ansible]# ansible-playbook while.yml
#说明: with_items为循环的对象
ansible条件判断
when的值是一个条件表达式,如果条件判断成立,这个task就执行,如果判断不成立,则task不执行。
---
- hosts: mysql
- remote_user: roottasks:- name: "shutdown C6 systems"command: /sbin/shutdown -t nowwhen: (ansible_distribution == CentOS and ansible_distribution_major_version == "6") or(ansible_distribution == CentOS and ansible_distribution_major_version == "7")
role风格的入口
- hosts: 192.168.0.2remote_user: rootgather_facts: falseroles:- nginx- hosts: testremote_user: rootgather_facts: falseroles:- mysql
如果想要有区别的执行,而不是全部执行,可以加tag标记
role风格的排版
仿写playbook,可参照其他作者的该文章
https://www.bilibili.com/read/cv24358297/