• Ansible的lookup,query,with_xxx


    环境

    • 管理节点:Ubuntu 22.04
    • 控制节点:CentOS 8
    • Ansible:2.15.6

    file lookup插件

    lookup插件从外部数据源(文件,数据库,API等)获取数据,它是在控制节点上运行的。

    下面以 file 插件为例。

    假设在控制节点上,有文件 /tmp/a.txt/tmp/b.txt

    /tmp/a.txt 内容如下:

    xxx
    yyyyy
    z
    
    • 1
    • 2
    • 3

    /tmp/b.txt 内容如下:

    good
    better
    best
    
    • 1
    • 2
    • 3

    单个文件

    lookup()

    可以通过 file 插件来读取文件内容:

    ---
    - hosts: all
      vars:
        var1: "{{ lookup('file', '/tmp/a.txt') }}"
      tasks:
        - name: task1
          debug:
            msg: "{{ var1 }}"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行结果如下:

    ......
    TASK [task1] ***************************************************************************************
    ok: [192.168.1.55] => {
        "msg": "xxx\nyyyyy\nz"
    }
    ......
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    查看 var1 类型:

    ......
        - name: task2
          debug:
            msg: "{{ var1 | type_debug }}"
    ......
    
    • 1
    • 2
    • 3
    • 4
    • 5

    运行结果如下:

    ......
    TASK [task2] ***************************************************************************************
    ok: [192.168.1.55] => {
        "msg": "AnsibleUnsafeText"
    }
    ......
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    可见,其类型是字符串( AnsibleUnsafeText )。

    with_file

    我们常见的 with_ ,都是使用了 xxx lookup。因此,二者通常可以互换。

    把上面的 lookup('file', '') 改为 with_file 的形式:

    ......
        - name: task1
          debug:
            msg: "{{ item }}"
          with_file: "/tmp/a.txt"
    ......
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    运行结果如下:

    TASK [task1] ***************************************************************************************
    ok: [192.168.1.55] => (item=xxx
    yyyyy
    z) => {
        "msg": "xxx\nyyyyy\nz"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    多个文件

    lookup()

    若想访问多个文件,只需对 lookup() 添加多个参数:

    ---
    - hosts: all
      vars:
        var1: "{{ lookup('file', '/tmp/a.txt', '/tmp/b.txt', wantlist=True) }}"
      tasks:
        - name: task1
          debug:
            msg: "{{ item }}"
          loop: "{{ var1 }}"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注意:一般情况下,对于多个文件,我们希望得到一个list,所以需要显式的指定 wantlist=True

    ......
    TASK [task1] ***************************************************************************************
    ok: [192.168.1.55] => (item=xxx
    yyyyy
    z) => {
        "msg": "xxx\nyyyyy\nz"
    }
    ok: [192.168.1.55] => (item=good
    better
    best) => {
        "msg": "good\nbetter\nbest"
    }
    ......
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    var1 的类型是list,可以遍历 var1 ,访问各个文件内容。

    如果不指定 wantlist=True

    ---
    - hosts: all
      vars:
        var1: "{{ lookup('file', '/tmp/a.txt', '/tmp/b.txt') }}"
      tasks:
        - name: task1
          debug:
            msg: "{{ var1 }}"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行结果如下:

    ......
    TASK [task1] ***************************************************************************************
    ok: [192.168.1.55] => {
        "msg": "xxx\nyyyyy\nz,good\nbetter\nbest"
    }
    ......
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    可见, 若不指定 wantlist=True ,则 var1 类型为字符串,会通过逗号,把多个文件的内容拼接在一起。

    当然,对于单个文件,也可以指定 wantlist=True ,只不过list里只有一个元素而已。

    with_file

    ---
    - hosts: all
      tasks:
        - name: task1
          debug:
            msg: "{{ item }}"
          with_file:
            - "/tmp/a.txt"
            - "/tmp/b.txt"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行结果如下:

    ......
    TASK [task1] ***************************************************************************************
    ok: [192.168.1.55] => (item=xxx
    yyyyy
    z) => {
        "msg": "xxx\nyyyyy\nz"
    }
    ok: [192.168.1.55] => (item=good
    better
    best) => {
        "msg": "good\nbetter\nbest"
    }
    ......
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    query

    query 是一个Jinja2函数,会调用lookup插件。 query 会返回一个list,也就是相当于lookup指定了 wantlist=True

    上面的例子,用query改写如下:

    ---
    - hosts: all
      vars:
        #var1: "{{ lookup('file', '/tmp/a.txt', '/tmp/b.txt', wantlist=True) }}"
        var1: "{{ query('file', '/tmp/a.txt', '/tmp/b.txt') }}"
      tasks:
        - name: task1
          debug:
            msg: "{{ item }}"
          loop: "{{ var1 }}"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    注: query 可简写为 q

    其它lookup插件

    具体参见文末的lookup插件列表。

    常见的比如 items lookup。

    ---
    - hosts: all
      vars:
        var1: "{{ query('items', 'aaa', 'bbb', 'ccc') }}"
        # var1: "{{ lookup('items', 'aaa', 'bbb', 'ccc', wantlist=True) }}" # 两种写法都可以
      tasks:
        - name: task1
          debug:
            msg: "{{ item }}"
          loop: "{{ var1 }}"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    也可以写成 with_items 的形式:

    ---
    - hosts: all
      tasks:
        - name: task1
          debug:
            msg: "{{ item }}"
          with_items:
            - "aaa"
            - "bbb"
            - "ccc"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    错误处理

    比如,要访问的文件不存在,则会报错。

    ---
    - hosts: all
      vars:
        var1: "{{ query('file','/tmp/a.txt', '/tmp/z.txt') }}"
      tasks:
        - name: task1
          debug:
            msg: "{{ item }}"
          loop: "{{ var1 }}"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    报错如下:

    ......
    TASK [task1] ***************************************************************************************
    fatal: [192.168.1.55]: FAILED! => {"msg": "An unhandled exception occurred while templating '{{ query('file','/tmp/a.txt', '/tmp/z.txt') }}'. Error was a , original message: The 'file' lookup had an issue accessing the file '/tmp/z.txt'. file not found, use -vvvvv to see paths searched"}
    
    PLAY RECAP *****************************************************************************************
    192.168.1.55               : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    可以添加一个 errors 参数:

    • strict :默认值,即报错
    • ignore :忽略错误
    • warn :警告

    指定 ignore

    ---
    - hosts: all
      vars:
        var1: "{{ query('file', '/tmp/a.txt', '/tmp/z.txt', errors='ignore') }}"
      tasks:
        - name: task1
          debug:
            msg: "{{ item }}"
          loop: "{{ var1 }}"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行结果如下:

    ......
    TASK [task1] ***************************************************************************************
    skipping: [192.168.1.55]
    
    PLAY RECAP *****************************************************************************************
    192.168.1.55               : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    指定 warn

    ---
    - hosts: all
      vars:
        var1: "{{ query('file', '/tmp/a.txt', '/tmp/z.txt', errors='warn') }}"
      tasks:
        - name: task1
          debug:
            msg: "{{ item }}"
          loop: "{{ var1 }}"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行结果如下:

    TASK [task1] ***************************************************************************************
    [WARNING]: Lookup failed but the error is being ignored: The 'file' lookup had an issue accessing
    the file '/tmp/z.txt'. file not found, use -vvvvv to see paths searched
    skipping: [192.168.1.55]
    
    PLAY RECAP *****************************************************************************************
    192.168.1.55               : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    参考

    • https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_lookups.html
    • https://docs.ansible.com/ansible/latest/plugins/lookup.html
    • https://docs.ansible.com/ansible/latest/collections/ansible/builtin/file_lookup.html
    • https://docs.ansible.com/ansible/latest/collections/ansible/builtin/index.html#lookup-plugins
  • 相关阅读:
    91. 解码方法
    【JavaSE】多线程篇(四)线程的同步机制、互斥锁、线程死锁与释放锁
    下载遥感数据慢的原因
    利用nicegui开发ai工具示例
    Disk Drill for Mac v5.0.1043 苹果数据恢复软件
    代码实现:求前N个数字的阶乘
    6 个意想不到的 JavaScript 问题
    Java多线程基础
    Redis中的事务可以满足ACID属性吗?
    维护表空间中的数据文件
  • 原文地址:https://blog.csdn.net/duke_ding2/article/details/134483726