Python Ansible-如何将selectattr与不同键的yaml一起使用

Python Ansible-如何将selectattr与不同键的yaml一起使用,python,ansible,jinja2,Python,Ansible,Jinja2,我正在努力做一件简单的事情(我认为这应该很容易),解析yaml并过滤Ansible中的一些键 我的yaml文件如下所示: --- - vm: "vm1" ip: 10.10.10.1 - vm: "vm2" ip: 10.10.10.2 - test_vm: something - another_vm: something_other --- - vm: "vm1" ip: 10.10.10.1 - vm: "vm2" ip: 10.10.10.2 - test_vm:

我正在努力做一件简单的事情(我认为这应该很容易),解析yaml并过滤Ansible中的一些键

我的yaml文件如下所示:

---

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

- 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
所以我觉得比一个表情更像

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和另一个_-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 filter是否希望列表中的所有DICT都具有相同的键?因为不能使用Jinja2筛选自定义DICT列表没有任何意义

例如,如果我有一个更复杂的yaml(不是那个平面),我是否仅限于在Ansible中搜索和过滤

例如,如果我有一个yaml,如下所示:

---

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

- 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
例如,如何快速筛选流程_2? 有办法吗

先谢谢你

selectattr
filter是否希望列表中的所有dict都具有相同的键

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

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

以下是从您的上述要求中选取的一些示例。您的最后一个代码片段不是正确的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
更准确地说,它期望列表中的所有dict都具有您选择的属性

并非所有过滤器函数都是100%正确的,通过并非所有元素都定义的属性选择对象:

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

thx@Zeitounator。我已经看过json_查询并解决了我的问题。但我很高兴你的回答。很好的例子。糟糕的是,jmespath中的过滤器不太具有解释性。例如,我在用逻辑或字典进行过滤时遇到了麻烦。无论如何,最终我找到了它,使用contains,但仍然…Jinja2和jmespath可能会更好。