如何在Ansible中从json输出生成特定的字典

58wvjzkj  于 2022-11-19  发布在  其他
关注(0)|答案(2)|浏览(163)

我有一个Ansible作业运行在2个或更多的url上。每个url返回相同的变量,但值不同。下面是该作业的JSON数据注册表:

{
  "msg": {
    "results": [
      {
        "url": "http://0.0.0.1:xxx1",
        "othervar": "othervar",
        "othervar2": "othervar2",
        "json": {
          "messages": [
            {
              "message": "This is message number 1",
              "message2": "This is message2 number 1"
            },
            {
                "message": "This is message number 2",
                "message2": "This is message2 number 2"
            },
            {
                "message": "This is message number 3",
                "message2": "This is message2 number 3"
            }
          ]
        }
      },
      {
        "url": "http://0.0.0.2:xxx2",
        "othervar": "othervar",
        "othervar2": "othervar2",
        "json": {
          "messages": [
            {
              "message": "This is message number 1",
              "message2": "This is message2 number 1"
            },
            {
                "message": "This is message number 2",
                "message2": "This is message2 number 2"
            },
            {
                "message": "This is message number 3",
                "message2": "This is message2 number 3"
            }
          ]
        }
      }
    ]
  }
}

我想创建一个只包含url变量以及messagemessage2变量的特定dict。对于预期结果,我有两种选择:
备选案文1:

"message": [
    {
      "url": "http://0.0.0.1:xxx1",
      "content": [
          {
            "message": "This is message number 1",
            "message2": "This is message2 number 1"
          },
          {
              "message": "This is message number 2",
              "message2": "This is message2 number 2"
          },
          {
              "message": "This is message number 3",
              "message2": "This is message2 number 3"
          }
        ]
    },
    {
        "url": "http://0.0.0.2:xxx2",
        "content": [
            {
              "message": "This is message number 1",
              "message2": "This is message2 number 1"
            },
            {
                "message": "This is message number 2",
                "message2": "This is message2 number 2"
            },
            {
                "message": "This is message number 3",
                "message2": "This is message2 number 3"
            }
          ]
      }

备选案文2:

"message": [
  {
    "url": "http://0.0.0.0:xxx1",
    "message": "This is message number 1",
    "message2": "This is message2 number 1"
  },
  {
    "url": "http://0.0.0.0:xxx1",
    "message": "This is message number 2",
    "message2": "This is message2 number 2"
  },
  {
    "url": "http://0.0.0.0:xxx1",
    "message": "This is message number 2",
    "message2": "This is message2 number 2"
  },
  {
    "url": "http://0.0.0.0:xxx2",
    "message": "This is message number 1",
    "message2": "This is message2 number 1"
  },
  {
    "url": "http://0.0.0.0:xxx2",
    "message": "This is message number 2",
    "message2": "This is message2 number 2"
  },
  {
    "url": "http://0.0.0.0:xxx2",
    "message": "This is message number 2",
    "message2": "This is message2 number 2"
  }
]

我可以得到每个变量(url,message,message2),但我如何将它们合并到一个像选项1或选项2的dict中?

dwthyt8l

dwthyt8l1#

最简单的方法是从最接近原始数据的选项1开始。例如,您可以在您的剧本中将其声明为var:

my_results: "{{ results | json_query('[].{\"url\": url, \"content\": json.     messages}') }}"
  • 请注意,json_query需要community.general集合(通常在安装了ansible meta包的情况下可用)和pip install jmespath*

这将给出(调试上述变量):

TASK [debug] *******************************************************************
ok: [localhost] => {
    "my_results": [
        {
            "content": [
                {
                    "message": "This is message number 1",
                    "message2": "This is message2 number 1"
                },
                {
                    "message": "This is message number 2",
                    "message2": "This is message2 number 2"
                },
                {
                    "message": "This is message number 3",
                    "message2": "This is message2 number 3"
                }
            ],
            "url": "http://0.0.0.1:xxx1"
        },
        {
            "content": [
                {
                    "message": "This is message number 1",
                    "message2": "This is message2 number 1"
                },
                {
                    "message": "This is message number 2",
                    "message2": "This is message2 number 2"
                },
                {
                    "message": "This is message number 3",
                    "message2": "This is message2 number 3"
                }
            ],
            "url": "http://0.0.0.2:xxx2"
        }
    ]
}

从这里开始,如果你需要在看起来像选项2的结构上循环,使用subelements查找很容易实现:

- name: loop on a structure looking like option 2
      debug:
        msg:
          - "url is {{ item.0.url }}"
          - "message one is {{ item.1.message }}"
          - "message two is {{ item.1.message2 }}"
      loop: "{{ q('subelements', my_results, 'content') }}"
      loop_control:
        label: "{{ item.0.url }}"

其给出:

TASK [loop on a structure looking like option 2] *******************************
ok: [localhost] => (item=item.0.url) => {
    "msg": [
        "url is http://0.0.0.1:xxx1",
        "message one is This is message number 1",
        "message two is This is message2 number 1"
    ]
}
ok: [localhost] => (item=item.0.url) => {
    "msg": [
        "url is http://0.0.0.1:xxx1",
        "message one is This is message number 2",
        "message two is This is message2 number 2"
    ]
}
ok: [localhost] => (item=item.0.url) => {
    "msg": [
        "url is http://0.0.0.1:xxx1",
        "message one is This is message number 3",
        "message two is This is message2 number 3"
    ]
}
ok: [localhost] => (item=item.0.url) => {
    "msg": [
        "url is http://0.0.0.2:xxx2",
        "message one is This is message number 1",
        "message two is This is message2 number 1"
    ]
}
ok: [localhost] => (item=item.0.url) => {
    "msg": [
        "url is http://0.0.0.2:xxx2",
        "message one is This is message number 2",
        "message two is This is message2 number 2"
    ]
}
ok: [localhost] => (item=item.0.url) => {
    "msg": [
        "url is http://0.0.0.2:xxx2",
        "message one is This is message number 3",
        "message two is This is message2 number 3"
    ]
}

以下是完整测试的行动手册:

---
- hosts: localhost
  gather_facts: false

  vars:
    # Your orig data minified
    results: [{"url":"http://0.0.0.1:xxx1","othervar":"othervar","othervar2":"othervar2","json":{"messages":[{"message":"This is message number 1","message2":"This is message2 number 1"},{"message":"This is message number 2","message2":"This is message2 number 2"},{"message":"This is message number 3","message2":"This is message2 number 3"}]}},{"url":"http://0.0.0.2:xxx2","othervar":"othervar","othervar2":"othervar2","json":{"messages":[{"message":"This is message number 1","message2":"This is message2 number 1"},{"message":"This is message number 2","message2":"This is message2 number 2"},{"message":"This is message number 3","message2":"This is message2 number 3"}]}}]

    my_results: "{{ results | json_query('[].{\"url\": url, \"content\": json.messages}') }}"

  tasks:
    - name: debug my_results var to check
      debug:
        var: my_results

    - name: loop on a structure looking like option 2
      debug:
        msg:
          - "url is {{ item.0.url }}"
          - "message one is {{ item.1.message }}"
          - "message two is {{ item.1.message2 }}"
      loop: "{{ q('subelements', my_results, 'content') }}"
      loop_control:
        label: item.0.url
kwvwclae

kwvwclae2#

下面的代码加载输入json,然后创建一个新数组,其结构与选项1中要求的结构相同,方法是在迭代消息列表时创建新项:

---
- name: Playbook for infinispan Hosts
  hosts: localhost
  tasks:
    - name: load json from file
      shell: cat test.json
      register: result
    - name: save the input json data to a variable
      set_fact:
        jsondata: "{{ result.stdout | from_json }}"
    - name: display the input dict
      debug:
        var: jsondata
    - name: parse the json into new array
      set_fact:
        message: "{{ message|default([]) + [ { 'url': item.url, 'content': item.json.messages }  ] }}"
      loop: "{{ jsondata.msg.results }}"
    - name: display the resulting data structure
      debug:
        var: message

相关问题