【问题标题】:Extract nested dict value with conditions from JSON using JINJA2 in Ansible在 Ansible 中使用 JINJA2 从 JSON 中提取带有条件的嵌套 dict 值
【发布时间】:2019-05-23 02:17:50
【问题描述】:

我正在尝试从 Ansible 的 cloudfront_facts 中提取特定别名的 CDN 域名,输出如下(汇总):

{
  "cdn_facts": {
   "ansible_facts": {
    "cloudfront": {
      "summary": {
       "distributions": [
        {
          "Aliases": [
           "media.example.com"
          ],
          "DomainName": "a1b2c3d4e5f6g.cloudfront.net"
        },
        {
          "Aliases": [
           "example.com"
          ],
          "DomainName": "g7f6e5d4c3b2a.cloudfront.net"
        }
      ]
     }
    }
  }
}

换句话说,对于别名example.com,我想设置一个值为g7f6e5d4c3b2a.cloudfront.net 的事实。

我尝试了以下方法来尝试打印该值,但它只是生成一个空列表。

- debug:
    msg: "{{ cdn_facts.ansible_facts.cloudfront.summary.distributions | selectattr('Aliases[0]', 'equalto', 'example.com') | map(attribute='DomainName') | list }}"

我什至不知道如何调试它,因为cdn_facts.ansible_facts.cloudfront.summary.distributions 产生了一个dicts 数组,但selectattrmap 没有产生任何东西。

【问题讨论】:

    标签: python json ansible jinja2


    【解决方案1】:

    您的数据中没有任何内容具有名为 Aliases[0] 的属性,这就是您的 selectattr 过滤器失败的原因。

    对于从深度嵌套的字典中提取数据,json_query 过滤器通常是比尝试链接原生 Jinja 过滤器更好的选择。例如,给定别名example.com,下面的表达式将提取对应的DomainName属性:

    cdn_facts.ansible_facts.cloudfront.summary.distributions[?Aliases[0] == `example.com`]|[0].DomainName
    

    我们可以在这样的剧本中使用它:

    ---
    - hosts: localhost
      gather_facts: false
      tasks:
        - include_vars:
            file: data.json
            name: data
    
        - debug:
            msg: >-
              {{ item }} ->
              {{
              (data|json_query('cdn_facts.ansible_facts.cloudfront.summary.distributions[?Aliases[0] == `{}`]|[0].DomainName'.format(item)))
              }}
          loop:
            - media.example.com
            - example.com
    

    将输出:

    TASK [debug] **********************************************************************************************************************************************************************************
    ok: [localhost] => (item=media.example.com) => {
        "msg": "media.example.com -> a1b2c3d4e5f6g.cloudfront.net"
    }
    ok: [localhost] => (item=example.com) => {
        "msg": "example.com -> g7f6e5d4c3b2a.cloudfront.net"
    }
    

    json_query 模块使用jmespath 搜索语法。您可以通过将数据粘贴到 https://jmespath.org 的文本框中,然后在其上方的字段中输入搜索表达式来试验 jmespath 表达式。或者,您可以获取jpterm 命令行工具。

    【讨论】:

    • 非常感谢!我需要一个用于?Aliases[0] == '{}' 中的谓词的变量,因此最终首先使用set_fact 保存查询,然后将事实传递给json_query。像魅力一样工作!
    猜你喜欢
    • 1970-01-01
    • 2014-09-03
    • 2023-02-04
    • 1970-01-01
    • 1970-01-01
    • 2020-03-09
    • 1970-01-01
    • 1970-01-01
    • 2021-05-01
    相关资源
    最近更新 更多