1. 过滤器初识
获取到的变量的值中的所有字母都变成大写
---
- hosts: test70
remote_user: root
gather_facts: no
vars:
testvar: 1a2b3c
tasks:
- debug:
msg: "{{ testvar | upper }}"
2. 字符串过滤器
---
- hosts: test70
remote_user: root
vars:
testvar: "abc123ABC 666"
testvar1: " abc "
testvar2: '123456789'
testvar3: "1a2b,@#$%^&"
tasks:
- debug:
#将字符串转换成纯大写
msg: "{{ testvar | upper }}"
- debug:
#将字符串转换成纯小写
msg: "{{ testvar | lower }}"
- debug:
#将字符串变成首字母大写,之后所有字母纯小写
msg: "{{ testvar | capitalize }}"
- debug:
#将字符串反转
msg: "{{ testvar | reverse }}"
- debug:
#返回字符串的第一个字符
msg: "{{ testvar | first }}"
- debug:
#返回字符串的最后一个字符
msg: "{{ testvar | last }}"
- debug:
#将字符串开头和结尾的空格去除
msg: "{{ testvar1 | trim }}"
- debug:
#将字符串放在中间,并且设置字符串的长度为30,字符串两边用空格补齐30位长
msg: "{{ testvar1 | center(width=30) }}"
- debug:
#返回字符串长度,length与count等效,可以写为count
msg: "{{ testvar2 | length }}"
- debug:
#将字符串转换成列表,每个字符作为一个元素
msg: "{{ testvar3 | list }}"
- debug:
#将字符串转换成列表,每个字符作为一个元素,并且随机打乱顺序
#shuffle的字面意思为洗牌
msg: "{{ testvar3 | shuffle }}"
- debug:
#将字符串转换成列表,每个字符作为一个元素,并且随机打乱顺序
#在随机打乱顺序时,将ansible_date_time.epoch的值设置为随机种子
#也可以使用其他值作为随机种子,ansible_date_time.epoch是facts信息
msg: "{{ testvar3 | shuffle(seed=(ansible_date_time.epoch)) }}"
2. 数字过滤器
---
- hosts: test70
remote_user: root
vars:
testvar4: -1
tasks:
- debug:
#将对应的值转换成int类型
#ansible中,字符串和整形不能直接计算,比如{{ 8+'8' }}会报错
#所以,我们可以把一个值为数字的字符串转换成整形后再做计算
msg: "{{ 8+('8' | int) }}"
- debug:
#将对应的值转换成int类型,如果无法转换,默认返回0
#使用int(default=6)或者int(6)时,如果无法转换则返回指定值6
msg: "{{ 'a' | int(default=6) }}"
- debug:
#将对应的值转换成浮点型,如果无法转换,默认返回'0.0'
msg: "{{ '8' | float }}"
- debug:
#当对应的值无法被转换成浮点型时,则返回指定值’8.8‘
msg: "{{ 'a' | float(8.88) }}"
- debug:
#获取对应数值的绝对值
msg: "{{ testvar4 | abs }}"
- debug:
#四舍五入
msg: "{{ 12.5 | round }}"
- debug:
#取小数点后五位
msg: "{{ 3.1415926 | round(5) }}"
- debug:
#从0到100中随机返回一个随机数
msg: "{{ 100 | random }}"
- debug:
#从5到10中随机返回一个随机数
msg: "{{ 10 | random(start=5) }}"
- debug:
#从5到15中随机返回一个随机数,步长为3
#步长为3的意思是返回的随机数只有可能是5、8、11、14中的一个
msg: "{{ 15 | random(start=5,step=3) }}"
- debug:
#从0到15中随机返回一个随机数,这个随机数是5的倍数
msg: "{{ 15 | random(step=5) }}"
- debug:
#从0到15中随机返回一个随机数,并将ansible_date_time.epoch的值设置为随机种子
#也可以使用其他值作为随机种子,ansible_date_time.epoch是facts信息
#seed参数从ansible2.3版本开始可用
msg: "{{ 15 | random(seed=(ansible_date_time.epoch)) }}"
3. 列表过滤器
---
- hosts: test70
remote_user: root
vars:
testvar7: [22,18,5,33,27,30]
testvar8: [1,[7,2,[15,9]],3,5]
testvar9: [1,'b',5]
testvar10: [1,'A','b',['QQ','wechat'],'CdEf']
testvar11: ['abc',1,3,'a',3,'1','abc']
testvar12: ['abc',2,'a','b','a']
tasks:
- debug:
#返回列表长度,length与count等效,可以写为count
msg: "{{ testvar7 | length }}"
- debug:
#返回列表中的第一个值
msg: "{{ testvar7 | first }}"
- debug:
#返回列表中的最后一个值
msg: "{{ testvar7 | last }}"
- debug:
#返回列表中最小的值
msg: "{{ testvar7 | min }}"
- debug:
#返回列表中最大的值
msg: "{{ testvar7 | max }}"
- debug:
#将列表升序排序输出
msg: "{{ testvar7 | sort }}"
- debug:
#将列表降序排序输出
msg: "{{ testvar7 | sort(reverse=true) }}"
- debug:
#返回纯数字非嵌套列表中所有数字的和
msg: "{{ testvar7 | sum }}"
- debug:
#如果列表中包含列表,那么使用flatten可以'拉平'嵌套的列表
#2.5版本中可用,执行如下示例后查看效果
msg: "{{ testvar8 | flatten }}"
- debug:
#如果列表中嵌套了列表,那么将第1层的嵌套列表‘拉平’
#2.5版本中可用,执行如下示例后查看效果
msg: "{{ testvar8 | flatten(levels=1) }}"
- debug:
#过滤器都是可以自由结合使用的,就好像linux命令中的管道符一样
#如下,取出嵌套列表中的最大值
msg: "{{ testvar8 | flatten | max }}"
- debug:
#将列表中的元素合并成一个字符串
msg: "{{ testvar9 | join }}"
- debug:
#将列表中的元素合并成一个字符串,每个元素之间用指定的字符隔开
msg: "{{ testvar9 | join(' , ') }}"
- debug:
#从列表中随机返回一个元素
#对列表使用random过滤器时,不能使用start和step参数
msg: "{{ testvar9 | random }}"
- debug:
#从列表中随机返回一个元素,并将ansible_date_time.epoch的值设置为随机种子
#seed参数从ansible2.3版本开始可用
msg: "{{ testvar9 | random(seed=(ansible_date_time.epoch)) }}"
- debug:
#随机打乱顺序列表中元素的顺序
#shuffle的字面意思为洗牌
msg: "{{ testvar9 | shuffle }}"
- debug:
#随机打乱顺序列表中元素的顺序
#在随机打乱顺序时,将ansible_date_time.epoch的值设置为随机种子
#seed参数从ansible2.3版本开始可用
msg: "{{ testvar9 | shuffle(seed=(ansible_date_time.epoch)) }}"
- debug:
#将列表中的每个元素变成纯大写
msg: "{{ testvar10 | upper }}"
- debug:
#将列表中的每个元素变成纯小写
msg: "{{ testvar10 | lower }}"
- debug:
#去掉列表中重复的元素,重复的元素只留下一个
msg: "{{ testvar11 | unique }}"
- debug:
#将两个列表合并,重复的元素只留下一个
#也就是求两个列表的并集
msg: "{{ testvar11 | union(testvar12) }}"
- debug:
#取出两个列表的交集,重复的元素只留下一个
msg: "{{ testvar11 | intersect(testvar12) }}"
- debug:
#取出存在于testvar11列表中,但是不存在于testvar12列表中的元素
#去重后重复的元素只留下一个
#换句话说就是:两个列表的交集在列表1中的补集
msg: "{{ testvar11 | difference(testvar12) }}"
- debug:
#取出两个列表中各自独有的元素,重复的元素只留下一个
#即去除两个列表的交集,剩余的元素
msg: "{{ testvar11 | symmetric_difference(testvar12) }}"
4. 变量过滤器
---
- hosts: test70
remote_user: root
gather_facts: no
vars:
testvar6: ''
tasks:
- debug:
#如果变量没有定义,则临时返回一个指定的默认值
#注:如果定义了变量,变量值为空字符串,则会输出空字符
#default过滤器的别名是d
msg: "{{ testvar5 | default('zsythink') }}"
- debug:
#如果变量的值是一个空字符串或者变量没有定义,则临时返回一个指定的默认值
msg: "{{ testvar6 | default('zsythink',boolean=true) }}"
- debug:
#如果对应的变量未定义,则报出“Mandatory variable not defined.”错误,而不是报出默认错误
msg: "{{ testvar5 | mandatory }}"
5. "可有可无"过滤器
一共定义了3个文件,只有第一个文件指定了权限,第二个文件和第三个文件没有指定任何权限,这样定义目的是,当这三个文件在目 标主机中创建时,只有第一个文件按照指定的权限被创建,之后的两个文件都按照操作系统的默认权限进行创建,在实际工作中,你获得列表中可能有几十个这样的文件需要被创建,这些文件中,有些文件需要特定的权限,有些不需要,所以,可能需要使用循环来处理这 个问题,但是在使用循环时,会遇到另一个问题,有的文件有mode属性,有的文件没有mode属性。
vars:
paths:
- path: /tmp/testfile
mode: '0444'
- path: /tmp/foo
- path: /tmp/bar
使用file模块在目标主机中创建文件,一共循环了两遍,因为我们需要对文件是否有 mode属性进行判断,然后根据判断结果调整file模块的参数设定。
- hosts: test70
remote_user: root
gather_facts: no
vars:
paths:
- path: /tmp/test
mode: '0444'
- path: /tmp/foo
- path: /tmp/bar
tasks:
- file: dest={{item.path}} state=touch mode={{item.mode}}
with_items: "{{ paths }}"
when: item.mode is defined
- file: dest={{item.path}} state=touch
with_items: "{{ paths }}"
when: item.mode is undefined
并没有对文件是否有mode属性进行判断,而是直接调用了file模块的mode参数,将mode参数的值设定为了" {{item.mode | default(omit)}}",这是什么意思呢?它的意思是,如果item有mode属性,就把file模块的mode参数的值设置为item的 mode属性的值,如果item没有mode属性,file模块就直接省略mode参数,'omit’的字面意思就是"省略",换成大白话说就是:[有就 用,没有就不用,可以有,也可以没有],所谓的"可有可无"就是这个意思。
- hosts: test70
remote_user: root
gather_facts: no
vars:
paths:
- path: /tmp/test
mode: '0444'
- path: /tmp/foo
- path: /tmp/bar
tasks:
- file: dest={{item.path}} state=touch mode={{item.mode | default(omit)}}
with_items: "{{ paths }}"
6. 利用过滤器进行格式转换
vim /testdir/ansible/wsCdnLogList
{"logs":[{"domainName":"asia1.cdn.test.com","files":[{"dateFrom":"2018-09-05-0000","dateTo":"2018-09-05-2359","logUrl":"http://log.testcd.com/log/zsy/asia1.cdn.test.com/2018-09-05-0000-2330_asia1.cdn.test.com.all.log.gz?wskey=XXXXX5a","fileSize":254,"fileName":"2018-09-05-0000-2330_asia1.cdn.test.com.all.log.gz","fileMd5":"error"}]},{"domainName":"image1.cdn.test.com","files":[{"dateFrom":"2018-09-05-2200","dateTo":"2018-09-05-2259","logUrl":"http://log.testcd.com/log/zsy/image1.cdn.test.com/2018-09-05-2200-2230_image1.cdn.test.com.cn.log.gz?wskey=XXXXX1c","fileSize":10509,"fileName":"2018-09-05-2200-2230_image1.cdn.test.com.cn.log.gz","fileMd5":"error"},{"dateFrom":"2018-09-05-2300","dateTo":"2018-09-05-2359","logUrl":"http://log.testcd.com/log/zsy/image1.cdn.test.com/2018-09-05-2300-2330_image1.cdn.test.com.cn.log.gz?wskey=XXXXXfe","fileSize":5637,"fileName":"2018-09-05-2300-2330_image1.cdn.test.com.cn.log.gz","fileMd5":"error"}]}]}
---
- hosts: test70
remote_user: root
gather_facts: no
tasks:
- include_vars:
file: "/testdir/ansible/wsCdnLogList"
name: testvar
- debug:
msg: "{{ testvar }}"
json是yaml的子集,yaml是json的超集,yaml格式的数据和json格式的数据是可以互相转换的,所以,对于 ansible来说,当我们把上例中的json数据文件当做变量文件引入时,就好像引入了一个我们定义好的yaml格式的变量文件一样,对于 ansible来说是没有区别的,而且,即使在变量文件中使用yaml格式定义了变量,在使用debug模块输出变量信息时,ansible也会自动将 yaml格式的数据转化为json格式后进行输出,json数据转换成yaml的格式。通过with_subelements循环,获取到当前整个大列表中的所有日志的logUrl属性。
logs:
- domainName: asia1.cdn.test.com
files:
- dateFrom: 2018-09-05-0000
dateTo: 2018-09-05-2359
fileMd5: error
fileName: 2018-09-05-0000-2330_asia1.cdn.test.com.all.log.gz
fileSize: 254
logUrl: http://log.testcd.com/log/zsy/asia1.cdn.test.com/2018-09-05-0000-2330_asia1.cdn.test.com.all.log.gz?wskey=XXXXX5a
- domainName: image1.cdn.test.com
files:
- dateFrom: 2018-09-05-2200
dateTo: 2018-09-05-2259
fileMd5: error
fileName: 2018-09-05-2200-2230_image1.cdn.test.com.cn.log.gz
fileSize: 10509
logUrl: http://log.testcd.com/log/zsy/image1.cdn.test.com/2018-09-05-2200-2230_image1.cdn.test.com.cn.log.gz?wskey=XXXXX1c
- dateFrom: 2018-09-05-2300
dateTo: 2018-09-05-2359
fileMd5: error
fileName: 2018-09-05-2300-2330_image1.cdn.test.com.cn.log.gz
fileSize: 5637
logUrl: http://log.testcd.com/log/zsy/image1.cdn.test.com/2018-09-05-2300-2330_image1.cdn.test.com.cn.log.gz?wskey=XXXXXfe
tasks:
- include_vars:
file: "/testdir/ansible/wsCdnLogList"
name: testvar
- debug:
msg: "{{ item.1.logUrl }}"
with_subelements:
- "{{testvar.logs}}"
- files
json_query过滤器
json格式需要被json_query过滤器转换的的数据
{
"users": [
{
"name": "tom",
"age": 18
},
{
"name": "jerry",
"age": 20
}
]
}
yaml格式需要被json_query过滤器转换的的数据
---
users:
- name: tom
age: 18
- name: jerry
age: 20
json_query(‘users[*].name’)表示找到users列表中所有元素的name属性
---
- hosts: test70
remote_user: root
gather_facts: no
tasks:
- include_vars:
file: "/testdir/ansible/testvarfile"
name: testvar
- debug:
msg: "{{ testvar | json_query('users[*].name') }}"
vim /testdir/ansible/testvarfile1
---
test:
users:
- name: tom
age: 18
hobby:
- Skateboard
- VideoGame
- name: jerry
age: 20
hobby:
- Music
---
- hosts: test70
remote_user: root
gather_facts: no
tasks:
- include_vars:
file: "/testdir/ansible/testvarfile1"
name: testvar
- debug:
msg: "{{ testvar | json_query('test.users[*].hobby[*]') }}"
json_query(‘test.users[?name==tom
].hobby[*]’)表示只查找users列表中 name属性等于tom的hobby信息,你肯定发现了,上例中,我们使用了"反引号"将tom引起来了,这是因为当你在添加查询条件时,对需要为对应的 值添加引号,但是,上例中msg的值的外侧已经存在一对双引号,双引号内又有一对单引号,所以,为了不让引号之间互相冲突,此处使用反引号将tom引起。
tasks:
- include_vars:
file: "/testdir/ansible/testvarfile1"
name: testvar
- debug:
msg: "{{ testvar | json_query('test.users[?name==`tom`].hobby[*]') }}"
除了使用反引号,也可以用querystring
tasks:
- include_vars:
file: "/testdir/ansible/testvarfile1"
name: testvar
- debug:
msg: "{{ testvar | json_query(querystring) }}"
vars:
querystring: "test.users[?name=='tom'].age"
同时获取多个属性值时,需要通过键值对的方式调用属性
tasks:
- include_vars:
file: "/testdir/ansible/testvarfile1"
name: testvar
- debug:
msg: "{{ testvar | json_query('test.users[*].{uname:name,uage:age}') }}"
使用json_query过滤器找到cdn厂商返回的json数据中的所有日志的logUrl
---
- hosts: test70
remote_user: root
gather_facts: no
vars_files:
- /testdir/ansible/wsCdnLogList
tasks:
- debug:
msg: "{{item}}"
with_items: "{{ logs | json_query('[*].files[*].logUrl') }}"
7. 常用过滤器
---
- hosts: test70
remote_user: root
gather_facts: no
tasks:
######################################################################
#在调用shell模块时,如果引用某些变量时需要添加引号,则可以使用quote过滤器代替引号
#示例如下,先看示例,后面会有注解
- shell: "echo {{teststr | quote}} > /testdir/testfile"
vars:
teststr: "a\nb\nc"
#上例中shell模块的写法与如下写法完全等效
#shell: "echo '{{teststr}}' > /testdir/testfile"
#没错,如你所见,quote过滤器能够代替引号
#上例中,如果不对{{teststr}}添加引号,则会报错,因为teststr变量中包含"\n"转义符
######################################################################
#ternary过滤器可以实现三元运算的效果 示例如下
#如下示例表示如果name变量的值是John,那么对应的值则为Mr,否则则为Ms
#简便的实现类似if else对变量赋值的效果
- debug:
msg: "{{ (name == 'John') | ternary('Mr','Ms') }}"
vars:
name: "John"
######################################################################
#basename过滤器可以获取到一个路径字符串中的文件名
- debug:
msg: "{{teststr | basename}}"
vars:
teststr: "/testdir/ansible/testfile"
######################################################################
#获取到一个windows路径字符串中的文件名,2.0版本以后的ansible可用
- debug:
msg: "{{teststr | win_basename}}"
vars:
teststr: 'D:\study\zsythink'
######################################################################
#dirname过滤器可以获取到一个路径字符串中的路径名
- debug:
msg: "{{teststr | dirname}}"
vars:
teststr: "/testdir/ansible/testfile"
######################################################################
#获取到一个windows路径字符串中的文件名,2.0版本以后的ansible可用
- debug:
msg: "{{teststr | win_dirname}}"
vars:
teststr: 'D:\study\zsythink'
######################################################################
#将一个windows路径字符串中的盘符和路径分开,2.0版本以后的ansible可用
- debug:
msg: "{{teststr | win_splitdrive}}"
vars:
teststr: 'D:\study\zsythink'
#可以配合之前总结的过滤器一起使用,比如只获取到盘符,示例如下
#msg: "{{teststr | win_splitdrive | first}}"
#可以配合之前总结的过滤器一起使用,比如只获取到路径,示例如下
#msg: "{{teststr | win_splitdrive | last}}"
######################################################################
#realpath过滤器可以获取软链接文件所指向的真正文件
- debug:
msg: "{{ path | realpath }}"
vars:
path: "/testdir/ansible/testsoft"
######################################################################
#relpath过滤器可以获取到path对于“指定路径”来说的“相对路径”
- debug:
msg: "{{ path | relpath('/testdir/testdir') }}"
vars:
path: "/testdir/ansible"
######################################################################
#splitext过滤器可以将带有文件名后缀的路径从“.后缀”部分分开
- debug:
msg: "{{ path | splitext }}"
vars:
path: "/etc/nginx/conf.d/test.conf"
#可以配置之前总结的过滤器,获取到文件后缀
#msg: "{{ path | splitext | last}}"
#可以配置之前总结的过滤器,获取到文件前缀名
#msg: "{{ path | splitext | first | basename}}"
######################################################################
#to_uuid过滤器能够为对应的字符串生成uuid
- debug:
msg: "{{ teststr | to_uuid }}"
vars:
teststr: "This is a test statement"
######################################################################
#bool过滤器可以根据字符串的内容返回bool值true或者false
#字符串的内容为yes、1、True、true则返回布尔值true,字符串内容为其他内容则返回false
- debug:
msg: "{{ teststr | bool }}"
vars:
teststr: "1"
#当和用户交互时,有可能需要用户从两个选项中选择一个,比如是否继续,
#这时,将用户输入的字符串通过bool过滤器处理后得出布尔值,从而进行判断,比如如下用法
#- debug:
# msg: "output when bool is true"
# when: some_string_user_input | bool
######################################################################
#map过滤器可以从列表中获取到每个元素所共有的某个属性的值,并将这些值组成一个列表
#当列表中嵌套了列表,不能越级获取属性的值,也就是说只能获取直接子元素的共有属性值。
- vars:
users:
- name: tom
age: 18
hobby:
- Skateboard
- VideoGame
- name: jerry
age: 20
hobby:
- Music
debug:
msg: "{{ users | map(attribute='name') | list }}"
#也可以组成一个字符串,用指定的字符隔开,比如分号
#msg: "{{ users | map(attribute='name') | join(';') }}"
######################################################################
#与python中的用法相同,两个日期类型相减能够算出两个日期间的时间差
#下例中,我们使用to_datatime过滤器将字符串类型转换成了日期了类型,并且算出了时间差
- debug:
msg: '{{ ("2016-08-14 20:00:12"| to_datetime) - ("2012-12-25 19:00:00" | to_datetime) }}'
#默认情况下,to_datatime转换的字符串的格式必须是“%Y-%m-%d %H:%M:%S”
#如果对应的字符串不是这种格式,则需要在to_datetime中指定与字符串相同的时间格式,才能正确的转换为时间类型
- debug:
msg: '{{ ("20160814"| to_datetime("%Y%m%d")) - ("2012-12-25 19:00:00" | to_datetime) }}'
#如下方法可以获取到两个日期之间一共相差多少秒
- debug:
msg: '{{ ( ("20160814"| to_datetime("%Y%m%d")) - ("20121225" | to_datetime("%Y%m%d")) ).total_seconds() }}'
#如下方法可以获取到两个日期“时间位”相差多少秒,注意:日期位不会纳入对比计算范围
#也就是说,下例中的2016-08-14和2012-12-25不会纳入计算范围
#只是计算20:00:12与08:30:00相差多少秒
#如果想要算出连带日期的秒数差则使用total_seconds()
- debug:
msg: '{{ ( ("2016-08-14 20:00:12"| to_datetime) - ("2012-12-25 08:30:00" | to_datetime) ).seconds }}'
#如下方法可以获取到两个日期“日期位”相差多少天,注意:时间位不会纳入对比计算范围
- debug:
msg: '{{ ( ("2016-08-14 20:00:12"| to_datetime) - ("2012-12-25 08:30:00" | to_datetime) ).days }}'
######################################################################
#使用base64编码方式对字符串进行编码
- debug:
msg: "{{ 'hello' | b64encode }}"
#使用base64编码方式对字符串进行解码
- debug:
msg: "{{ 'aGVsbG8=' | b64decode }}"
#######################################################################
#使用sha1算法对字符串进行哈希
- debug:
msg: "{{ '123456' | hash('sha1') }}"
#使用md5算法对字符串进行哈希
- debug:
msg: "{{ '123456' | hash('md5') }}"
#获取到字符串的校验和,与md5哈希值一致
- debug:
msg: "{{ '123456' | checksum }}"
#使用blowfish算法对字符串进行哈希,注:部分系统支持
- debug:
msg: "{{ '123456' | hash('blowfish') }}"
#使用sha256算法对字符串进行哈希,哈希过程中会生成随机"盐",以便无法直接对比出原值
- debug:
msg: "{{ '123456' | password_hash('sha256') }}"
#使用sha256算法对字符串进行哈希,并使用指定的字符串作为"盐"
- debug:
msg: "{{ '123456' | password_hash('sha256','mysalt') }}"
#使用sha512算法对字符串进行哈希,哈希过程中会生成随机"盐",以便无法直接对比出原值
- debug:
msg: "{{ '123123' | password_hash('sha512') }}"
#使用sha512算法对字符串进行哈希,并使用指定的字符串作为"盐"
- debug:
msg: "{{ '123123' | password_hash('sha512','ebzL.U5cjaHe55KK') }}"
#如下方法可以幂等的为每个主机的密码生成对应哈希串
#有了之前总结的过滤器用法作为基础,你一定已经看懂了
- debug:
msg: "{{ '123123' | password_hash('sha512', 65534|random(seed=inventory_hostname)|string) }}"
————Blueicex 2020/3/30 09:19 [email protected]