代码之家  ›  专栏  ›  技术社区  ›  Edward Q. Bridges

在Ansible中使用JINJA2从JSON中提取带条件的嵌套dict值

  •  0
  • Edward Q. Bridges  · 技术社区  · 7 年前

    cloudfront_facts ,具有以下(汇总)输出:

    {
      "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 生成一个dict数组,但 selectattr 和 map 我们什么也不生产。

    0 回复  |  直到 7 年前
        1
  •  3
  •   larsks    7 年前

    数据中没有名为的属性 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_查询 jmespath 搜索语法。您可以通过将数据粘贴到 https://jmespath.org 然后在上面的字段中输入搜索表达式。或者,您可以抓住 jpterm 命令行工具。