Ansible not gathering facts on tags
Asked Answered
S

2

6

I'm habituated to use --tags when I'm using ansible-playbook to filter what tasks will be executed. I recently switched from Ansible 2.7 to 2.9 (huge gap, eh ?).

I was surprised ansible did not gathering facts exclusively when I'm using --tags. And I saw multiple similar cases closed in GitHub like this one or this one. It seems affects ansible since 2.8 version, but shown as resolved. Is anybody can confirm this behavior ? It seems happening from 2.8.

ANSIBLE VERSION :

ansible --version

ansible 2.9.9.post0
  config file = None
  configured module search path = [u'/opt/ansible/ansible/library']
  ansible python module location = /opt/ansible/ansible/lib/ansible
  executable location = /opt/ansible/ansible/bin/ansible
  python version = 2.7.6 (default, Nov 13 2018, 12:45:42) [GCC 4.8.4]

ANSIBLE CONFIG :

ansible-config dump --only-changed

DEFAULT_MODULE_PATH(env: ANSIBLE_LIBRARY) = [u'/opt/ansible/ansible/library']

STEPS TO REPRODUCE :

playbook test.yml :

- name: First test
  hosts: localhost
  connection: local
  gather_facts: yes
  roles:
    - { role: test, tags: test }
  tags: first

- name: Second test
  hosts: localhost
  connection: local
  gather_facts: yes
  roles:
    - { role: test, tags: test }
  tags: second

role : roles/test/tasks/main.yml

- debug:
    msg: System {{ inventory_hostname }} has uuid {{ ansible_product_uuid }}

Results :

ansible-playbook test.yml --check

= No errors.


ansible-playbook test.yml --check --tags "test"

= failed: 1

"The task includes an option with an undefined variable. The error was: 'ansible_product_uuid' is undefined [...]"

And I can see on the output that facts are not gathered.

Sleepwalk answered 4/9, 2020 at 10:59 Comment(0)
A
4

Well, it seems to be a purposed behaviour when you have tags on a play level:

This is intended behavior. Tagging a play with tags applies those tags to the gather_facts step and removes the always tag which is applied by default. If the goal is to tag the play, you can add a setup task with tags in order to gather facts.

samdoran commented on 11 Jun 2019


Please note that this is, then, not linked to the usage of roles, as it can be reproduced by simply doing:

- name: First test
  hosts: all
  tags:
    - first

  tasks:
    - debug:
        msg: System {{ inventory_hostname }} has uuid {{ ansible_product_uuid }}
      tags: test

Which yields the failing recap:

$ ANSIBLE_STDOUT_CALLBACK=debug ansible-playbook play.yml --tags "test"

PLAY [First test] *************************************************************************************************

TASK [debug] ******************************************************************************************************
fatal: [localhost]: FAILED! => {}

MSG:

The task includes an option with an undefined variable. The error was: 'ansible_product_uuid' is undefined

The error appears to be in '/ansible/play.yml': line 7, column 7, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

  tasks:
    - debug:
      ^ here


PLAY RECAP ********************************************************************************************************
localhost                  : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0  

So you'll either have to remove the tag of you play level, or use the setup module, as prompted.

This can be done inside your role, so your role stops relying on variables that could possibly not be set.

Given the role roles/test/tasks/main.yml

- setup:
- debug:
    msg: System {{ inventory_hostname }} has uuid {{ ansible_product_uuid }}

And the playbook:

- name: First test
  hosts: all
  tags:
    - first

  roles:
    - role: test
      tags: 
        - test

- name: Second test
  hosts: all
  tags: 
    - second

  roles:
    - role: test
      tags: 
        - test

Here would be the run and recap for it:

$ ansible-playbook play.yml --tags "test"

PLAY [First test] *************************************************************************************************

TASK [test : setup] ***********************************************************************************************
ok: [localhost]

TASK [test : debug] ***********************************************************************************************
ok: [localhost] => {
    "msg": "System localhost has uuid 3fc44bc9-0000-0000-b25d-bf9e26ce0762"
}

PLAY [Second test] ************************************************************************************************

TASK [test : setup] ***********************************************************************************************
ok: [localhost]

TASK [test : debug] ***********************************************************************************************
ok: [localhost] => {
    "msg": "System localhost has uuid 3fc44bc9-0000-0000-b25d-bf9e26ce0762"
}

PLAY RECAP ********************************************************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

All this run on:

ansible 2.9.9
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.8/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.8.3 (default, May 15 2020, 01:53:50) [GCC 9.3.0]
Aqueous answered 4/9, 2020 at 17:0 Comment(2)
Ok, your solution works well and make sense for me now. However, I found very curious that the use of tags impacts the gathering of facts. So, In my case, I have to be careful to not mix playbook & role tags, or gather facts as many times as roles I have (using setup module). Thanks for the helpSleepwalk
Well this is linked to the fact that a play or task without explicit tag actually still have one applied: the always tag. So when you explicitly tag a play, as prompted by the Ansible maintainer's comment mentioned in the answer, you overwrite this always tag and then have to specify the tag's play if you want the facts of the play to be gathered.Rebellion
P
0

Adding this tag to my play pre_tasks, allowed me to always gather facts when only running a tagged role inside that play.

 pre_tasks:
    # always gather facts
    - setup:
      tags: always

  roles:
    - { role: foo, tags: [foo] }
    - { role: bar, tags: [bar] }
    - { role: baz, tags: [baz] }
  tags: base

ansible-playbook --inventory someInventory configure-guests.yml --tags bar

Gathers facts and only applies role bar.

Papyraceous answered 8/10, 2024 at 17:18 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.