一、Jinja2介绍

Jinja2是基于python的模板引擎,功能比较类似于PHP的smarty,J2ee的Freemarker和velocity。它能完全支持unicode,并具有集成的沙箱执行环境,应用广泛。jinja2使用BSD授权

Jinja2的语法是由variables(变量)和statement(语句)组成,如下;

1、variables:可以输出数据

{{ my_variables }}

{{ some_dudes_name | capitalize }}

2、statements: 可以用来创建条件和循环等

1
2
3
4
5
6
7
8
9
if语句:
{% if my_conditional %} 
...
{% endif %}
for 语句:
{% for item in all_items %}
{{item}} 
……
{% endfor %}

从上面第二个variables的例子中可以看出,jinja2支持使用带过滤器的Unix型管道操作符,有很多的内置过滤器可供使用。我们可以仅仅用一堆简单if和for就可以建立几乎任何的常规配置文件,不过如果你有意更进一步,jinja2 documentation (http://jinja.pocoo.org/docs/dev/)包含了很多有趣的东西可供了解。我们可以看到ansible允许在模板中使用诸如绘制时间此类的一些额外的模板变量

第一个例子:引用变量

1
2
3
4
5
6
7
8
9
10
11
#cd roles/template/
.
├── meta
│   └── main.yml
├── tasks
│   ├── template.yml  
│   └── main.yml
├── templates
│   ├── order.j2
└── vars
    └── main.yml

总调度yml文件:

1
2
3
4
5
6
7
#cat templates.yml
---
- hosts: 10.0.90.27
  user: root
  gather_facts: false
  roles:
   - role: template

注意:这里 - role: template 和 - template 是一样的!

其他yml文件,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#cat tasks/main.yml
- include: template.yml
#cat tasks/template.yml
- name: create {{ PROJECT }} directory
  file: dest=/data/{{ PROJECT }} state=directory
- name: template transfor java dir
  template: src=order.j2 dest=/data/{{ PROJECT }}/order.conf
#cat templates/order.j2
project: {{ PROJECT }}
switch: {{ SWITCH }}
dbport: {{ DBPORT }}
#cat vars/main.yml
PROJECT: "JAVA"
SWITCH: "ON"
DBPORT: "8080"
测试:
# ansible-playbook templates.yml --syntax-check
playbook: templates.yml
执行:
# ansible-playbook templates.yml 
PLAY [10.0.90.27] **************************************************************
TASK [template : include] ***************************************************
included: /etc/ansible/roles/template/tasks/template.yml for 10.0.90.27
TASK [template : create JAVA directory] *************************************
changed: [10.0.90.27]
TASK [template : template transfor java dir] ********************************
changed: [10.0.90.27]
PLAY RECAP *********************************************************************
10.0.90.27                 : ok=3    changed=2    unreachable=0    failed=0   
到10.0.90.27查看结果
#cat /data/JAVA/order.conf
project: JAVA
switch: ON
dbport: 8080

第二个例子:for 语句

为远程主机生成服务器列表,加入该列表从192.168.13.201 web01.test.com 到192.168.13.211 web11.test.com 结束,如果手动添加就很不科学了,这里需要使用jinja2语法的for循环通过模板批量生成对应的配置文件,如下:

ansible目录结构:

1
2
3
4
5
6
7
8
9
10
11
#cd /etc/ansible/roles/test_hosts
.
├── meta
│   └── main.yml
├── tasks
│   ├── file1.yml
│   └── main.yml
├── templates
│   └── test1.j2
└── vars
    └── main.yml

各个目录下yml文件内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
# cat tasks/file1.yml 
- name: ansible jinja2 template for hosts config
  template: src=test1.j2 dest=/etc/httpd/conf/httpd.conf.test
# cat tasks/main.yml 
- include: file1.yml
# cat templates/test1.j2 
{% for id in range(201,212) %}
192.168.13.{{ id }} web{{ "%03d" |format(id-200) }}.test.com
{% endfor %}
解释:
{{ id }} 提取for循环中对应的变量id
"%02d"   调用的是python内置的字符串格式化输出(%d格式化整数)因为是01,02这种格式,所以是保留2位,故用02
然后将结果通过管道符 “|” 传递给format 函数做二次处理。

执行结果:

1
2
3
4
5
6
7
8
9
10
11
12
#cat httpd.conf.test
192.168.13.201 web01.test.com
192.168.13.202 web02.test.com
192.168.13.203 web03.test.com
192.168.13.204 web04.test.com
192.168.13.205 web05.test.com
192.168.13.206 web06.test.com
192.168.13.207 web07.test.com
192.168.13.208 web08.test.com
192.168.13.209 web09.test.com
192.168.13.210 web10.test.com
192.168.13.211 web11.test.com

第三个例子:if语句

说明:如果定义端口号,就绑定定义的端口号,如果不定义端口号,就绑定默认端口号

1
2
3
4
5
6
7
8
9
10
11
ansible目录结果
#cd /etc/ansible/roles/mysql_cnf
#tree
.
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
├── templates
│   └── test3.j2
└── vars

主要的yml文件是templates目录下面的test3.j2

1
2
3
4
5
6
# cat templates/test3.j2 
{% if PORT %}
bind_address=10.0.90.27:{{ PORT }}
{% else %}
bind_address=10.0.90.27:3306
{% endif %}

playbook主文件

1
2
3
4
5
6
7
8
9
10
# cat jinj2_test.yml 
---
- hosts: 10.0.90.27
  user: root
  gather_facts: false
  vars:
    PORT: 3136
  tasks:
    - name: copy file to client
      template: src=/etc/ansible/roles/mysql_cnf/templates/test3.j2 dest=/root/my.cnf

执行:

1
2
3
4
5
6
# ansible-playbook jinj2_test.yml
PLAY [10.0.90.27] **************************************************************
TASK [copy file to client] *****************************************************
changed: [10.0.90.27]
PLAY RECAP *********************************************************************
10.0.90.27                 : ok=1    changed=1    unreachable=0    failed=0

查看

1
2
# cat my.cnf 
bind_address=10.0.90.27:3136

如果将vars变量去掉,执行结果:

1
2
3
4
5
6
7
8
9
10
# cat jinj2_test.yml 
---
- hosts: 10.0.90.27
  user: root
  gather_facts: false
  vars:
    PORT: false
  tasks:
    - name: copy file to client
      template: src=/etc/ansible/roles/mysql_cnf/templates/test3.j2 dest=/root/my.cnf

查看:

1
2
# cat my.cnf 
bind_address=10.0.90.27:3306

3、Jinja default()设定

精通程序编码的朋友皆知,default()默认值的设定有助于程序的健壮性和简洁性。所幸Jinja也支持该功能,上面的例子中生成Mysql配置文件中的端口定义,如果指定则PORT=3136,否则PORT=3306,我们将该案例改造为使用default()试试

编辑/etc/ansible/roles/mysql_cnf/templates/test3.j2内容如下,这种方法更简介。

bind_address=10.0.90.27:{{ PORT | default(3306) }}

二、ansible使用jiaja2生成apache多主机配置

1、创建目录,创建好之后如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#cd /etc/ansible/roles/apache_conf
# tree ./
./
├── meta
│   └── main.yml
├── tasks
│   ├── file.yml
│   └── main.yml
├── templates
│   └── apache.config.j2
└── vars
    └── main.yml
 
4 directories, 5 files

2、创建tasks调度文件,如下:

1
2
3
4
5
#cat file.yml 
- name: ansible jinja2 template for apache config
  template: src=apache.config.j2 dest=/etc/httpd/conf/httpd.conf.template
#cat main.yml 
- include: file.yml

3、创建apache的jinja2模板文件,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#cat apache.config.j2 
NameVirtualHost *:80
{% for vhost in apache_vhost %}
<VirtualHost *:80>
ServerName {{ vhost.servername }}
DocumentRoot {{ vhost.documentroot }}
{% if vhost.serveradmin is defined %}
ServerAdmin {{ vhost.serveradmin }}
{% endif %}
<Directory "{{ vhost.documentroot }}">
AllowOverride All
Options -Indexes FollowSymLinks
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
{% endfor %}

4、创建变量,如下:

1
2
3
4
#cat vars/main.yml
apache_vhost:
- {servername: "apache.test1.com", documentroot: "/data/test1/"}
- {servername: "apache.test2.com", documentroot: "/data/test2/"}

5、创建总调度yml文件,如下:

1
2
3
4
5
6
7
#cat /etc/ansible/apache_test.yml 
---
- hosts: 10.0.90.27
  user: root
  gather_facts: no
  roles:
   - { role: apache_conf }

6、测试:

1
2
3
#ansible-playbook apache_test.yml --syntax-check
 
playbook: apache_test.yml

7、执行测试

1
2
3
4
5
6
7
8
#ansible-playbook apache_test.yml 
PLAY [10.0.90.27] **************************************************************
TASK [apache_conf : include] ***************************************************
included: /etc/ansible/roles/apache_conf/tasks/file.yml for 10.0.90.27
TASK [apache_conf : ansible jinja2 template for apache config] *****************
changed: [10.0.90.27]
PLAY RECAP *********************************************************************
10.0.90.27                 : ok=2    changed=1    unreachable=0    failed=0

8、到客户端查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#cat httpd.conf.template 
NameVirtualHost *:80
<VirtualHost *:80>
ServerName apache.test1.com
DocumentRoot /data/test1/
<Directory "/data/test1/">
AllowOverride All
Options -Indexes FollowSymLinks
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerName apache.test2.com
DocumentRoot /data/test2/
<Directory "/data/test2/">
AllowOverride All
Options -Indexes FollowSymLinks
Order allow,deny
Allow from all
</Directory>
</VirtualHost>

三、ansible使用jiaja2生成nginx一个模板多种不同配置

说明:为2台Nginx Proxy,1台Nginx Web通过一套模板生成对应的配置

1、ansible目录结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
# cd roles/nginx_conf/
#tree
.
├── files
├── meta
│   └── main.yml
├── tasks
│   ├── file.yml
│   └── main.yml
├── templates
│   └── nginx.conf.j2
└── vars
    └── main.yml

2、tasks目录下文件内容:

1
2
3
4
5
#cat tasks/file.yml 
- name: nginx.j2 template transfer example 
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf.template
#cat tasks/main.yml 
- include: file.yml

3、nginx模板文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#cat templates/nginx.conf.j2 
{% if nginx_use_proxy %}
{% for proxy in nginx_proxies %}
upstream {{ proxy.name }}
   #server 127.0.0.1:{{ proxy.port }};
   server {{ ansible_eth0.ipv4.address }}:{{ proxy.port }};
}
{% endfor %}
{% endif%}
server {
    listen 80;
    servername {{ nginx_server_name }};
    access_log off;
    error_log /etc/nginx/nginx_error.log;
    rewrite ^ https://$server_name$request_uri? permanent;
}
server {
    listen 443 ssl;
    server_name {{ nginx_server_name }};
    ssl_certificate /etc/nginx/ssl/{{ nginx_ssl_cert_name }};
    ssl_certificate_key /etc/nginx/ssl/{{ nginx_ssl_cert_key }};
    root {{ nginx_web_root }};
    index index.html index.html;
{% if nginx_use_auth %}
   auth_basic  "Restricted";
   auth_basic_user_file /etc/nginx/{{ project_name }}.htpasswd;
{% endif %}
{% if nginx_use_proxy %}
{% for proxy in nginx_proxies %}
   location {{ proxy.location }} {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-Proto http;
      proxy_set_header X-Url-Scheme $scheme;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-NginX-Proxy true;
      proxy_redirect off;
      proxy_pass http://{{ proxy.name }};
      break;
}
{% endfor %}
{% endif %}
{% if nginx_server_static %}
   location / {
       try_files $url $url/ =404;
}
{% endif %}
}

4、ansible变量文件

1
2
3
4
5
6
7
8
9
10
cat vars/main.yml 
nginx_server_name: www.testnginx.com
nginx_web_root: /data/html/
nginx_proxies:
- name: suspicious
  location: /
  port: 1234
- name: suspicious-api
  location: /api
  port: 4567

ansible主playbook文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#cat nginx_test.yml 
##The first roles
- name: Nginx Proxy Server's Config Dynamic Create
  hosts: "10.0.90.25:10.0.90.26"
  remote_user: root
  vars:
    nginx_use_proxy: true
    nginx_ssl_cert_name: ifa.crt
    nginx_ssl_cert_key: ifa.key
    nginx_use_auth: true
    project_name: suspicious
    nginx_server_static: true
  gather_facts: true
  roles:
     -  role: nginx_conf
##The second roles
- name: Nginx WebServer's Config Dynamic Create
  hosts: 10.0.90.27
  remote_user: root
  vars:
    nginx_use_proxy: false
    nginx_ssl_cert_name: ifa.crt
    nginx_ssl_cert_key: ifa.crt
    nginx_use_auth: false
    project_name: suspicious
    nginx_server_static: false
  gather_facts: false
  roles:
     -  role: nginx_conf

5、测试并执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#ansible-playbook nginx_test.yml --syntax-check
playbook: nginx_test.yml
执行:
# ansible-playbook nginx_test.yml
PLAY [Nginx Proxy Server's Config Dynamic Create] ******************************
 
TASK [setup] *******************************************************************
ok: [10.0.90.25]
ok: [10.0.90.26]
 
TASK [nginx_conf : include] ****************************************************
included: /etc/ansible/roles/nginx_conf/tasks/file.yml for 10.0.90.25, 10.0.90.26
 
TASK [nginx_conf : nginx.j2 template transfer example] *************************
changed: [10.0.90.26]
changed: [10.0.90.25]
 
PLAY [Nginx WebServer's Config Dynamic Create] *********************************
 
TASK [nginx_conf : include] ****************************************************
included: /etc/ansible/roles/nginx_conf/tasks/file.yml for 10.0.90.27
 
TASK [nginx_conf : nginx.j2 template transfer example] *************************
changed: [10.0.90.27]
 
PLAY RECAP *********************************************************************
10.0.90.25                 : ok=3    changed=1    unreachable=0    failed=0   
10.0.90.26                 : ok=3    changed=1    unreachable=0    failed=0   
10.0.90.27                 : ok=2    changed=1    unreachable=0    failed=0

6、查看检测执行结果

到Nginx Proxy 服务器查看配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#cat nginx.conf.template 
upstream suspicious
   #server 127.0.0.1:1234;
   server 10.0.90.26:1234;
}
upstream suspicious-api
   #server 127.0.0.1:4567;
   server 10.0.90.26:4567;
}
server {
    listen 80;
    servername www.testnginx.com;
    access_log off;
    error_log /etc/nginx/nginx_error.log;
    rewrite ^ https://$server_name$request_uri? permanent;
}
server {
    listen 443 ssl;
    server_name www.testnginx.com;
    ssl_certificate /etc/nginx/ssl/ifa.crt;
    ssl_certificate_key /etc/nginx/ssl/ifa.key;
    root /data/html/;
    index index.html index.html;
   auth_basic  "Restricted";
   auth_basic_user_file /etc/nginx/suspicious.htpasswd;
   location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-Proto http;
      proxy_set_header X-Url-Scheme $scheme;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-NginX-Proxy true;
      proxy_redirect off;
      proxy_pass http://suspicious;
      break;
}
   location /api {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-Proto http;
      proxy_set_header X-Url-Scheme $scheme;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-NginX-Proxy true;
      proxy_redirect off;
      proxy_pass http://suspicious-api;
      break;
}
   location / {
       try_files $url $url/ =404;
}
}

到Nginx Web 服务器上查看配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#cat nginx.conf.template 
server {
    listen 80;
    servername www.testnginx.com;
    access_log off;
    error_log /etc/nginx/nginx_error.log;
    rewrite ^ https://$server_name$request_uri? permanent;
}
server {
    listen 443 ssl;
    server_name www.testnginx.com;
    ssl_certificate /etc/nginx/ssl/ifa.crt;
    ssl_certificate_key /etc/nginx/ssl/ifa.crt;
    root /data/html/;
    index index.html index.html;
}

到这里,就结束了。用同样的模板通过简单的if和变量设置就可以完成不同类型主机的Nginx conf配置,所以一方面在了解Ansible强大的模板功能的同时,也需要看到模板质量的重要性。

ansible使用jinja2管理配置文件以及jinja2语法简介的更多相关文章

  1. Ansible 小手册系列 十三(Jinja2)

    用于playbook中的jinja 2过滤器 更改数据格式,其结果是字符串 {{ some_variable | to_json }} {{ some_variable | to_yaml }} 对于 ...

  2. Linux centosVMware 自动化运维Ansible介绍、Ansible安装、远程执行命令、拷贝文件或者目录、远程执行脚本、管理任务计划、安装rpm包/管理服务、 playbook的使用、 playbook中的循环、 playbook中的条件判断、 playbook中的handlers、playbook实战-nginx安装、管理配置文件

    一.Ansible介绍 不需要安装客户端,通过sshd去通信 基于模块工作,模块可以由任何语言开发 不仅支持命令行使用模块,也支持编写yaml格式的playbook,易于编写和阅读 安装十分简单,ce ...

  3. Ansible批量自动化管理工具

    一,工具与环境介绍 1.1 ansible简介 批量管理服务器的工具 无需部署agent,通过ssh进行管理 流行的自动化运维工具:https://github.com/ansible/ansible ...

  4. Ansible批量自动化管理工具(二)

    Ansible批量自动化管理工具(二) 链接:https://pan.baidu.com/s/1A3Iq3gGkGS27L_Gt37_I0g 提取码:ncy2 复制这段内容后打开百度网盘手机App,操 ...

  5. Ansible批量自动化管理工具 roles标准化

    批量管理服务器的工具,无需部署代理,通过ssh进行管理,是python写的 ansible 常用模块 : (1)shell命令模块执行命令 (2)copy模块批量下发文件或文件夹 (3)script模 ...

  6. Linux 运维工作中的经典应用ansible(批量管理)Docker容器技术(环境的快速搭建)

    一 Ansible自动化运维工具 Python 在运维工作中的经典应用 ansible(批量管理操作) .安装ansible(需要bese epel 2种源) wget -O /etc/yum.rep ...

  7. Ansible的Inventory管理

    Ansible将可管理的服务器集合成为Inventory,Inventory的管理便是服务器的管理. hosts文件的位置: /etc/ansible/hosts 在命令行通过-i参数指定 通过/et ...

  8. spring 学习(二):spring bean 管理--配置文件和注解混合使用

    spring 学习(二)spring bean 管理--配置文件和注解混合使用 相似的,创建 maven 工程,配置pom.xml 文件,具体可以参考上一篇博文: sprint 学习(一) 然后我们在 ...

  9. 利用泛型和反射,管理配置文件,把Model转换成数据行,并把数据行转换成Model

    利用泛型和反射,管理配置文件,把Model转换成数据行,并把数据行转换成Model   使用场景:网站配置项目,为了便于管理,网站有几个Model类来管理配置文件, 比如ConfigWebsiteMo ...

随机推荐

  1. ios集合

    Foundation framework中用于收集cocoa对象(NSObject对象)的三种集合分别是: NSArray 用于对象有序集合(数组) NSSet 用于对象无序集合 (集合) NSDic ...

  2. SQL 2005批量插入数据的二种方法

    SQL 2005批量插入数据的二种方法 Posted on 2010-07-22 18:13 moss_tan_jun 阅读(2635) 评论(2) 编辑 收藏 在SQL Server 中插入一条数据 ...

  3. 第二周 Leetcode 493. Reverse Pairs(HARD)

    leetcode 493跟经典的逆序对问题没有什么区别, 首先考虑对数组前半部和后半部求逆序对数,若能保证两段数组都有序,则显然可以在线性时间内求出对数. 所以我们采用归并排序的方法,一方面让数组有序 ...

  4. Windows7安装SQLServer 2008图解

    Windows7安装SQL Server 2008图解        这几天因为需要,一直想安装SQL Server 2008来作为Web后台的数据库进行些实验,但总是没有时间,今天终于有时间了,便安 ...

  5. codevs1993 草地排水(最大流)

    1993 草地排水 USACO  时间限制: 2 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond   题目描述 Description 在农夫约翰的农场上,每逢下雨,Bes ...

  6. 数值分析常见算法C++实现

    1.1-有效数字丢失现象观察 #include<bits./stdc++.h> using namespace std; double f1(double x) { )-sqrt(x)); ...

  7. Gym - 101982B 2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) B. Coprime Integers Mobius+容斥 ab间gcd(x,y)=1的对数

    题面 题意:给你 abcd(1e7),求a<=x<=b,c<=y<=d的,gcd(x,y)=1的数量 题解:经典题目,求从1的到n中选x,从1到m中选y的,gcd(x,y)=k ...

  8. JavaScript中的substr和Java中的substring

    JavaScript::substr(index, length)从下标开始截取多少位,如果length为空,则截取到最后,-1倒数第一位,-2倒数第二位.... Java:substring(sta ...

  9. 题解报告:hdu 1233 还是畅通工程

    Problem Description 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能 ...

  10. hcode视频教程中心(学习h5和hbuilder等)

    网站: http://www.hcoder.net/course