-1

I need to create a variable of ip addresses that are derived from the run state of all hosts. I expect to insert a new string value and have it appended to the list.

When I run the following ansible-playbook, it creates what looks to be a new list instance for each host instead of modifying the playbook level vars.

My understanding is the set_fact below should concatenate the lists and assign them back to the play scoped var ip_list_from_terraform. Why am I getting host scoped results?

---
  - name: Bootstrap nodes
    hosts: all
    become: true
    gather_facts: true
    vars:
      ip_list_from_terraform: ['Verify']
    tasks:
      - name: assign a list of all the physical network private IPs
        set_fact:
          ip_list_from_terraform: "{{ ip_list_from_terraform + [ item ] }}"
        with_items: " {{ hostvars[inventory_hostname]['ansible_' + ansible_default_ipv4['interface']]['ipv4']['address'] }} "
        register: ip_list_from_terraform_list

      - name: Debug global var
        debug:
          var: ip_list_from_terraform

      - name: Debug register result
        debug:
          var: ip_list_from_terraform_list

Expected:

ok: [shrimp-master-0] => {
"ip_list_from_terraform": [
    "Verify",
    "10.0.2.41",
    "10.0.2.172",
    "10.0.2.33",
    "10.0.2.215",
    "10.0.2.131",
    "10.0.2.168",
    "10.0.2.118"
]

}

Actual:

TASK [Debug global var] ********************************************************************************************************************************************************************************************************************
ok: [shrimp-master-0] => {
    "ip_list_from_terraform": [
        "Verify",
        "10.0.2.12"
    ]
}
ok: [shrimp-master-1] => {
    "ip_list_from_terraform": [
        "Verify",
        "10.0.2.33"
    ]
}
ok: [shrimp-master-2] => {
    "ip_list_from_terraform": [
        "Verify",
        "10.0.2.215"
    ]
}
ok: [shrimp-worker-0-super-wallaby] => {
    "ip_list_from_terraform": [
        "Verify",
        "10.0.2.131"
    ]
}
ok: [shrimp-gpu-worker-0-settled-wombat] => {
    "ip_list_from_terraform": [
        "Verify",
        "10.0.2.151"
    ]
}
Jack Murphy
  • 2,952
  • 1
  • 30
  • 49

1 Answers1

0

Let's simplify the case. Given the inventory

shell> cat hosts
host1 test_ip=10.0.2.41
host2 test_ip=10.0.2.172
host3 test_ip=10.0.2.33

the playbook

- hosts: host1,host2,host3
  vars:
    ip_list_from_terraform: ['Verify']
  tasks:
    - set_fact:
        ip_list_from_terraform: "{{ ip_list_from_terraform + [ item ] }}"
      with_items: "{{ hostvars[inventory_hostname]['test_ip'] }}"
    - debug:
        var: ip_list_from_terraform

gives

ok: [host2] => 
  ip_list_from_terraform:
  - Verify
  - 10.0.2.172
ok: [host1] => 
  ip_list_from_terraform:
  - Verify
  - 10.0.2.41
ok: [host3] => 
  ip_list_from_terraform:
  - Verify
  - 10.0.2.33

As a side-note, with_items is needed because the argument is a string. loop would crash with the error 'Invalid data passed to ''loop'', it requires a list,.


Q: "set_fact should concatenate the lists"

A: Run once and loop ansible_play_hosts. For example

    - set_fact:
        ip_list_from_terraform: "{{ ip_list_from_terraform +
                                    [hostvars[item]['test_ip']] }}"
      loop: "{{ ansible_play_hosts }}"
      run_once: true

gives

  ip_list_from_terraform:
  - Verify
  - 10.0.2.41
  - 10.0.2.172
  - 10.0.2.33
Vladimir Botka
  • 58,131
  • 4
  • 32
  • 63
  • your final result is a single array, but it shows all the same IP, the intention was to create a list with an IP from each host – Jack Murphy Sep 09 '21 at 15:37