Ansible自动化运维学习笔记5

时间:2022-07-28
本文章向大家介绍Ansible自动化运维学习笔记5,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

[TOC]

常用过滤器一(filters)

描述:”过滤器(filters)”可以帮助我们对数据进行处理,ansible中的过滤器功能来自于jinja2模板引擎,我们可以借助jinja2的过滤器功能在ansible中对数据进行各种处理;很多其他的过滤器有些是jinja2内置的有些是ansible特有,变量和过滤器之间采用类似于管道符进行拼接;

(1)字符串操作有关的过滤器:

  • upper 过滤器 : 将所有小写字母都被变成了大写
  • lower 过滤器 : 将所有大写字母都被变成了小写
  • capitalize 过滤器 : 将字符串变成首字母大写,之后所有字母纯小写
  • reverse 过滤器 : 将字符串反转
  • list 过滤器 : 将字符串转换成列表,每个字符作为一个元素
  • shuffle 过滤器 : 字面意思为洗牌,将字符串转换成列表每个字符作为一个元素,并且随机打乱顺序 #在随机打乱顺序时将ansible_date_time.epoch的值设置为随机种子
  • first 过滤器 : 返回字符串的第一个字符
  • last 过滤器 : 返回字符串的最后一个字符
  • length 过滤器 : 返回字符串长度,length与count等效,可以写为count
  • center(width=30) : 将字符串放在中间,并且设置字符串的长度默认以0补齐

(2)数字操作有关的过滤器

  • int,int(default=6) : 将对应的值转换成int类型,将对应的值转换成int类型,如果无法转换,默认返回0
  • float,float(8.88) : 将对应的值转换成浮点型,如果无法转换,默认返回’0.0’,当对应的值无法被转换成浮点型时,则返回指定值’8.8‘
  • abs : 获取对应数值的绝对值
  • round,round(5): 四舍五入或者取小数点后
  • random(seed=(ansible_date_time.epoch)),random(start=5),random(start=5,step=3): 随机返回一个随机数并且可以设置步长,同样可以设置随机数种子

(3)与列表相关的过滤器

  • length,first,last,random,shuffle,upper,lower : 与前面意思相同不同在于是列表
  • min : 返回列表中最小的值
  • max : 返回列表中最大的值
  • sort, sort(reverse=true) :将列表升序排序输出,将列表降序排序输出
  • sum : 返回纯数字非嵌套列表中所有数字的和
  • flatten : 那么使用flatten可以’拉平’嵌套的列表
  • join, join(‘ , ‘) : 列表元素合成字符串还可以每个元素之间用指定的字符隔开;
  • unique : 去掉列表中重复的元素,重复的元素只留下一个
  • union(testvar12) : 两个列表的并集
  • intersect(testvar12) : 两个列表的交集
  • symmetric_difference(testvar12) : 去除两个列表的补集
  • difference(testvar12) : 两个列表的交集在列表1中的补集

(4)变量未定义时相关操作的过滤器

  • default(‘WeiyiGeek’) : 如果变量没有定义,则临时返回一个指定的默认值
  • mandatory : 如果对应的变量未定义,则报出“Mandatory variable not defined.”错误

基础示例1:

# cat >filtersString.yml<<END
---
- hosts: local
  remote_user: root
  gather_facts: no
  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)) }} 
END

基础示例1:

#cat >filtersNumber.yml<<END
---
- 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)) }}"
END

基础示例2:

cat >filtersList.yml<<END
---
- hosts: local
  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) }}"
END

基础示例3:

cat >filtersVarible.yml<<END
---
- hosts: test70
  remote_user: root
  gather_facts: no
  vars:
    testvar6: ''
  tasks:
  - debug:
      #如果变量没有定义,则临时返回一个指定的默认值
      #注:如果定义了变量,变量值为空字符串,则会输出空字符
      #default过滤器的别名是d
      msg: "{{ testvar5 | default('WeiyiGeek') }}"
  - debug:
      #如果变量的值是一个空字符串或者变量没有定义,则临时返回一个指定的默认值
      msg: "{{ testvar6 | default('WeiyiGeek',boolean=true) }}"
  - debug:
      #如果对应的变量未定义,则报出“Mandatory variable not defined.”错误,而不是报出默认错误
      msg: "{{ testvar5 | mandatory }}"
END

default过滤器还有一个很方便的用法,不仅能在变量未定义时返回指定的值,还能够让模块的参数变得”可有可无”

  • 如果item有mode属性,就把file模块的mode参数的值设置为item的mode属性的值
  • 如果item没有mode属性,file模块就直接省略mode参数’omit’的字面意思就是”省略”

实际案例:对应其中一个建立建立的文件进行权限设定,而其他建立的文件则设置为系统缺省权限;

# cat >default.yml<<END
---
- hosts: local
  remote_user: root
  gather_facts: no
  vars:
    paths:
      - path: /tmp/test
        mode: '0444'
      - path: /tmp/foo
      - path: /tmp/bar
  tasks:
  #未使用了default过滤器
  # - 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
  #使用了default过滤器
  - file: dest={{item.path}} state=touch mode={{item.mode | default(omit)}} #我们并没有对文件是否有mode属性进行判断,而是直接调用了file模块的mode参数
    with_items: "{{ paths }}"
END

过滤器的用法详细:

json_query 过滤器

描述:如果有时候您从某处API接口进行请求并且成功返回一串json字符串的话,有当您打开后发现里面是杂乱无章的这时可以借助于我们的ansible神器;

{"logs":[{"domain":"test.com","url":"?key=asdashashdhad&uid=124"},{"domain":"test.com","url":"?key=jioenlkhuxcai&uid=125"}]}

将这段数据所在的文件当做变量文件引入到playbook中,然后输出对应的变量即可;

---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  - include_vars:
      file: "/testdir/ansible/CDN.log"
      name: testjson
  - debug:
      msg: "{{test.json}}"

运行上面这段脚本后便会将杂乱无章的json格式化显示;

原因:其实json是yaml的子集yaml是json的超集,yaml格式的数据和json格式的数据是可以互相转换的,所以对于ansible来说,当我们把上例中的json数据文件当做变量文件引入时,就好像引入了一个我们定义好的yaml格式的变量文件一样,对于ansible来说是没有区别的,而且,即使在变量文件中使用yaml格式定义了变量,在使用debug模块输出变量信息时,ansible也会自动将yaml格式的数据转化为json格式后进行输出;

我们把上述json数据转换成yaml的格式,同时列出上述数据的json格式与yaml格式,你可以根据自己的使用习惯选择阅读哪种格式的数据,以便你能够更好的理解这段数据的含义,yaml格式如下:

#cat >/root/filter.txt<<END
---
logs:
- domainName: test.com
  files:
   - dateFrom: 2018-09-05-0000
     url: ?key=asdashashdhad&uid=124
- domainName: test123.com
  files:
   - dateFrom: 2018-09-05-0000
     url: ?key=asdashashdhad&uid=124
END

此刻如果我们想要获取到整个列表中的所有日志文件的Url,我们该怎么办呢? 答:我们有两种方式一种是通过with_subelements,另外一种是通过json_query的过滤器实现;

#cat >/root/filterYml.yml<<END
---
- hosts: local
  remote_user: root
  gather_facts: no
  tasks:
  - include_vars:
      file: "/root/filter.txt"
      name: vartest
  - debug:
      msg: "{{item.1.url}}"
    with_subelements:
    - "{{vartest.logs}}"
    - files
END

执行结果:(坑呀)

TASK [debug] 
ok: [local] => (item=[{u'domainName': u'test.com'}, {u'url': u'?key=asdashashdhad&uid=124', u'dateFrom': u'2018-09-05-0000'}]) => {
    "msg": "?key=asdashashdhad&uid=124"
}
ok: [local] => (item=[{u'domainName': u'test123.com'}, {u'url': u'?key=asdashashdhad&uid=124', u'dateFrom': u'2018-09-05-0000'}]) => {
    "msg": "?key=asdashashdhad&uid=124"
}

json_query过滤器 描述:可以直接提取json数据,可以进行通配符进行配置,从而比上面采用with_subelement更加的简便;在复现上面的实例的时候我们先来看看你它如何使用; 基础示例:

# cat > filter1.txt<<END
---
users:
- name: tom
  age: 17
  hobby:
    - run
    - pingpang
- name: jerry
  age: 12
  hobby:
    - computer
    - basketball
END
  • 当数据结构中存在列表时,我们可以使用”列表名[*]”获取到列表下面的所有项
  • 使用json_query过滤器对这个变量进行了处理json_query(‘users[*].name’)表示找到users列表中所有元素的name属性
  • 使用json_query(‘test.users[?name==`tom`].hobby[*]’)表示只查找users列表中name属性等于tom的hobby信息 (注意是反引号)
  • 使用json_query(‘test.users[*].{uname:name,uage:age}’)表示找到users列表中所有用户的name值和age值
#cat >json_queryDemo.yml<<END
---
- hosts: local
  remote_user: root
  gather_facts: no
  tasks:
  - include_vars:
      file: "/root/filter1.txt"
      name: vartest
      #坑:注意下面是name(在palybook执行中显示的title)
  - name: "json_query Demo 1 : Name"
    debug:
      msg: "{{vartest | json_query('users[*].name')}}" 
  - name: "json_query Demo 2 : Hobby"
    debug:
      msg: "{{vartest | json_query('users[*].hobby[*]')}}"
  - name: "Advances json_query Demo1"
    debug:
      msg: "{{vartest | json_query('users[?name==`tom`].hobby[*]')}}" #关键点指定用户过滤
  - name: "Advances json_query Demo2"
    debug:
       #用户的姓名和年龄都按照我们定义的方式输出
       msg: "{{vartest | json_query('users[*].{username:name,userage:age}')}}"
END
`

执行结果:

TASK [json_query Demo 1 : Name] 
ok: [local] => {
    "msg": ["tom","jerry"]
}

TASK [json_query Demo 2 : Hobby] 
ok: [local] => {
    "msg": [
        ["run", "pingpang"],
        ["computer","basketball"]
    ]
}

TASK [Advances json_query Demo] 
ok: [local] => {
    "msg": [["run","pingpang"]]  #关键点1 过滤判断是关键
}

TASK [Advances json_query Demo2] 
ok: [local] => {
    "msg": [
        {"userage": 17, "username": "tom"},
        { "userage": 12, "username": "jerry"}  #关键点2 指定格式输出
    ]
}

回归最初的示例:

#cat >json_query.yml<<END
---
- hosts: local
  remote_user: root
  gather_facts: no
  tasks:
  - include_vars:
      file: "/root/filter.txt"
      name: vartest
  - name: "json_query Filter Demo"
    debug:
      msg: "{{vartest|json_query('logs[*].files[*].url')}}"
END

执行结果:

TASK [json_query Filter Demo] 
ok: [local] => {
    #从这里可以看出于with_subelements关键字的不同更加的高效
    "msg": [["?key=asdashashdhad&uid=124"], ["?key=asdashashdhad&uid=124"]]
}

常用过滤器二

描述:继续总结一些使用的过滤器,可以直接采用cmd进行测试:

#查看软连接的实际文件(注意硬连接是不行的)
ansible local -m debug -e "path=/bin/bash" -a "msg={{path|realpath}}"
---
- hosts: test70
  remote_user: root
  gather_facts: no
  tasks:
  ######################################################################
  #在调用shell模块时,如果引用某些变量时需要添加引号,则可以使用quote过滤器代替引号
  #示例如下,先看示例,后面会有注解
  - shell: "echo {{teststr | quote}} > /testdir/testfile"
    vars:
      teststr: "anbnc"
  #上例中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过滤器可以获取到一个路径字符串中的 文件名 "msg": "test.conf"
  - debug:
      msg: "{{teststr | basename}}"
    vars:
      teststr: "/testdir/ansible/testfile"
  ######################################################################
  #获取到一个windows路径字符串中的文件名,2.0版本以后的ansible可用
  - debug:
      msg: "{{teststr | win_basename}}"
    vars:
      teststr: 'D:studyWeiyiGeek' 
  #示例如下"msg": "D:\study"
  ######################################################################
  #dirname过滤器可以获取到一个路径字符串中的 路径名
  - debug:
      msg: "{{teststr | dirname}}"
    vars:
      teststr: "/testdir/ansible/testfile"
  ######################################################################
  #获取到一个windows路径字符串中的文件名,2.0版本以后的ansible可用
  - debug:
      msg: "{{teststr | win_dirname}}"
    vars:
      teststr: 'D:studyWeiyiGeek'
  ######################################################################
  #将一个windows路径字符串中的盘符和路径分开,2.0版本以后的ansible可用
  - debug:
      msg: "{{teststr | win_splitdrive}}"
    vars:
      teststr: 'D:studyWeiyiGeek'
  #可以配合之前总结的过滤器一起使用,比如只获取到盘符/路径,示例如下 "msg": "(u'D:', u'\\study\\WeiyiGeek')"
  ######################################################################
  #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": "(u'/etc/nginx/conf.d/test', u'.conf')"
  ######################################################################
  #to_uuid过滤器能够为对应的字符串生成uuid  "msg": "9e4cc6d9-89b3-5a09-be35-f3fbd1526102"
  - 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','.U5cjaHe55KK') }}"
  #如下方法可以幂等的为每个主机的密码生成对应哈希串
  #有了之前总结的过滤器用法作为基础,你一定已经看懂了
  - debug:
      msg: "{{ '123123' | password_hash('sha512', 65534|random(seed=inventory_hostname)|string) }}"