Ansible - 'dict object' has no attribute 'key'

Viewed 1308

I have an XML File that looks like this:

<nodes>
  <switch1>
    <node_type>router</node_type>
  </switch1>
  <switch2>
    <node_type>apic</node_type>
  </switch2>
</nodes>

The simple goal is to get all the node names (switch1, switch2) with a simple Ansible (2.9) task. I get all the Node names from this file with the XML module:

- name: get nodes from xml
  xml:
    path: "/nodes.xml"
    xpath: "/nodes/*[node_type='apic']"
    content: attribute
  register: nodes
  delegate_to: localhost

And when i try to debug the output and filter the node name, i get very weird outputs. My debugging looks like this:

- name: debugging
  debug:
    msg: "{{item}}"
  loop: "{{nodes.matches}}"
  delegate_to: localhost

And I get this output:

"msg": {
        "switch1": {}
}

This output is so close to my desired solution, but i cannot get Ansible to only output "switch1". Whether with "item.key" or "item.value", not even "item[0]" or something like that seems to work. And when i try to debug "{{item.key}}" i get this output:

"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'key'

When i try debugging "item.keys" i get this output:

"msg": "<built-in method keys of dict object at 0x7f6000b420d8>"

I cannot believe the struggle i have to go through for something simple like this. I am open to suggestions about alternatives to Ansible.

2 Answers

We can use an intermediate set_fact task to create a variable using the nodes.matches registered variable.

Each item within this list is a dict of "key": "value", where "key" is the name of the switch (switch2). So we could use the dict2items filter to get the name of the switch in the key, and the empty hash ({}) in value.

    - set_fact:
        nodes_dict: "{{ item | dict2items }}"
      loop: "{{ nodes.matches }}"

    - debug:
        msg: "apic: {{ item.key }}"
      loop: "{{ nodes_dict }}"
      loop_control:
        label: "{{ item.key }}"

Gives:

ok: [localhost] => (item=switch2) => {
    "msg": "apic: switch2"
}

I solved the problem: use with_dict instead of loop

Related