Ansible-如何将selectattr与不同键的Yaml结合使用

时间:2019-09-09 17:05:44

标签: python ansible jinja2

im试图解析yaml并过滤Ansible中的某些键来尝试做一件简单的事情(我认为这应该很容易)。

我的Yaml文件如下:

---

- vm: "vm1"
  ip: 10.10.10.1
- vm: "vm2"
  ip: 10.10.10.2
- test_vm: something
- another_vm: something_other

所以我想的不是

这样的表达式
lookup('file','my_file.yaml') | from_yaml | selectattr('vm','search','vm1')|list

可以工作,但是会显示类似错误

fatal: [localhost]: FAILED! => {"msg": "Unexpected templating type error occurred on ({{ lookup('file','{{sysfile}}') | from_yaml | selectattr('vm','search','vm1')|list}}): expected string or bytes-like object"}

如果我删除了test_vm和another_vm键,它将正常工作。

ok: [localhost] => {
    "msg": [
        {
            "ip": "10.10.10.1",
            "vm": "vm1"
        }
    ]
}

如果我尝试搜索test_vm密钥,它将失败并显示:

fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'test_vm'\n\nThe error appears to be ...

selectattr过滤器是否期望列表中的所有字典都具有相同的键?因为无法使用Jinja2过滤自定义字典列表没有任何意义。

例如,如果我有一个更复杂的Yaml(不是该单位),我是否仅限于在Ansible中搜索和过滤?

例如,如果我有一个Yaml,看起来像这样:

---

- vm: "vm1"
  ip: 10.10.10.1
- vm: "vm2"
  ip: 10.10.10.2
- test_vm: something
   - process_1: X
   - process_2: Y
   - process_3: Z
- another_vm: something_other

例如,如何快速过滤process_2? 有办法吗?

非常感谢。

2 个答案:

答案 0 :(得分:1)

  

selectattr过滤器是否期望列表中的所有字典具有相同的键?

更准确地说,它期望列表中的所有字典都具有您选择的属性。这就是为什么它不适合您的情况。

幸运的是,还有其他过滤器可以完成这项工作。在这种情况下,我建议您看一下实现json_query

jmespath

以下是您上述要求中的几个示例。您的最后一个片段不是正确的Yaml,所以我按我认为应该的样子进行了纠正。

剧本:

---
- name: "Filter data with json_query"
  hosts: "localhost"
  gather_facts: false

  vars:
    test_var:
      - vm: "vm1"
        ip: 10.10.10.1
      - vm: "vm2"
        ip: 10.10.10.2
      - test_vm: something
        process_1: X
        process_2: Y
        process_3: Z
      - another_vm: something_other

  tasks:
    - name: Get object having vm==vm1
      debug:
        msg: "{{ test_var | json_query(\"[?vm=='vm1']\") | list }}"

    - name: Get all objects having vm attribute
      debug:
        msg: "{{ test_var | json_query(\"[?vm]\") | list }}"

    - name: Get all objects having process_2 attribute
      debug:
        msg: "{{ test_var | json_query(\"[?process_2]\") | list }}"

    - name: Get only a list of process_2 attributes
      debug:
        msg: "{{ test_var | json_query(\"[].process_2\") | list }}"

给出:

PLAY [Filter data with json_query] **************************************************************************************************************************************************************************************************************************************

TASK [Get object having vm==vm1] ****************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "ip": "10.10.10.1",
            "vm": "vm1"
        }
    ]
}

TASK [Get all objects having vm attribute] ******************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "ip": "10.10.10.1",
            "vm": "vm1"
        },
        {
            "ip": "10.10.10.2",
            "vm": "vm2"
        }
    ]
}

TASK [Get all objects having process_2 attribute] ***********************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "process_1": "X",
            "process_2": "Y",
            "process_3": "Z",
            "test_vm": "something"
        }
    ]
}

TASK [Get only a list of process_2 attributes] ***************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        "Y"
    ]
}

PLAY RECAP **************************************************************************************************************************************************************************************************************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

答案 1 :(得分:1)

更准确地说,它期望列表中的所有字典都具有您选择的属性。

并非所有过滤器功能都通过并非所有元素都定义的属性来选择对象,这并非100%正确:

{{ test_var | selectattr('vm','defined') |selectattr('vm','equalto','vm1') | list }}