Search code examples
jsonparsingansiblejmespath

Unable to read json data in ansible play


I have the below json data file:

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

         {
            "name": "mydom"
         },
         {
            "domain-version": "12.2.1.3.0"
         },

         {
            "server": [
               {
                  "name": "AdminServer"
               },
               {
                  "ssl": {
                     "name": "AdminServer"
                  }
               },
               {
                  "listen-port": "12400"
               },
               {
                  "listen-address": "mydom.myserver1.mybank.com"
               }
            ]
         },
         {
            "server": [
               {
                  "name": "SERV01"
               },
               {
                  "log": [
                     {
                        "name": "SERV01"
                     },
                     {
                        "file-name": "/web/bea_logs/domains/mydom/SERV01/SERV01.log"
                     }
                  ]
               },
               {
                  "listen-port": "12401"
               },

               {
                  "listen-address": "mydom.myserver1.mybank.com"
               },

               {
                  "server-start": [
                     {
                        "java-vendor": "Sun"
                     },
                     {
                        "java-home": "/web/bea/platform1221/jdk"
                     }
                  ]
               }
            ]
         },
         {
            "server": [
               {
                  "name": "SERV02"
               },
               {
                  "log": [
                     {
                        "name": "SERV02"
                     },
                     {
                        "file-name": "/web/bea_logs/domains/mydom/SERV02/SERV02.log"
                     }
                  ]
               },
               {
                  "listen-port": "12401"
               },

               {
                  "listen-address": "mydom.myhost2.mybank.com"
               },
               {
                  "server-start": [

                     {
                        "java-home": "/web/bea/platform1221/jdk"
                     }                  ]
               }
            ]
         }

      ]
   }
]

I wish to display all the server names and their respective port numbers.

Below is my failed attempt to display all the server names viz

AdminServer
SERV01
SERV02

My playbook:

tasks:

  - name: Read the JSON file content in a variable
    shell: "cat {{ playbook_dir }}/tmpfiles/{{ Latest_Build_Number }}/testme.json"
    register: result

  - name: Server Names
    set_fact:
      servernames:  "{{ jsondata | json_query(jmesquery) }}"
    vars:
      jmesquery: '*.domain.server[*].name'

  - name: Server Names and Ports
    set_fact:
      serverinfo:  "{{ jsondata | json_query(jmesquery) }}"
    vars:
      jmesquery: '*.server[*].[name, port]'


  - name: Print all server names
    debug:
      msg: "{{ item}}"
    with_items:
      - "{{ servernames }}"

I also tried the below:

      jmesquery: 'domain.server[*].name'

There is no error but no data in the output as well. Output below:

TASK [Print all server names] *********************************************************************************
Monday 21 February 2022  03:07:47 -0600 (0:00:00.129)       0:00:03.590 *******
ok: [localhost] => (item=) => {
    "msg": ""
}

Can you please suggest how can I get the desired data?


Solution

  • lot of solutions, one with jmespath, you could try this:

    
      tasks:
    
        - name: Read the JSON file content in a variable
          shell: "cat testme.json"
          register: result
    
        - name: jsondata
          set_fact:
            jsondata:  "{{ result.stdout | from_json }}"
           
    
        - name: Server Names
          set_fact:
            servernames:  "{{ servernames | default([]) + [dict(name=item[0], port=item[1])] }}"
          loop: "{{ jsondata | json_query(jmesquery0) | zip(jsondata | json_query(jmesquery1)) | list }}"
          vars:
            jmesquery0: '[].domain[].server[].name'
            jmesquery1: '[].domain[].server[]."listen-port"'
    
        - name: debug result
          debug:
            msg: "{{ servernames }}"
    

    result:

    
    ok: [localhost] => {
        "msg": [
            {
                "name": "AdminServer",
                "port": "12400"
            },
            {
                "name": "SERV01",
                "port": "12401"
            },
            {
                "name": "SERV02",
                "port": "12401"
            }
        ]
    }