文章目录
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:password@www.acme.com: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:password@www.acme.com: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