
templates是ansible的一個子產品,其功能是根據模闆檔案動态生成配置檔案,templates檔案必須存放于templates目錄下,且命名為".j2"結尾,yaml/yml檔案需要和templates目錄平級,這樣我們在yml檔案中調用模闆的時候,就不需要寫模闆檔案的路徑,否則需要描述模闆檔案的路徑,因為template子產品會自動去找templates目錄下的模闆檔案。目錄結構如下
一、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中使用模闆
.
├── 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實作了對應使用者建立時加入對應的組裡
作者:Linux-1874
出處:https://www.cnblogs.com/qiuhom-1874/
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利.