通过将 dict2items 和 JMESPath 与 ansible 相结合,从复杂 json 中查询键

query key from complex json by combining dict2items and JMESPath with ansible

我正在寻找基于查询结果的 return 值,到目前为止我没有得到想要的结果。 json 看起来像这样并且来自 ansible var

{
  "header": {
    "nodes": {
        "node1": {
            "last_shutdown": "date",
            "level": {
                "kind_node": {}
            },
            "state": {
                "running": "true",
                "more": {
                    "type": "admin"
            }
        }
    },
        "node2": {
            "last_shutdown": "date",
            "level": {
                "kind_node": {}
            },
            "state": {
                "running": "true",
                "more": {
                    "type": "engine"
            }
        }
    },
        "node3": {
            "last_shutdown": "date",
            "level": {
                "kind_node": {}
            },
            "state": {
                "running": "true",
                "more": {
                    "type": "engine"
            }
        }
      }
    }
  }
}
  

到目前为止,我已经尝试使用 dict2items 但没有成功。目前,我得到一个空列表。

     set_fact:
       my_var: "{{ nodes | dict2items | json_query('[?value.state.more.type==`admin`]') }}"

基本上,这个任务应该设置 my_var ==> node1 因为它是管理员。非常感谢任何帮助。

您不需要 json_query。它会起作用,但我强烈建议您仅在默认核心 ansible 过滤器根本无法完成工作时才使用它。

此外,您的 jmespath 表达式(我没有测试验证)将 return 匹配参数的元素的完整列表,而不仅仅是节点名称。

简而言之(注意:已更新,即使某些元素不包含 state 键内的 more 属性,它也能正常工作)

- set_fact:
    my_var: >-
      {{
        nodes 
        | dict2items
        | selectattr('value.state.more', 'defined')
        | selectattr('value.state.more.type', '==', 'admin')
        | map(attribute='key')
        | first
      }}

换句话说:

  1. 将 dict 转换为列表或 key/value
  2. select 只有定义了 value.state.more 的元素
  3. select 只有在 value.state.more.type 参数中具有 "admin" 的元素
  4. 仅提取每个元素的 key 参数
  5. 获取列表中的第一个元素