Ansible——lookup,过滤器

发布于:2024-05-07 ⋅ 阅读:(42) ⋅ 点赞:(0)

Ansible——lookup,过滤器

Ansible Playbook允许用户使用自定义变量,不过当变量过大,或者太复杂时,无论是在Playbook中通过vars定义,还是在单独的变量文件中定义,可读性都比较差

lookup能够读取Ansible管理节点上文件系统的文件内容到Ansible变量中,也可以读取配置的数据库中的内容

lookup读取文件

下面是lookup基本使用方法,将Ansible管理节点上的文件data/plain.txt的内容读取出来,并赋值给变量"contents"。"file"告诉lookup读取对象的类型是File,直接读取文件内容,无须做特别的处理

[root@csq ~]# mkdir data
[root@csq ~]# echo "csqcsqcsq" > data/plain.txt
[root@csq ~]# vim test.yml 
- hosts: all
  remote_user: root
  gather_facts: false
  vars:
    contents: "{{ lookup('file','/root/data/plain.txt') }}"
  tasks:
    - debug: msg="the value of /root/data/plain.txt is {{ contents }}"
    
# 执行结果
TASK [debug] **********************************************************************************
ok: [192.168.200.20] => {
    "msg": "the value of /root/data/plain.txt is csqcsqcsq"
}
ok: [192.168.200.30] => {
    "msg": "the value of /root/data/plain.txt is csqcsqcsq"
}

lookup生成随机密码

如果密码文件/tmp/password/kitty不存在,lookup会生成长度为5的随机密码,存储在文件中。如果密码文件存在,那么直接读取该文件中的内容作为密码

[root@csq ~]# vim a.yml 
- hosts: all
  remote_user: root
  vars:
    password: "{{ lookup('password','/tmp/password/kitty length=5') }}"
  tasks:
  - debug: var=password

# 执行结果
TASK [debug] **********************************************************************************
ok: [192.168.200.20] => {
    "password": "TWLDK"
}
ok: [192.168.200.30] => {
    "password": "TWLDK"
}

lookup读取环境变量

env类型的lookup可以读取Linux上的环境变量

[root@csq ~]# vim c.yml              
      tasks:
- hosts: test
  remote_user: root
  tasks:
    - name: env
      debug: msg=" {{lookup('env','HOME') }} 是一个环境变量"

# 执行结果
[root@csq ~]# ansible-playbook c.yml 

PLAY [test] *************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************
ok: [192.168.200.20]

TASK [env] **************************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": " /root 是一个环境变量"
}

PLAY RECAP **************************************************************************************************************************
192.168.200.20             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

lookup读取Linux命令的执行结果

pipe类型的lookup可以将Linux上命令的执行结果读取到Ansible中

[root@csq ~]# vim d.yml         
- hosts: all
  remote_user: root
  tasks:
    - name: 读取管理节点的Linux命令执行结果
      debug: msg="{{ lookup('pipe','date') }} 这是该命令执行的结果"
      
      
# 执行结果
[root@csq ~]# ansible-playbook d.yml 

PLAY [all] **************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************
ok: [192.168.200.30]
ok: [192.168.200.20]

TASK [读取管理节点的Linux命令执行结果] **********************************************************************************************
ok: [192.168.200.20] => {
    "msg": "2024年 05月 02日 星期四 11:42:35 CST 这是该命令执行的结果"
}
ok: [192.168.200.30] => {
    "msg": "2024年 05月 02日 星期四 11:42:35 CST 这是该命令执行的结果"
}

PLAY RECAP **************************************************************************************************************************
192.168.200.20             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.200.30             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

lookup读取template变量替换后的文件

template类型的lookup可以将一个template文件经过变量替换后的内容读取到Ansible中。如果在template文件中有未定义的变量,则会报错

# template文件
[root@csq ~]# vim template1.j2            
hostname: {{ansible_hostname}}

# playbook文件
[root@csq ~]# vim e.yml              
- hosts: all
  remote_user: root
  tasks:
    - name: 读取template
      debug: msg="{{ lookup('template','/root/template1.j2') }} 这是template.j2的变量"

# 执行结果
[root@csq ~]# ansible-playbook e.yml 

PLAY [all] **************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************
ok: [192.168.200.30]
ok: [192.168.200.20]

TASK [读取template] *****************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "hostname: podman\n 这是template.j2的变量"
}
ok: [192.168.200.30] => {
    "msg": "hostname: localhost\n 这是template.j2的变量"
}

PLAY RECAP **************************************************************************************************************************
192.168.200.20             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.200.30             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

lookup读取配置文件

lookup支持读取两种类型的配置文件;ini和java的properties

ini类型的lookup默认读取配置文件类型是ini

# ini文件
[root@csq ~]# vim data/users.ini 
[test1]
user=csq
password=111
[test2]
user=zhw
password=000

# playbook文件
[root@csq ~]# vim f.yml
    - name:
- hosts: test
  remote_user: root
  tasks:
    - debug:
        msg: "test1 user = {{ lookup('ini','user section=test1 file=/root/data/users.ini') }}"
    - debug:
        msg: "test2 user = {{ lookup('ini','user section=test2 file=/root/data/users.ini') }}"
# 执行结果
[root@csq ~]# ansible-playbook  f.yml 

PLAY [test] *************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************
ok: [192.168.200.20]

TASK [debug] ************************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "test1 user = csq"
}

TASK [debug] ************************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "test2 user = zhw"
}

PLAY RECAP **************************************************************************************************************************
192.168.200.20             : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

读取properties类型文件时,需要加一个额外的参数来告诉lookup,这是properties类型的文件

# user.properties文件
[root@csq ~]# vim data/user.properties
user.name=csq
user.pass=111

# playbook文件
[root@csq ~]# vim g.yml
    - name: dd
- hosts: test
  remote_user: root
  tasks:
   - debug:
      msg: "user.name is {{ lookup('ini','user.name type=properties file=/root/data/user.properties') }}"

# 执行结果
[root@csq ~]# ansible-playbook g.yml 

PLAY [test] *************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************
ok: [192.168.200.20]

TASK [debug] ************************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "user.name is csq"
}

PLAY RECAP **************************************************************************************************************************
192.168.200.20             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

ini类型参数格式:

lookup('ini','key [type=<properties|ini>] [section=section] [file=file.ini] [re=true] [default=<defaultvalue>]')
# 每个参数都是可选的,没有传入的参数会使用默认值
参数名 默认值 参数含义
type ini 文件的类型
file ansible.ini 加载文件的名字
section global 默认的在哪个section里面查找key
re False key的正则表达式
default empty string key不存在时的返回值

lookup读取DNS解析的值

dig类型的lookup可以向DNS服务器查询指定域名的DNS记录。它可以查询任何DNS记录,包括正向反向查询

使用dig类型的lookup查询DNS,使用正向反向查询DNS解析,还可以指定查询的DNS服务器

# 首先安装dnspython因为需要用到这个Python库
[root@localhost ansible]# pip3.11 install dnspython
# 剧本文件
[root@localhost ansible]# vim test7.yml              
- hosts: test
  remote_user: root
  gather_facts: false
  tasks:
    - debug: msg="这是baidu.com的ipv4地址:{{lookup('dig','baidu.com')}}"
    - debug: msg="这是baidu.com的TXT记录:{{lookup('dig','baidu.com','qtype=TXT')}}"
    - debug: msg="这是baidu.com的TXT记录:{{lookup('dig','baidu.com./TXT')}}"
    - debug: msg="163.com的mx记录之一是:{{item}}"
      with_items: "{{lookup('dig','163.com./MX','wantlist=True')}}"
# 执行剧本
TASK [debug] ************************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "这是baidu.com的ipv4地址:110.242.68.66,39.156.66.10"
}

TASK [debug] ************************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "这是baidu.com的TXT记录:9279nznttl321bxp1j464rd9vpps246v,v=spf1 include:spf1.baidu.com include:spf2.baidu.com include:spf3.baidu.com include:spf4.baidu.com mx ptr -all,google-site-verification=GHb98-6msqyx_qqjGl5eRatD3QTHyVB6-xQ3gJB5UwM,_globalsign-domain-verification=qjb28W2jJSrWj04NHpB0CvgK9tle5JkOq-EcyWBgnE"
}

TASK [debug] ************************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "这是baidu.com的TXT记录:9279nznttl321bxp1j464rd9vpps246v,v=spf1 include:spf1.baidu.com include:spf2.baidu.com include:spf3.baidu.com include:spf4.baidu.com mx ptr -all,google-site-verification=GHb98-6msqyx_qqjGl5eRatD3QTHyVB6-xQ3gJB5UwM,_globalsign-domain-verification=qjb28W2jJSrWj04NHpB0CvgK9tle5JkOq-EcyWBgnE"
}

TASK [debug] ************************************************************************************************************************
ok: [192.168.200.20] => (item=10 163mx02.mxmail.netease.com.,10 163mx03.mxmail.netease.com.,50 163mx00.mxmail.netease.com.,10 163mx01.mxmail.netease.com.) => {
    "msg": "163.com的mx记录之一是:10 163mx02.mxmail.netease.com.,10 163mx03.mxmail.netease.com.,50 163mx00.mxmail.netease.com.,10 163mx01.mxmail.netease.com."
}

反向查询DNS

# 剧本文件
[root@localhost ansible]# vim test8.yml              
- hosts: test
  remote_user: root
  gather_facts: false
  tasks:
    - debug: msg="114.114.114.114反向查询DNS是:{{lookup('dig','114.114.114.114/PTR')}}"    
# 执行结果
TASK [debug] ************************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "114.114.114.114反向查询DNS是:public1.114dns.com."
}

指定查询的DNS服务器

    - debug: msg="使用8.8.8.8查询baidu.com的ipv4地址:{{lookup('dig','baidu.com','@8.8.8.8')}}"
# 执行结果
TASK [debug] ************************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "使用8.8.8.8查询baidu.com的ipv4地址:39.156.66.10,110.242.68.66"
}

过滤器

在 Ansible 中,过滤器(Filters)是一种功能强大的工具,用于在模板中处理变量的值。过滤器可以对变量进行转换、格式化、筛选和操作

过滤器使用的位置

quote过滤器的功能是给字符串加引号

[root@csq ~]# vim b.yml
- hosts: test2
  remote_user: root
  gather_facts: false
  vars:
    my_test_string: "This is the test string"
  tasks:
    - name: "quote {{ my_test_string }}"
      debug: msg="echo {{ my_test_string | quote }}"

# 执行结果
TASK [quote This is the test string] **********************************************************
ok: [192.168.200.30] => {
    "msg": "echo 'This is the test string'"
}

过滤器对普通变量的操作

default:为没有定义的变量提供默认值

因为变量some_undefined_varible表示没有定义,所以下面的任务会输出NONE

[root@csq ~]# vim c.yml   
- hosts: test
  remote_user: root
  gather_facts: false
  tasks:
  - name: output1
    debug: msg="{{ some_undefined_varible | default('NONE') }}"
# 执行结果
TASK [output1] ********************************************************************************
ok: [192.168.200.20] => {
    "msg": "NONE"
}

如果是远程主机fact里面的变量,当远程主机的fact变量为空一般都是显示的[]或者"",那么我不想让他显示这个空的

true:这是 default 过滤器的第二个参数,用于指示 Ansible 在判断变量是否为空时将空字符串、空列表、空字典等视为真实的空值。如果设置为 true,则 Ansible 会将这些空值视为真实的空值,否则会将其视为非空值。

[root@csq ~]# vim c.yml              
- hosts: test
  remote_user: root
  tasks:
  - name: output1
    debug: msg="{{ ansible_fibre_channel_wwn | default('NONE',true) }}"

# 执行结果

TASK [output1] ********************************************************************************
ok: [192.168.200.20] => {
    "msg": "NONE"
}

omit:忽略变量的占位符

与default一起使用时,如果某个变量没有定义,那么使用omit占位符,Ansible就会把这个对应的参数按照没用传这个参数的值来处理

[root@csq ~]# vim r.yml
- hosts: test
  remote_user: root
  tasks:
    - name: touch file
      file: dest={{item.path}} state=touch mode={{item.mode|default(omit)}}
      with_items:
       - path: /tmp/csq1
       - path: /tmp/csq2
         mode: "0444"
[root@csq ~]# ansible test -m shell -a "ls /tmp/csq* -la"     
192.168.200.20 | CHANGED | rc=0 >>
-rw-r--r--. 1 root root 0  52 13:58 /tmp/csq1
-r--r--r--. 1 root root 0  52 13:58 /tmp/csq2
# 文件/tmp/csq1没用定义参数mode,所以default(omit)会在没有定义mode时忽略mode变量
# ansible的file模块会按照没有传入mode这个参数来创建文件/tmp/csq1,/tmp/csq2定义了mode为0444
# 所以文件的权限为0444

mandatory:强制变量必须定义,否则报错

在ansible默认的配置中,如果变量没有定义,那么直接使用未定义的变量{{aaa-bbb-ccc}}会报错

如果ansible配置文件中使用了下面的配置,那么遇到未定义的变量时,ansible就不会报错

error_on_undefined_vars=False

如果你想要某一个变量必须定义,就可使用mandatory

[root@csq ~]# vim l.yml                    
- hosts: test
  remote_user: root
  vars:
    aaabbbccc: abc
  gather_facts: false
  tasks:
    - name: 定义了变量
      debug:
        msg: "{{aaabbbccc}}"
    - name: 未定义变量报错
      debug:
        msg: "{{aaa-bbb-ccc | mandatory}}"

# 执行结果
[root@csq ~]# ansible-playbook l.yml       

PLAY [test] *************************************************************************************************************************

TASK [定义了变量] *******************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "abc"
}

TASK [未定义变量报错] ***************************************************************************************************************
fatal: [192.168.200.20]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'aaa' is undefined. 'aaa' is undefined\n\nThe error appears to be in '/root/l.yml': line 10, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n        msg: \"{{aaabbbccc}}\"\n    - name: 未定义变量报错\n      ^ here\n"}

PLAY RECAP **************************************************************************************************************************
192.168.200.20             : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

bool:判断变量是否为布尔类型

bool的过滤器是playbook中判断条件bool类型的过滤器,其中bool类型的过滤器用来判断变量是否为布尔类型

[root@csq ~]# vim i.yml              
- hosts: test
  remote_user: root
  gather_facts: false
  vars:
    var1: "Test"
    var2: True
    var3: "True"
  tasks:
    - debug: msg=test
      when: var1 | bool
    - debug: msg=test
      when: var2 | bool
    - debug: msg=test
      when: var3 | bool
#  执行结果
TASK [debug] **************************************************************************************************************************
skipping: [192.168.200.20]

TASK [debug] **************************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "test"
}

TASK [debug] **************************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "test"
}

ternary:Playbook的条件表达式

ternary类似于编程语言中的类型表达式,(“A?B:C”)当条件为真时,返回一个值;当条件为假时,返回另一个值

[root@csq ~]# vim j.yml              
- hosts: test
  remote_user: root
  gather_facts: false
  vars:
    hostname: "csq"
  tasks:
  - name: if hostname = csq Yes if hostname = other No
    debug: msg="{{ (hostname == "csq") | ternary('Yes','No') }}"
# 执行结果
TASK [if hostname = csq Yes if hostname = other No] ***********************************************************************************
ok: [192.168.200.20] => {
    "msg": "Yes"
}

过滤器对文件路径的操作

Ansible为了方便文件及其路径进行操作,提供了一系列关于文件目录的操作,包括获取文件名,路径名,等等。

Linux文件路径的操作的过滤器如下:

  • basename:获取路径中的文件名
  • dirname:获取文件的目录
  • expanduser:扩展~为实际的目录
  • realpath:获取链接文件所指文件的真实路径
  • relpath:获得相对某一根目录的相对路径
  • splitext:把文件名用点号(.)分割成多个部分
[root@csq ~]# vim test1.yml              
- hosts: test
  remote_user: root
  gather_facts: false
  vars:
    linux_path: "/etc/csq/a.txt"
    linux_user_path: "~/data/my_test/file.txt"
    link_to_ansible_cfg: "/bin"
  tasks:
    - name: "获取Linux路径的文件名 {{linux_path}}"
      debug: msg="{{linux_path | basename}}"
    - name: "获取Linux路径的目录名 {{linux_path}}"
      debug: msg="{{linux_path | dirname}}"
    - name: "获取展开文件路径中的用户目录 {{linux_user_path}}"
      debug: msg="{{linux_user_path | expanduser}}"
    - name: "获取文件路径的真实路径 {{link_to_ansible_cfg}}"
      debug: msg="{{link_to_ansible_cfg | realpath}}"
    - name: "获取相对某一根目录的相对路径 {{linux_path}}"
      debug: msg="{{linux_path | relpath('/etc')}}"
    - name: "把文件名用点号(.)分隔成多个部分{{linux_path}}"
      debug: msg="{{linux_path | splitext}}"
# 执行结果
TASK [获取Linux路径的文件名 /etc/csq/a.txt] *******************************************************************************************
ok: [192.168.200.20] => {
    "msg": "a.txt"
}

TASK [获取Linux路径的目录名 /etc/csq/a.txt] *******************************************************************************************
ok: [192.168.200.20] => {
    "msg": "/etc/csq"
}

TASK [获取展开文件路径中的用户目录 ~/data/my_test/file.txt] ***************************************************************************
ok: [192.168.200.20] => {
    "msg": "/root/data/my_test/file.txt"
}

TASK [获取文件路径的真实路径 /bin] ****************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "/usr/bin"
}

TASK [获取相对某一根目录的相对路径 /etc/csq/a.txt] ************************************************************************************
ok: [192.168.200.20] => {
    "msg": "csq/a.txt"
}

TASK [把文件名用点号(.)分隔成多个部分/etc/csq/a.txt] **********************************************************************************
ok: [192.168.200.20] => {
    "msg": "('/etc/csq/a', '.txt')"
}

过滤器对字符串变量的操作

quote:给字符串加引号

[root@csq ~]# vim b.yml
- hosts: test2
  remote_user: root
  gather_facts: false
  vars:
    my_test_string: "This is the test string"
  tasks:
    - name: "quote {{ my_test_string }}"
      debug: msg="echo {{ my_test_string | quote }}"

# 执行结果
TASK [quote This is the test string] **********************************************************
ok: [192.168.200.30] => {
    "msg": "echo 'This is the test string'"
}

base64:得到字符串Base64编码

[root@csq ~]# vim test2.yml              
- hosts: test
  remote_user: root
  gather_facts: false
  vars:
    my_comment: "hello world"
    my_comment_base64: "aGVsbG8gd29ybGQ="
  tasks:
    - name: "获取base64编码{{my_comment}}"
      debug: msg="{{my_comment | b64encode}}"
    - name: "解码base64 {{my_comment_base64}}"
      debug: msg="{{my_comment_base64 | b64decode}}"
    - name: "获取uuid {{my_comment}}"
      debug: msg="{{my_comment | to_uuid}}"
# 执行结果
TASK [获取base64编码hello world] ******************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "aGVsbG8gd29ybGQ="
}

TASK [解码base64 aGVsbG8gd29ybGQ=] ****************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "hello world"
}

TASK [获取uuid hello world] ***********************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "9a129f19-657c-5ca0-80f4-31b29d10569c"
}

hash:获取字符串的哈希值

计算哈希值的算法有很多,如果sha1、md5、checksum等

[root@csq ~]# vim test3.yml              
- hosts: test
  remote_user: root
  gather_facts: false
  vars:
    my_password: "mypassword"
  tasks:
    - name: "获取字符串{{my_password}}的sha1 hash"
      debug: msg="{{my_password | hash('sha1')}}"
    - name: "获取字符串{{my_password}}的MD5 hash"
      debug: msg="{{my_password | hash('md5')}}"
    - name: "获取字符串{{my_password}}的checksum"
      debug: msg="{{my_password | checksum}}"
    - name: "获取字符串{{my_password}}的sha512 hash"
      debug: msg="{{my_password | password_hash('sha512')}}"
    - name: "获取字符串{{my_password}}的sha256 hash带有特定字符串"
      debug: msg="{{my_password | password_hash('sha256','mysecretsalt')}}"
# 执行结果
TASK [获取字符串mypassword的sha1 hash] ************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "91dfd9ddb4198affc5c194cd8ce6d338fde470e2"
}

TASK [获取字符串mypassword的MD5 hash] *************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "34819d7beeabb9260a5c854bc85b3e44"
}

TASK [获取字符串mypassword的checksum] *************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "91dfd9ddb4198affc5c194cd8ce6d338fde470e2"
}

TASK [获取字符串mypassword的sha512 hash] **********************************************************************************************

ok: [192.168.200.20] => {
    "msg": "$6$kM35/CEoWTM1xoIX$0HjNRHNwS01H2uH4Rik7h06E3DzDZpI9uHvg0NN0QE2kQOMKYwkN28kPKOuB9.0aShHv6CsFJAbAPnOCv1PZO0"
}

TASK [获取字符串mypassword的sha256 hash带有特定字符串] ********************************************************************************

ok: [192.168.200.20] => {
    "msg": "$5$mysecretsalt$HhobCuvPwbLCsdua9UNYk8C.EPib1CkzWvN23KBHYV2"
}

comment:把字符串变成代码注释的一部分

comment展示了将字符串转化为不同风格和格式注释的使用方法,最后一个是用户自定义的注释风格

[root@csq ~]# vim test4.yml              
    - name: "erlang 
- hosts: test
  remote_user: root
  gather_facts: false
  vars:
    my_comment: "hello world"
  tasks:
    - name: "Simple comment"
      debug: msg="{{my_comment | comment}}"
    - name: "C  comment"
      debug: msg="{{my_comment | comment('c')}}"
    - name: "cblock  comment"
      debug: msg="{{my_comment | comment('cblock')}}"
    - name: "erlang  comment"
      debug: msg="{{my_comment | comment('erlang')}}"
    - name: "xml  comment"
      debug: msg="{{my_comment | comment('xml')}}"
    - name: "customize comment"
      debug: msg="{{my_comment | comment('plain',prefix='######\n#',postfix='#\n######\n###\n#')}}"
# 执行结果
TASK [Simple comment] *****************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "#\n# hello world\n#"
}

TASK [C  comment] *********************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "//\n// hello world\n//"
}

TASK [cblock  comment] ****************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "/*\n *\n * hello world\n *\n */"
}

TASK [erlang  comment] ****************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "%\n% hello world\n%"
}

TASK [xml  comment] *******************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "<!--\n -\n - hello world\n -\n-->"
}

TASK [customize comment] **************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "######\n#\n# hello world\n#\n######\n###\n#"
}

regex:利用正则表达式对字符串进行替换

[root@csq ~]# vim test5.yml              
- hosts: test
  remote_user: root
  vars:
    my_comment: "hello world"
  gather_facts: false
  tasks:
    - name: "转换 ansible 为 able"
      debug: msg="{{'ansible' | regex_replace('^a.*i(.*)$','a\\1')}}"
    - name: "转换 foobar 为 bar"
      debug: msg="{{'foobar' | regex_replace('^f.*o(.*)$','\\1')}}"
    - name: "转换 localhost:80 为 localhost,80"
      debug: msg="{{'localhost:80' | regex_replace('^(?P<host>.+):(?P<port>\\d+)$','\\g<host>,\\g<port>') }}"
# 执行结果
TASK [转换 ansible 为 able] ***********************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "able"
}

TASK [转换 foobar 为 bar] *************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "bar"
}

TASK [转换 localhost:80 为 localhost,80] **********************************************************************************************
ok: [192.168.200.20] => {
    "msg": "localhost,80"
}

ip:判断字符串是否是合法的IP地址

[root@localhost ansible]# vim test6.yml              
- hosts: test
  remote_user: root
  gather_facts: false
  vars:
    ip_address1: "192.168.2455.1"
    ip_address2: "192.168.200.20"
    ip_addr_ipv6: "fe80::20c:29ff:fe4e:d6a9"
  tasks:
    - name: "判断{{ip_address1}}是否为合法ip"
      debug: msg="{{ ip_address1 | ipaddr}}"
    - name: "判断{{ip_address2}}是否为合法ip"
      debug: msg="{{ ip_address2 | ipaddr}}"
    - name: "判断{{ip_address2}}是否为ipv4地址"
      debug: msg="{{ ip_address2 | ipv4}}"
    - name: "判断{{ip_addr_ipv6}}是否为ipv6地址"
      debug: msg="{{ ip_addr_ipv6 | ipv6}}"
    - name: "判断{{'192.0.2.1/24' | ipaddr('address')}}是否为合法IP"
      debug: msg="{{'192.0.2.1/24' | ipaddr('address')}}"
# 执行结果
[root@localhost ansible]# ansible-playbook test6.yml 

TASK [判断192.168.2455.1是否为合法ip] ***********************************************************************************************

ok: [192.168.200.20] => {
    "msg": false
}

TASK [判断192.168.200.20是否为合法ip] ***********************************************************************************************

ok: [192.168.200.20] => {
    "msg": "192.168.200.20"
}

TASK [判断192.168.200.20是否为ipv4地址] *********************************************************************************************

ok: [192.168.200.20] => {
    "msg": "192.168.200.20"
}

TASK [判断fe80::20c:29ff:fe4e:d6a9是否为ipv6地址] ***********************************************************************************

ok: [192.168.200.20] => {
    "msg": "fe80::20c:29ff:fe4e:d6a9"
}

TASK [判断192.0.2.1是否为合法IP] ****************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "192.0.2.1"
}

过滤器对JSON的操作

format:将变量的值按照JSON/YAML格式输出

# 剧本文件
[root@localhost ansible]# vim test1.yml   
- hosts: test
  gather_facts: false
  vars:
    my_variable:
      key1: value1
      key2: value2
  tasks:
    - name: Print variable as JSON
      debug:
        msg: "{{ my_variable | to_json }}"

    - name: Print variable as YAML
      debug:
        msg: "{{ my_variable | to_yaml }}"
    - name: Print variable as Nice JSON
      debug:
        msg: "{{ my_variable | to_nice_json }}"

    - name: Print variable as Nice YAML
      debug:
        msg: "{{ my_variable | to_nice_yaml }}"
# 执行结果


TASK [Print variable as JSON] *******************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "{\"key1\": \"value1\", \"key2\": \"value2\"}"
}

TASK [Print variable as YAML] *******************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "{key1: value1, key2: value2}\n"
}

TASK [Print variable as Nice JSON] **************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "{\n    \"key1\": \"value1\",\n    \"key2\": \"value2\"\n}"
}

TASK [Print variable as Nice YAML] **************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "key1: value1\nkey2: value2\n"
}

query:在一个JSON对象里,搜索符合条件的属性,返回符合条件的属性数组

[root@localhost ansible]# vim test2.yml              
- name: Search for properties matching a condition in a JSON object
  hosts: localhost
  gather_facts: false
  vars:
    my_json:
      users:
        - name: John
          age: 30
        - name: Alice
          age: 25
        - name: Bob
          age: 35
  tasks:
    - name: Query JSON object
      debug:
        msg: "{{ my_json.users | json_query('[].name') }}"
# 执行结果
ok: [localhost] => {
    "msg": [
        "John",
        "Alice",
        "Bob"
    ]
}

过滤器对数据结构的操作

Ansible中的过滤器支持以下几种数据结构的操作

random:取随机数

[root@localhost ansible]# vim test3.yml              
- hosts: test
  remote_user: root
  gather_facts: false
  tasks:
    - name: 列表随机
      debug: msg="{{ ['a','b','c'] | random}}"
    - name: 随机数
      debug: msg="{{ 59 | random}} * * * * echo hello world"
    - name: random with step
      debug: msg="{{ 100 | random(step=10)}}"
    - name: random with start and step
      debug: msg="{{ 100 | random(2,10)}}"
    - name: random with start and step
      debug: msg="{{ 100|random(start=2,step=10)}}"
# 执行结果

TASK [列表随机] *********************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "b"
}

TASK [随机数] ***********************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "33 * * * * echo hello world"
}

TASK [random with step] *************************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "10"
}

TASK [random with start and step] ***************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "32"
}

TASK [random with start and step] ***************************************************************************************************
ok: [192.168.200.20] => {
    "msg": "72"
}

过滤器的链式/连续使用

ansible的过滤器是支持链式使用的,就是在一个{{}}中使用多个过滤器

[root@localhost ansible]# vim test4.yml              
- hosts: test
  remote_user: root
  vars:
    aaabbbccc: abc
  gather_facts: false
  tasks:
    - name: 判断变量是否存在,存在就使用base64加密该变量
      debug:
        msg: "{{aaabbbccc | mandatory | b64encode}}"
# 执行结果

TASK [判断变量是否存在,存在就使用base64加密该变量] *********************************************************************************
ok: [192.168.200.20] => {
    "msg": "YWJj"
}

常见插件类型

modules插件

模块插件是Ansible的核心成分,用于执行具体的任务。它们可以通过在任务中调用来提供丰富的功能,例如文件操作、软件包管理、配置管理等。

Inventory插件

主机清单插件用于动态生成Ansible的主机清单。它们可以从各种源(如INI文件、YAML文件、云服务提供商)读取主机信息,并动态生成可供Ansible使用的清单。

Action插件

和模块使用方法类似,只不过执行目标不是远程主机,而是在Ansible的控制节点(管理节点)本机上

Cache插件

为Facts(主机变量)提供缓存,以避免多次执行Playbook时搜集Facts

Callback插件

Ansible执行Playbook后,提供额外的行为,例如,将执行结果发送到E-mail中,或者将执行结果写入log中等等

connection插件

用于在Ansible连接远程主机时进行身份验证。认证插件允许使用不同的认证机制,如用户名/密码、私钥等

filters插件

过滤器插件用于对变量进行转换、过滤和操作。

lookup插件

文件查找插件用于在Ansible中查找文件和数据。它们可以从文件系统、远程主机或其它的数据源中查找所需的文件或数据

test插件

ansible Jinja2 test提供更多功能