Skip to content

Ansible, delegate_to and set_fact

Another Ansible upgrade, another Playbook failing.

I have a number Playbooks which run on virtual machines. Some tasks are "outsourced" to the physical machine where the VM is running on, using "delegate_to". One of the tasks (which I haven't used in a while, because I rarely touch this machine) stopped working, and instead throws a "variable undefined" error. But from the beginning, here is the VM Playbook:

- block:
  - include: server-part.yml
  delegate_to: "{{ ansible_host }}"
  delegate_facts: True

That's the short form of it, and the $ansible_host variable holds the physical server address. That part is working. In "server-part.yml" I have the following:

# re-do the gather_facts task for the host
- action: setup

- name: Determine network interface name
  set_fact:
    main_interface: "{{ item }}"
  with_items:
    "{{ hostvars[physicalhost]['ansible_interfaces'] }}"
  when: item is match("^e[tn]")
  changed_when: false

- name: Verify interface name is set
  fail:
    msg: "Could not determine network interface name!"
  when: main_interface is not defined

The only physical network interface in this server is "eth0", that's still the case. There are a couple reasons why I still scan the list of interfaces, instead of just depending on "eth0". The main reason however is that this part also works with the enumeration systemd is doing with network interfaces (they have "en" names, instead of "eth"). But suddenly $main_interface in the next step is no longer defined.

Digging deeper (aka: -vvvv) it shows that Ansible is setting the correct interface name in the "set_fact" task, but then the variable is no longer defined immediately after that. What? I'm not sure I had to use this Playbook since my host was upgraded to Ansible 2.8.3, but I couldn't find any issues matching this problem either.

 

What happened? After more investigation it seems that Ansible is now attaching the variable from "set_fact" to the physical host, but is reading any variable from the virtual machine facts. Example:

- action: setup
- set_fact: testvar="Test"
- debug: msg="{{ testvar }}"

This fails with: The task includes an option with an undefined variable. The error was: 'testvar' is undefined.

- action: setup
- set_fact: testvar="Test"
- debug: msg="{{ hostvars['physicalhost']['testvar'] }}"

This works. Or I can turn it around:

- action: setup
- set_fact: testvar="Test"
  delegate_to: "virtualvm"
  delegate_facts: True
- debug: msg="{{ testvar }}"

Assign the "set_fact" to the VM and then I can access the variable on the physical host.

 

Quite strange, and definitely didn't work that way when I last used that Playbook. Now please excuse me, I have to check a couple more Playbooks *sigh*

Trackbacks

No Trackbacks

Comments

Display comments as Linear | Threaded

No comments

Add Comment

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
E-Mail addresses will not be displayed and will only be used for E-Mail notifications.
To leave a comment you must approve it via e-mail, which will be sent to your address after submission.
Form options