无法在 ansible 中理想地解析 json 文件

unable to ideally parse a json file in ansible

下面是我的示例 JSON 文件。

[
   {
      "?xml": {
         "attributes": {
            "encoding": "UTF-8",
            "version": "1.0"
         }
      }
   },
   {
      "domain": [

         {
            "server": [
               {
                  "name": "myserv1"
               },
               {
                  "ssl": {
                     "name": "myserv1"
                  }
               },
               {
                  "log": [
                     {
                        "name": "myserv1"
                     },
                     {
                        "file-name": "/web/bea_logs/domains/mydom/myserv1/myserv1.log"
                     }
                  ]
               }
            ]
         },
         {
            "server": [
               {
                  "name": "myserv2"
               },
               {
                  "ssl": {
                     "name": "myserv2"
                  }
               },
               {
                  "log": [
                     {
                        "name": "myserv2"
                     },
                     {
                        "file-name": "/web/bea_logs/domains/mydom/myserv2/myserv2.log"
                     }
                  ]
               }
            ]
         }
      ]
   }
]

我的要求是读取 json 文件并将值存储在如下文件中:

myserv1_log: "/web/bea_logs/domains/mydom/myserv1/myserv1.log"
myserv2_log: "/web/bea_logs/domains/mydom/myserv2/myserv2.log"

<server>_log: <file-name>

这是我使用 JMESPath 查询读取 json 数据的 Ansible 游戏。

- name: Server Names and log details
  set_fact:
    serverlog:  "{{ jsondata | json_query(jmesquery) }}"
  vars:
    jmesquery: '[].domain[].server[*].log[*].[name, "file-name"]'

- name: Print all server names with log details
  debug:
    msg: "{{ item }}"
  with_items:
    - "{{ serverlog }}"

如您所见,我在输出中得到了几个 null

输出:

TASK [Print all server names with log details] *********************************
Wednesday 02 March 2022  03:17:45 -0600 (0:00:00.100)       0:00:04.730 *******
ok: [localhost] => (item=[]) => {
    "msg": []
}
ok: [localhost] => (item=[[['myserv1', None], [None, '/web/bea_logs/domains/mydom/myserv1/myserv1.log']]]) => {
    "msg": [
        [
            [
                "myserv1",
                null
            ],
            [
                null,
                "/web/bea_logs/domains/mydom/myserv1/myserv1.log"
            ]
        ]
    ]
}

我使用下面的方法摆脱了 null,但这也没有得到我想要的输出:

 - name: test
   set_fact:
     list2: "{{list2  + [item]}}"
   when: item != "null"
   with_items:
     - "{{serverlog}}"

 - name: Neww Print all server names with log details
   debug:
     msg: "{{ item }}"
   with_items:
     - "{{ list3 }}"

我也尝试了 Whosebug 上提出的解决方案,但出现错误:

"{{ jsondata | selectattr('domain', 'defined') | map(attribute='domain') | flatten | map(attribute='server') | flatten | selectattr('log', 'defined') | map(attribute='log') | map('combine') }}"

输出错误:

The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'server'\n\nThe error appears to be in....

任何较早的类似 post 都没有得到任何有效的解决方案,这就是我决定 post 此处的原因:

remove null elements from list ansible

请多多指教。

你的 json 的结构总是一样的,不需要使用 jmepath:

- hosts: localhost
  gather_facts: no
  vars:
    json: "{{ lookup('file', './file.json') | from_json }}"
  tasks:
    - name: display
      debug:
        msg: "name: {{ servername }} --> filename: {{ filename }}"
      loop: "{{ json[1].domain }}"
      vars:
        servername: "{{ item.server.0.name }}_log"
        filename: "{{ item['server'][2]['log'][1]['file-name'] }}"

结果:

ok: [localhost] => (item={'server': [{'name': 'myserv1'}, {'ssl': {'name': 'myserv1'}}, {'log': [{'name': 'myserv1'}, {'file-name': '/web/bea_logs/domains/mydom/myserv1/myserv1.log'}]}]}) => {
    "msg": "name: myserv1_log --> filename: /web/bea_logs/domains/mydom/myserv1/myserv1.log"
}
ok: [localhost] => (item={'server': [{'name': 'myserv2'}, {'ssl': {'name': 'myserv2'}}, {'log': [{'name': 'myserv2'}, {'file-name': '/web/bea_logs/domains/mydom/myserv2/myserv2.log'}]}]}) => {
    "msg": "name: myserv2_log --> filename: /web/bea_logs/domains/mydom/myserv2/myserv2.log"
}

一些解释: json 是一个包含 2 条记录的数组,一条带有键 ?xml,另一条带有键 domain

domain 是一个数组,键为 server

server 是一个包含不同键的数组 name, ssl and log

log 是一个具有不同键的数组 name and file-name


json[1].domain只保留包含domain的部分,json[0]包含json

的header

item.server.0.name (= item['server'][0]['name']) 是包含密钥 name

的记录服务器的第一项

item['server'][2]['log'][1]['file-name'] 是包含密钥 log 的记录服务器的第三项,日志的第二项包含密钥 file-name