使用 jmespath 从 dict 中提取嵌套数组

Extract nested arrays from dict using jmespath

我有这个字典数组,其中包含来自 acme_certificate 的 Ansible 输出的数组,用于 DNS 挑战({{ le_challenges.results | json_query('[].challenge_data_dns') }}):

[
  {
    "_acme-challenge.foo.example.de": [
      "<token1>"
    ],
    "_acme-challenge.bar.example.de": [
      "<token2>",
      "<token3>"
    ]
  },
  {
    "_acme-challenge.baz.example.de": [
      "<token4>"
    ]
  }
]

因为我不需要单独的 _acme-challenge 记录,因为所有有问题的域都是针对单个 Route53 托管区域的 CNAME 别名,我需要将上述输出转换为此,以便我可以 运行 loop 超过 route53 个动作:

[
  "<token1>",
  "<token2>",
  "<token3>",
  "<token4>"
]

我在 Ansible 端尝试了所有可能的实验,包括 dict2listmap,但我找不到完成此转换的方法,因为包含令牌的键具有动态名称。有什么想法吗?

查询字典的任何键就像在 JMESPath 中使用 .* 一样简单,然后您将得到一个令牌列表列表。

有了这个,就有了一个展平运算符,它很简单[],你需要对你想要展平的每一层列表重复它。

这就是说,您必须先重置您所做的投影:使用 pipe operator|

所以,您的查询最终是:

[].challenge_data_dns.* | [][]

鉴于任务:

- debug:
    var: >-
      le_challenges.results | json_query(
        '[].challenge_data_dns.* | [][]'
      )
  vars:
    le_challenges:
      results:
        - challenge_data_dns:
            _acme-challenge.foo.example.de:
              - "<token1>"
            _acme-challenge.bar.example.de:
              - "<token2>"
              - "<token3>"
        - challenge_data_dns:
            _acme-challenge.baz.example.de:
              - "<token4>"

这产生:

? |-
  le_challenges.results | json_query(
    '[].challenge_data_dns.* | [][]'
  )
: - <token1>
  - <token2>
  - <token3>
  - <token4>

一般来说,在字典challenge_data_dns中,可能会有更多的属性伴随着_acme-challenge.*.example.de。然后,下面的表达式完成工作

    le_tokens: "{{ le_challenges.results|
                   map(attribute='challenge_data_dns')|
                   map('dict2items')|
                   map('selectattr', 'key', 'match', key_match)|
                   map('map', attribute='value')|
                   flatten }}"
    key_match: '_acme-challenge\.(.*)\.example\.de'

给予

  le_tokens:
  - <token1>
  - <token2>
  - <token3>
  - <token4>

备注

使用以下数据进行测试

  le_challenges:
    results:
    - challenge_data_dns:
        _acme-challenge.foo.example.de:
        - <token1>
        b2: test
    - challenge_data_dns:
        _acme-challenge.bar.example.de:
        - <token2>
        - <token3>
    - challenge_data_dns:
        _acme-challenge.baz.example.de:
        - <token4>