Ansible filter item in list using variables+wildcard

Viewed 70
  1. I have the below lists stored in variable results_one.msg
[
  {
   "IP": [
      "192.168.1.100",
      "192.168.1.101"
    ],
   "Pool": "lan_pool_sftp",
   "Members": [
      "sftpnode01:5425",
      "sftpnode02:5425"
    ]
  },
{
   "IP": [
     "192.168.1.103",
     "192.168.1.104"
    ],
   "Pool": "icmp-net-pool",
   "Members": [
      "icmpnet01:8443",
      "icmpnet02:8443"
    ]
  }
]
  1. I have another variable node_name

I would like to get the Pool and Members information from above output, by querying one of the members name.

For example, if I assign the variable node_name: icmpnet02 I want to get the output stored as in respective variable names as below.

pool_name: icmp-net-pool
pool_members: [ icmpnet01:8443,icmpnet02:8443 ]

I tried as below and I'm unable to get it

- set_fact: 
    pool_name: "{{ item.Pool }}"
    pool_members: "{{ item.Members }}"
  with_items: "{{results_one.msg }}"
  when: 'item.Members.0 is defined and "node_name:*" in item.Members'
1 Answers
  1. Create a list of lists of members with their names only:
    _members_hostnames: "{{ results_one.msg | map(attribute='Members') 
      | map('map', 'regex_replace', '^(.*):.*$', '\\1') }}"

Gives:

    "_members_hostnames": [
        [
            "sftpnode01",
            "sftpnode02"
        ],
        [
            "icmpnet01",
            "icmpnet02"
        ]
    ]
  1. select the matching entry from your relevant variable, i.e.
    • create a list of tuples associating each original element with its counterpart calculated members hostnames
    • retain only element where hostname is present in the list
    • keep only the first element of tupple (i.e. the orginal entry)
    • keep only the first element from list
    _matching_entry: "{{ results_one.msg | zip(_members_hostnames) 
      | selectattr(1, 'contains', node_name) | map(attribute=0) | first }}"

gives

    "_matching_entry": {
        "IP": [
            "192.168.1.103",
            "192.168.1.104"
        ],
        "Members": [
            "icmpnet01:8443",
            "icmpnet02:8443"
        ],
        "Pool": "icmp-net-pool"
    }
  1. use the matching entry to extract whatever variable you need:
    pool_name: "{{ _matching_entry.Pool }}"
    pool_members: "{{ _matching_entry.Members }}"

Putting it all together in a test playbook:

---
- hosts: localhost
  gather_facts: false

  vars:
    # Your orig data on a single line for legibility
    results_one: {"msg":[{"IP":["192.168.1.100","192.168.1.101"],"Pool":"lan_pool_sftp","Members":["sftpnode01:5425","sftpnode02:5425"]},{"IP":["192.168.1.103","192.168.1.104"],"Pool":"icmp-net-pool","Members":["icmpnet01:8443","icmpnet02:8443"]}]}

    node_name: icmpnet02

    _members_hostnames: "{{ results_one.msg | map(attribute='Members') 
      | map('map', 'regex_replace', '^(.*):.*$', '\\1') }}"

    _matching_entry: "{{ results_one.msg | zip(_members_hostnames) 
      | selectattr(1, 'contains', node_name) | map(attribute=0) | first }}"

    pool_name: "{{ _matching_entry.Pool }}"
    pool_members: "{{ _matching_entry.Members }}"

  tasks:
    - debug:
        msg:
          - Pool name is {{ pool_name }}
          - Pool members are {{ pool_members }}

Which gives:

PLAY [localhost] ***********************************************************************************************************************************************************************************************************************

TASK [debug] ***************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        "Pool name is icmp-net-pool",
        "Pool members are ['icmpnet01:8443', 'icmpnet02:8443']"
    ]
}

PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  
Related