Search code examples
arraysjsonansibletype-conversionruntime-error

Bad file descriptor in Ansible when read JSON content is numeric


Below is my JSON 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.host1.bank.com"
          }
        ]
      },
      {
        "server": [
          {
            "name": "myserv1"
          },
          {
            "ssl": [
              {
                "name": "myserv1"
              },
              {
                "login-timeout-millis": "25000"
              }
            ]
          },
          {
            "listen_port": "22421"
          }
        ]
      }
    ]
  }
]

Here is the code to get the listen port number form the json

---
  - name: ReadJsonfile
    hosts: localhost
    tasks:
      - name: Display the JSON file content
        shell: "cat this.json"
        register: result

      - name: save the Json data to a Variable as a Fact
        set_fact:
          jsondata: "{{ result.stdout | from_json }}"

      - name: create YML for server name with Listen port
        shell: "echo {{ server.0.name }}_httpport: {{ httpport[0].listen_port }}>>{{ playbook_dir }}/wlsdatadump.yml"
        loop: "{{ jsondata[1].domain }}"
        vars:
          server: "{{ item.server | selectattr('name', 'defined') }}"
          httpport: "{{ item.server | selectattr('listen_port', 'defined') | list }}"
        when: item.server is defined and (item.server | selectattr('listen_port', 'defined')) != []

I get the below error when executing the play

TASK [create YML for server name with Listen port] ************************************************************
skipping: [localhost] => (item={'name': 'mydom'})
skipping: [localhost] => (item={'domain-version': '12.2.1.3.0'})
failed: [localhost] (item={'server': [{'name': 'AdminServer'}, {'ssl': {'name': 'AdminServer'}}, {'listen_port': '12400'}, {'listen_address': 'mydom.host1.bank.com'}]}) => {"ansible_loop_var": "item", "changed": true, "cmd": "echo AdminServer_httpport: 12400>>/web/aes/admin/playbooks/dump.yml", "delta": "0:00:00.007706", "end": "2022-03-17 04:43:24.665832", "item": {"server": [{"name": "AdminServer"}, {"ssl": {"name": "AdminServer"}}, {"listen_port": "12400"}, {"listen_address": "mydom.host1.bank.com"}]}, "msg": "non-zero return code", "rc": 1, "start": "2022-03-17 04:43:24.658126", "stderr": "/bin/sh: 12400: Bad file descriptor", "stderr_lines": ["/bin/sh: 12400: Bad file descriptor"], "stdout": "", "stdout_lines": []}

If i change the port number from numeric to non-numeric say change "12400" to "portfirst" the playbook works fine.

This issue may have to do with the data type.

Can you please suggest how can i overcome this error?


Solution

  • you create a file listenport.j2 in folder templates:

    {% for item in jsondata[1].domain  if item.server is defined and (item.server | selectattr('listen_port', 'defined')) != [] %}
    {{ item.server.0.name }}_httpport:  {{ (item.server | selectattr('listen_port', 'defined')| list).0.listen_port }}
    {% endfor %}
    

    playbook:

      - name: ReadJsonfile
        hosts: localhost
        tasks:
          - name: Display the JSON file content
            shell: "cat ./file2.json"
            register: result
    
          - name: save the Json data to a Variable as a Fact
            set_fact:
              jsondata: "{{ result.stdout | from_json }}"
            
          - name: template
            template:
              src: listenport.j2
              dest: "{{ playbook_dir }}/wlsdatadump.yml"
    

    result in file wlsdatadump.yml:

    AdminServer_httpport:  12400
    myserv1_httpport:  22421
    

    if you are working on lot of hosts (not only on localhost) and just want to create the file on localhost, use delegate_to: localhost inside the task