文章目錄
Ansible 常用Filter
Ansible中的過濾器來自Jinja2,用於在模板表達式中轉換數據。在寫playbook的時候,偶爾需要對變量進行處理,比如在一段json文件中查找某些值進行循環,又比如獲取了一段地址但是需要對它進行切分取basename,又比如直接從對一段url進行切分處理,等等等等,在Ansible內部實現了許多Filter對上述的這些場景都提供了比較健全的Filter,這裏列出一些常用的Filter,更全面的可以查看ansible的官方文檔,和jinja2的文檔,地址都已在參考文檔章節中給出,
示例json文件
// 示例字符串
// $ cat domain_definition.json
{
"domain": {
"cluster": [
{
"name": "cluster1"
},
{
"name": "cluster2"
}
],
"server": [
{
"name": "server11",
"cluster": "cluster1",
"port": "8080"
},
{
"name": "server12",
"cluster": "cluster1",
"port": "8090"
},
{
"name": "server21",
"cluster": "cluster2",
"port": "9080"
},
{
"name": "server22",
"cluster": "cluster2",
"port": "9090"
}
],
"library": [
{
"name": "lib1",
"target": "cluster1"
},
{
"name": "lib2",
"target": "cluster2"
}
]
}
}
from_json
from_json filter
從json格式變量中加載成字典變量
# 查看playbook內容,從加載json文件
$ cat from_json.yml
- hosts: 192.168.240.33
gather_facts: no # 本次playbook 不收集fact信息
tasks:
- name: from_json filter test
debug:
var: domain_definition
vars:
domain_definition: "{{ lookup('file','/home/ansible/ADT/domain_definition.json') | from_json }}"
# 執行
$ ansible-playbook from_json.yml
PLAY [192.168.240.33] ***********************************************************************************************************************************************
TASK [from_json filter test] ****************************************************************************************************************************************
ok: [192.168.240.33] => {
"domain_definition": {
"domain": {
"cluster": [
{
"name": "cluster1"
},
{
"name": "cluster2"
}
],
"library": [
{
"name": "lib1",
"target": "cluster1"
},
{
"name": "lib2",
"target": "cluster2"
}
],
"server": [
{
"cluster": "cluster1",
"name": "server11",
"port": "8080"
},
{
"cluster": "cluster1",
"name": "server12",
"port": "8090"
},
{
"cluster": "cluster2",
"name": "server21",
"port": "9080"
},
{
"cluster": "cluster2",
"name": "server22",
"port": "9090"
}
]
}
}
}
PLAY RECAP **********************************************************************************************************************************************************
192.168.240.33 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
json query filter
json查詢過濾器,測試的playbook如下,#註釋部分表示對應task的輸出信息
$ cat json_query.yml
---
- hosts: 192.168.240.33
gather_facts: no
vars:
domain_definition: "{{ lookup('file','/home/ansible/ADT/domain_definition.json') | from_json }}"
tasks:
- name: "Display all cluster names"
debug:
var: item
loop: "{{ domain_definition | json_query('domain.cluster[*].name') }}"
#TASK [Display all cluster names] ************************************************************************************************************************************
#ok: [192.168.240.33] => (item=cluster1) => {
# "ansible_loop_var": "item",
# "item": "cluster1"
#}
#ok: [192.168.240.33] => (item=cluster2) => {
# "ansible_loop_var": "item",
# "item": "cluster2"
#}
- name: "Display all server names"
debug:
var: item
loop: "{{ domain_definition | json_query('domain.server[*].name') }}"
#TASK [Display all server names] *************************************************************************************************************************************
#ok: [192.168.240.33] => (item=server11) => {
# "ansible_loop_var": "item",
# "item": "server11"
#}
#ok: [192.168.240.33] => (item=server12) => {
# "ansible_loop_var": "item",
# "item": "server12"
#}
#ok: [192.168.240.33] => (item=server21) => {
# "ansible_loop_var": "item",
# "item": "server21"
#}
#ok: [192.168.240.33] => (item=server22) => {
# "ansible_loop_var": "item",
# "item": "server22"
#}
#
- name: "Display all server ports and names from cluster1"
debug:
var: item
loop: "{{ domain_definition | json_query(server_name_cluster1_query) }}"
vars:
server_name_cluster1_query: "domain.server[?cluster=='cluster1'].port"
#TASK [Display all server ports and names from cluster1] *************************************************************************************************************
#ok: [192.168.240.33] => (item=8080) => {
# "ansible_loop_var": "item",
# "item": "8080"
#}
#ok: [192.168.240.33] => (item=8090) => {
# "ansible_loop_var": "item",
# "item": "8090"
#}
- name: "Display all ports from cluster1 as a string"
debug:
msg: "{{ domain_definition | json_query('domain.server[?cluster==`cluster1`].port') | join(', ') }}"
#TASK [Display all ports from cluster1 as a string] ******************************************************************************************************************
#ok: [192.168.240.33] => {
# "msg": "8080, 8090"
#}
- name: "Display all server ports and names from cluster1"
debug:
var: item
loop: "{{ domain_definition | json_query(server_name_cluster1_query) }}"
vars:
server_name_cluster1_query: "domain.server[?cluster=='cluster2'].{name: name, port: port}"
#TASK [Display all server ports and names from cluster1] *************************************************************************************************************
#ok: [192.168.240.33] => (item={u'name': u'server21', u'port': u'9080'}) => {
# "ansible_loop_var": "item",
# "item": {
# "name": "server21",
# "port": "9080"
# }
#}
#ok: [192.168.240.33] => (item={u'name': u'server22', u'port': u'9090'}) => {
# "ansible_loop_var": "item",
# "item": {
# "name": "server22",
# "port": "9090"
# }
#}
list filters
列表過濾器
# 求列表最小值
$ ansible 192.168.240.33 -m debug -a 'msg="{{ [1,2,3,4] | min }}"'
192.168.240.33 | SUCCESS => {
"msg": "1"
}
# 求列表最大值
$ ansible 192.168.240.33 -m debug -a 'msg="{{ [1,2,3,4] | max }}"'
192.168.240.33 | SUCCESS => {
"msg": "4"
}
# 將列表展開,這個在某些場景下非常有用
$ ansible 192.168.240.33 -m debug -a 'msg="{{ [1,2,[3,4]] | flatten }}"'
192.168.240.33 | SUCCESS => {
"msg": [
1,
2,
3,
4
]
}
# 也可以指定展開多少層
$ ansible 192.168.240.33 -m debug -a 'msg="{{ [1,2,[3,[4]]] | flatten(levels=1) }}"'
192.168.240.33 | SUCCESS => {
"msg": [
1,
2,
3,
[
4
]
]
}
# 對列表去重
$ ansible 192.168.240.33 -m debug -a 'msg="{{ [1,2,3,3,3,4,5,5]| unique }}"'
192.168.240.33 | SUCCESS => {
"msg": [
1,
2,
3,
4,
5
]
}
# 對比兩個列表去除不同的值
$ ansible 192.168.240.33 -m debug -a 'msg="{{ [1,2,3,3,3,4,5,5]| difference([1,2,3]) }}"'
192.168.240.33 | SUCCESS => {
"msg": [
4,
5
]
}
random number filter
隨機數生成器
# 60以內隨機生成一個整數
$ ansible 192.168.240.33 -m debug -a 'msg="{{ 60 | random }}"'
192.168.240.33 | SUCCESS => {
"msg": "1"
}
$ ansible 192.168.240.33 -m debug -a 'msg="{{ 60 | random }}"'
192.168.240.33 | SUCCESS => {
"msg": "21"
}
# 從列表中隨機選擇一個數字
$ ansible 192.168.240.33 -m debug -a 'msg="{{ [1,2,4,5] | random }}"'
192.168.240.33 | SUCCESS => {
"msg": "5"
}
$ ansible 192.168.240.33 -m debug -a 'msg="{{ [1,2,4,5] | random }}"'
192.168.240.33 | SUCCESS => {
"msg": "2"
}
IP address filter
ip地址過濾器,此filter需要安裝netaddr模塊,安裝方法如下pip install netaddr
,否則會報錯,報錯信息如下:
fatal: [192.168.240.33]: FAILED! => {"msg": "The ipaddr filter requires python's netaddr be installed on the ansible controller"}
示例:
{{ '192.0.2.1/24' | ipaddr('address') }}
Hashing filters
hash過濾器
# 示例playbook
$ cat hash_filter.yml
---
- hosts: 192.168.240.33
gather_facts: no
vars:
str: 'string'
tasks:
- debug:
msg: "{{ str | hash('md5') }}"
# 執行結果
$ ansible-playbook hash_filter.yml
PLAY [192.168.240.33] *******************************************************************************************************************
TASK [debug] ****************************************************************************************************************************
ok: [192.168.240.33] => {
"msg": "b45cffe084dd3d20d928bee85e7b0f21"
}
PLAY RECAP ******************************************************************************************************************************
192.168.240.33 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
URL Split Filter
url切分過濾器
$ cat url_split_filter.yml
---
- hosts: 192.168.240.33
gather_facts: no
vars:
url: 'http://user:[email protected]:9000/dir/index.html?query=term#fragment'
tasks:
- name: "get url hostname"
debug:
msg: "{{ url | urlsplit('hostname') }}"
# ==> "msg": "www.acme.com"
- name: "get url netloc"
debug:
msg: "{{ url | urlsplit('netloc') }}"
# ==> "user:[email protected]:9000"
- name: "get url path"
debug:
msg: "{{ url | urlsplit('path') }}"
# ==> "msg": "/dir/index.html"
- name: "get url port"
debug:
msg: "{{ url | urlsplit('port') }}"
# ==> "msg": "9000"
- name: "get url scheme"
debug:
msg: "{{ url | urlsplit('scheme') }}"
# ==> "msg": "http"
- name: "get url query"
debug:
msg: "{{ url | urlsplit('query') }}"
# ==> "msg": "query=term"
path Filter
路徑filter
# 獲取basename
$ ansible 192.168.240.33 -m debug -a 'msg={{ "/home/archforce/ADT/hosts.ini" | basename }}'
192.168.240.33 | SUCCESS => {
"msg": "hosts.ini"
}
# 獲取目錄
$ ansible 192.168.240.33 -m debug -a 'msg={{ "/home/archforce/ADT/hosts.ini" | dirname }}'
192.168.240.33 | SUCCESS => {
"msg": "/home/archforce/ADT"
}
# 獲取絕對路徑
$ ansible 192.168.240.33 -m debug -a 'msg={{ "./hosts.ini" | realpath }}'
192.168.240.33 | SUCCESS => {
"msg": "/home/ansible/ADT/hosts.ini"
}
Debug Filters
用於debug的filter
$ ansible 192.168.240.33 -m debug -a 'msg={{ "hello world" | type_debug }}'
192.168.240.33 | SUCCESS => {
"msg": "str"
}
Debug Filters
用於debug的filter
$ ansible 192.168.240.33 -m debug -a 'msg={{ "hello world" | type_debug }}'
192.168.240.33 | SUCCESS => {
"msg": "str"
}
參考文檔
- Ansible 官方文檔:https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#filters-for-formatting-data
- jinja2官方文檔:https://jinja.palletsprojects.com/en/2.10.x/templates/#builtin-filters
- ip address filter官方文檔:https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters_ipaddr.html