2

This is a very simple Ansible playbook I run from AWX to get information about hosts, and it works as intended on Linux machines:

---

- name: Get some info
  debug:
    msg: "{{ ansible_hostname }} {{ ansible_default_ipv4.address }} {{ ansible_distribution }}"

However, when run over Windows machines, it returns this error:

fatal: [MYWINHOST1]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'ansible_default_ipv4' is undefined\n\nThe error appears to be in '/tmp/bwrap_21138_4q41r57e/awx_21138_is8pox6p/project/roles/windows/tasks/getsomeinfo.yml': line 3, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Get some info\n ^ here\n"}

How do I access and print the same Ansible facts values from a Windows machine?

dr_
  • 2,400
  • 1
  • 25
  • 39

2 Answers2

1

From the documentation:

ansible_facts

This key should contain a dictionary which will be appended to the facts assigned to the host. These will be directly accessible and don’t require using a registered variable.

Source: https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#ansible-facts

So, if printing hostvars[inventory_hostname] shows you a variable ansible_facts.ip_addresses then you can access it via ansible_ip_addresses — if that node only have one IP address assigned, see below if this is not the case:

- debug:
    msg: >-
     {{ ansible_hostname }} 
     {{ ansible_ip_addresses }} 
     {{ ansible_distribution }}

Mind that there is a bug that has been reported to the Ansible tracker about Windows machine having multiple IP addresses, and that it does not seems to be as trivial of a consensus as though what really is the default IP address:

There's really not a great solution to this issue- the concept of a "default IP address" means different things to different people, and the Linux fact is wrong as much as it's right. Usually this comes down to locating an address on a particular subnet, which we have to filters to assist with given the list of IP addresses... Given the lack of clarity on this, I'm going to close this issue.

Source: nitzmahone's comment on the issue https://github.com/ansible/ansible/issues/17014


So, to clear things up, the fact gathering in Windows and Linux are not implementing the same variable, you sure can work around this, implementing an inline-if:

- debug:
    msg: >-
     {{ ansible_hostname }} 
     {{ 
        ansible_ip_addresses 
          if ansible_os_family == "Windows" 
          else ansible_default_ipv4.address 
     }}
     {# 
        Mind that you still have to implement your own logic 
        of what is the "default" IP if you have more 
        than one IP address on that Windows machine, as linked above
     #}
     {{ ansible_distribution }}
β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83
  • 1
    You are using `ansible_default_ipv4.address` and not `ansible_ip_addresses` – β.εηοιτ.βε May 17 '22 at 14:06
  • Why would this be different between Windows and Linux? – DustWolf Dec 27 '22 at 09:24
  • @DustWolf because the implementation on the fact gatherer is not the same on Windows and Linux, you can read the whole issue linked as the very last link of the answer that discuss it with the maintainers. In very short and simplified, on Windows, there is no real concept of « primary » IP, so they are reluctant to name it the same. – β.εηοιτ.βε Dec 27 '22 at 12:26
  • Ended up using `ansible_ip_addresses | select('match', '^(?:[0-9]{1,3}\\.){3}[0-9]{1,3}$') | first` it's not perfect but for machines with only one IP, where IPv4 is your prefered protocol, it works fine. – DustWolf Dec 27 '22 at 17:21
0

The first thing I would do is using the new notation (removing any possibility to have failures due to misinterpretation):

---
- name: Gather Info
  hosts: all
  gather_facts: yes
  tasks:
    - name: Get some info
      debug:
        msg: "{{ ansible_hostname }} {{ ansible_default_ipv4['address'] }} {{ ansible_distribution }}"

Unless you're using caching mechanisms like redis/memcache, sometimes it takes some time to get results and probably is more efficient to get minimum facts.

To address the issue, I can't assist too much but if there's a bug closed in the windows module only developers could help here, as either Ansible team address this somehow or you might need to develop a small module for your needs.

UPDATE #1:

For what I can see if you gather a subset, you miss some information that you require ...

If you activate the gather_facts it doesn't fail with The error was: 'ansible_default_ipv4' is undefined.

UPDATE #2:

In regards to your error message, looks like something copied didn't was properly aligned.

In regards to how to get access to the variables:

  pre_tasks:
    - name: Collect only minimum facts.
      ansible.builtin.setup:
        gather_subset: "!all"
      register: facts

When I register the collection, I use: facts.ansible_facts.ansible_domain to get the domain. maybe that give you enough insight about how to get the variables you need.

malpanez
  • 225
  • 1
  • 4
  • In regards to your error message, looks like something copied didn't was properly aligned. In regards to how to get access to the variables: ```yaml pre_tasks: - name: Collect only minimum facts. ansible.builtin.setup: gather_subset: "!all" register: facts ``` When I register the collection, I use: `facts.ansible_facts.ansible_domain` to get the domain. maybe that give you enough insight about how to get the variables you need. – malpanez May 17 '22 at 14:27