1

I'm trying to write a playbook that creates a Docker Swarm cluster from my four separate Docker hosts. As part of this, I'm gathering the Ansible hostnames and specific ethernet device IPv4 addresses from each node via Ansible facts and creating a dictionary:

- name: "Clear swarm_ips dictionary"
 set_fact:
    swarm_ips: "{{ swarm_ips | default([]) }}"


- name: "Create dictionary with enp42s0 IP and hostname of manager"
 set_fact:
    swarm_ips: "{{ swarm_ips | combine ({item.key : item.value}) }}"
 with_items:
    - { 'key': '{{ ansible_facts.hostname | string }}.ip' , 'value': '{{ ansible_facts.enp42s0.ipv4.address | string }}' }
 when: (ansible_facts.hostname == "manager") 

    
- name: "Add eth0 IP and hostname of worker[1,2] to swarm_ips"
 set_fact:
    swarm_ips: "{{ swarm_ips | combine ({item.key : item.value}) }}"
 with_items:
    - { 'key': '{{ ansible_facts.hostname | string }}.ip' , 'value': '{{ ansible_facts.eth0.ipv4.address | string }}' }
 when: (ansible_facts.hostname == "worker1") or 
       (ansible_facts.hostname == "worker2") 

- name: "Add br0 IP and hostname of worker0 to swarm_ips dictionary"
 set_fact:
    swarm_ips: "{{ swarm_ips | combine ({item.key : item.value}) }}"
 with_items:
    - { 'key': '{{ ansible_facts.hostname | string }}.ip' , 'value': '{{ ansible_facts.br0.ipv4.address | string }}' }
 when: (ansible_facts.hostname == "worker0")

- name: "Echo IP for all nodes from swarm_ips dict"
 debug: 
    var: swarm_ips 

I expect the output of the last step in the play to be something like what follows:

ok: {
    "swarm_ips": {
        "manager.ip": "10.0.1.203"
        "worker0.ip": "10.0.1.42"
        "worker1.ip": "10.0.1.201"
        "worker2.ip": "10.0.1.252"                
    }
}

Instead I get

ok: [manager.local] => {
    "swarm_ips": {
        "manager.ip": "10.0.1.203"
    }
}
ok: [worker0.local] => {
    "swarm_ips": {
        "worker0.ip": "10.0.1.42"
    }
}
ok: [worker1.local] => {
    "swarm_ips": {
        "worker1.ip": "10.0.1.201"
    }
}
ok: [worker2.local] => {
    "swarm_ips": {
        "worker2.ip": "10.0.1.252"
    }
}

There's likely a way I could run some or all of this on localhost and use hostvars to get information about the cluster hosts, but I think this should also work as I expect. What am I missing?

1 Answer 1

1

Extract the dictionaries swarm_ips from hostvars and combine them, e.g.

    - set_fact:
        swarm_ips: "{{ ansible_play_hosts|
                       map('extract', hostvars, 'swarm_ips')|
                       combine }}"
      run_once: true

gives

  swarm_ips:
    manager.ip: 10.0.1.203
    worker0.ip: 10.0.1.42
    worker1.ip: 10.0.1.201
    worker2.ip: 10.0.1.252
1
  • I appreciate this. Reading up about how to use map, extract and run_once. Commented Sep 23, 2021 at 13:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .