turmoilawaits
turmoilawaits

Reputation: 33

Ansible set_fact is overwriting the items

Here is my main.yml

---
- name: Gathering VCenter facts
  vmware_vm_info:
    hostname: "{{ vcenter_server }}"
    username: "{{ vcenter_user }}"
    password: "{{ vcenter_pass }}"
    validate_certs: false
  register: vcenter_facts
  delegate_to: localhost

- debug:
    var: vcenter_facts.virtual_machines

- name: Find all test-vms to run IO
  set_fact:
    vm_ip: "{{ item.ip_address }}"
  loop: "{{ vcenter_facts.virtual_machines }}"
  when: item.guest_name is regex("test_vm*")

- name: print vm_ip variable value
  debug:
    var: vm_ip

- name: Mount 16TB dropbox in each test vm
  shell: mount-16tb-dropbox.sh
  args:
    chdir: /usr/local/bin/
  with_items: "{{ vm_ip }}"

And here is the recap:

ok: [localhost] => {
    "vcenter_facts.virtual_machines": [
        {
            "attributes": {},
            "cluster": "Compute Cluster",
            "esxi_hostname": "100.80.90.179",
            "guest_fullname": "CentOS 7 (64-bit)",
            "guest_name": "test_vm4",
            "ip_address": "192.168.202.13",
            "mac_address": [
                "00:50:56:9d:d2:99"
            ],
            "power_state": "poweredOn",
            "tags": [],
            "uuid": "421d7b54-1359-14e8-3ec4-74b568cb96d2",
            "vm_network": {
                "00:50:56:9d:d2:99": {
                    "ipv4": [
                        "192.168.202.13"
                    ],
                    "ipv6": [
                        "fe80::44f6:a395:cde3:4dd1",
                        "fe80::a357:a163:e44f:2086",
                        "fe80::cd0c:e7d7:1356:2830"
                    ]
                }
            }
        },
        {
            "attributes": {},
            "cluster": "Compute Cluster",
            "esxi_hostname": "100.80.90.178",
            "guest_fullname": "CentOS 7 (64-bit)",
            "guest_name": "test_vm3",
            "ip_address": "192.168.202.12",
            "mac_address": [
                "00:50:56:9d:a9:e8"
            ],
            "power_state": "poweredOn",
            "tags": [],
            "uuid": "421d9239-0980-80c1-bca4-540efd726452",
            "vm_network": {
                "00:50:56:9d:a9:e8": {
                    "ipv4": [
                        "192.168.202.12"
                    ],
                    "ipv6": [
                        "fe80::cd0c:e7d7:1356:2830"
                    ]
                }
            }
        },
        {
            "attributes": {},
            "cluster": "Compute Cluster",
            "esxi_hostname": "100.80.90.178",
            "guest_fullname": "CentOS 7 (64-bit)",
            "guest_name": "Test_Automation_CentOS8_Linux_VM",
            "ip_address": "192.168.202.6",
            "mac_address": [
                "00:50:56:9d:13:14"
            ],
            "power_state": "poweredOn",
            "tags": [],
            "uuid": "421d53ba-4824-57e4-06fd-fba0f2b1dbea",
            "vm_network": {
                "00:50:56:9d:13:14": {
                    "ipv4": [
                        "192.168.202.6"
                    ],
                    "ipv6": [
                        "fe80::cd0c:e7d7:1356:2830",
                        "fe80::44f6:a395:cde3:4dd1"
                    ]
                }
            }
        },
        {
            "attributes": {},
            "cluster": "Compute Cluster",
            "esxi_hostname": "100.80.90.180",
            "guest_fullname": "CentOS 7 (64-bit)",
            "guest_name": "test_vm5",
            "ip_address": "192.168.202.14",
            "mac_address": [
                "00:50:56:9d:85:b6"
            ],
            "power_state": "poweredOn",
            "tags": [],
            "uuid": "421d6855-e60e-cd80-f113-39f11927d63b",
            "vm_network": {
                "00:50:56:9d:85:b6": {
                    "ipv4": [
                        "192.168.202.14"
                    ],
                    "ipv6": [
                        "fe80::44f6:a395:cde3:4dd1",
                        "fe80::cd0c:e7d7:1356:2830",
                        "fe80::a357:a163:e44f:2086"
                    ]
                }
            }
        }
    ]
}

I am not able to loop through all the ip_address variable (i.e. 192.168.202.12, 192.168.202.13, 192.168.202.14).
It just reads the last item (i.e. 192.168.202.14).

What am I possibly doing wrong with set_fact that it is not reading all the variable and performing the set of tasks that follows?

Upvotes: 2

Views: 297

Answers (2)

Moon
Moon

Reputation: 3037

This should give all the IP. You correctly assumed where the code may need correction. In the code, vm_ip variable was overwritten by each loop and the last IP remained. What you need is a list and then append each IP to the list.

- set_fact: 
    vm_ip: "{{ vm_ip | default([]) + [item.ip_address] }}"
  loop: "{{ vcenter_facts.virtual_machines | flatten }}"
  when: item.guest_name is regex("test_vm*")

- debug:
    var: vm_ip

Alternative solution using Jinja2 filters.

- set_fact:
    vm_ip: >- 
        {{ vcenter_facts.virtual_machines | flatten 
        | rejectattr('guest_name', 'match', '^(?!test_vm).*') 
        | map(attribute='ip_address') | list }}

Upvotes: 2

Zeitounator
Zeitounator

Reputation: 44605

An alternate solution using json_query

---
- name: Gathering VCenter facts
  vmware_vm_info:
    hostname: "{{ vcenter_server }}"
    username: "{{ vcenter_user }}"
    password: "{{ vcenter_pass }}"
    validate_certs: false
  register: vcenter_facts
  delegate_to: localhost

- name: Mount 16TB dropbox in each test vm
  shell: mount-16tb-dropbox.sh
  args:
    chdir: /usr/local/bin/
  vars:
    query: >-
      [?contains("guest_name", 'test_vm')].ip_address[]
  with_items: "{{ vcenter_facts.virtual_machines | to_json | from_json | json_query(query) | list }}"

Note: to_json | from_json is a workaround for a bug between ansible and jmespath so that all values can be converted to real strings and can be used with the jmespath contains function.

Upvotes: 2

Related Questions