SantaXL
SantaXL

Reputation: 664

Exclude AnsibleUndefined from a list

Relevant part of task:

- name: Get join-token for worker nodes
  set_fact:
    join_token_worker: "{{ ansible_play_hosts_all | map('extract', hostvars, ['result', 'swarm_facts', 'JoinTokens', 'Worker']) }}"
  run_once: true

- debug:
    msg: "{{ join_token_worker }}"
  run_once: true

And the output looks like this:

TASK [deploy_docker : Get join-token for worker nodes] ********************************************************************************************************************************************************************************************************************************************************
ok: [eu-central-1a-01]

TASK [deploy_docker : debug] **********************************************************************************************************************************************************************************************************************************************************************************
ok: [eu-central-1a-01] => {
    "msg": "[AnsibleUndefined, AnsibleUndefined, AnsibleUndefined, 'SWMTKN-1-2xgm1l987hh18gbq0tc8vrwn209qlxge6nkwdq4pof2zd4e2vs-7f7ig2ama5amqq8iuii4o8xxo', AnsibleUndefined, AnsibleUndefined, 'SWMTKN-1-2xgm1l987hh18gbq0tc8vrwn209qlxge6nkwdq4pof2zd4e2vs-7f7ig2ama5amqq8iuii4o8xxo', AnsibleUndefined, AnsibleUndefined]"
}

I want to extract the token from this list - but I don't know how to filter out AnsibleUndefined value. I am using docker_swarm module to get result.

Upvotes: 4

Views: 2077

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 68024

Let's minimize the case. For example, the playbook

- hosts: h1,h2,h3
  gather_facts: false
  vars:
    d2:
      h1:
        k1:
          k2: v1
      h2:
        k1:
          kX: v2
      h3:
        k1:
          k2: v3
  tasks:
    - debug:
        msg: "{{ ansible_play_hosts_all|
                 map('extract', d2, ['k1', 'k2'])|
                 list }}"
      run_once: true

gives

  msg: '[''v1'', Undefined, ''v3'']'

There are more options for how to "Exclude AnsibleUndefined from a list".

  1. Use select (credit @mdaniel)
    - debug:
        msg: "{{ ansible_play_hosts_all|
                 map('extract', d2, ['k1', 'k2'])|
                 select|
                 list }}"
      run_once: true

gives

  msg:
  - v1
  - v3
  1. Use regex_replace
    - debug:
        msg: "{{ ansible_play_hosts_all|
                 map('extract', d2, ['k1', 'k2'])|
                 map('regex_replace', '(.*)', '\\1')|
                 list }}"
      run_once: true

gives

  msg:
  - v1
  - ''
  - v3
  1. If you want to create a dictionary iterate the hosts. For example
    - set_fact:
        worker_dict: "{{ worker_dict|default({})|
                         combine({item: d2[item].k1.k2|default('')}) }}"
      loop: "{{ ansible_play_hosts_all }}"
      run_once: true

gives

  worker_dict:
    h1: v1
    h2: ''
    h3: v3

Upvotes: 3

Related Questions