Ansible group variable undefined in play

0

I have implemented a dynamic inventory for Ansible, during its execution it defines a group variable that I'm using later in a playbook.

In the playbook, I'm using it twice:

  • for looping over its contents:
    tasks:
       - include_tasks: include/restart.yaml
         loop: "{{ host_set | default(['all']) }}"
         loop_control:
           loop_var: h
    
  • and as a means to set serial conditionally
    serial: "{{ host_set | default(false) | ternary('100%', '5') }}"
    

The behavior I get that I can't explain is that the host_set variable is defined and populated correctly during task execution, but when trying to set serial it seems to be undefined.

Is this expected behavior, are Ansible group variables undefined when setting a play's attributes, but pop up later when task execution for that particular play begins?

ansible
2021-11-23 21:48:17
2

3

Group variables only apply to individual hosts. Plays are evaluated in a non-host context, so the only variables that are available are non-host-specific variables, like those from --extra-vars.

2021-11-24 01:32:48
1

When the reason of this behaviour is perfectly well stated by @flowerysong's answer, there is a workaround you can use to achieve your requirement.

The trick is using the fact that you can define two plays inside a playbook and, then, use the variable set on the host(s) of the first play.

So, what we are going to do is:

  1. Run a play on localhost and set a fact coming from the host group that we aim to target in the second play
  2. Optionally: I also defined a target_hosts variable in the first play, to be sure that, if the second play's target is modified, the host group variable is always the one that the second play is going to target.
  3. Use that variable in the second play, from localhost's hostvars

Extra note: there is no accounting for taste, but I prefer the inline if to the ternary filter, still, they are strictly equivalent.


So, given the playbook:

- hosts: localhost
  gather_facts: no

  tasks:
    - set_fact:
        target_hosts: nodes
        
    - set_fact:
        host_set: "{{ hostvars[groups[target_hosts].0].host_set }}"

- hosts: "{{ hostvars.localhost.target_hosts }}"
  gather_facts: no
  serial: "{{ '100%' if hostvars.localhost.host_set else '1' }}"
  
  tasks:
    - debug: 
  • When run with host_set: true in the nodes group:
    PLAY [localhost] *******************************************************************************************************************
    
    TASK [set_fact] ********************************************************************************************************************
    ok: [localhost]
    
    TASK [set_fact] ********************************************************************************************************************
    ok: [localhost]
    
    PLAY [nodes] ***********************************************************************************************************************
    
    TASK [debug] ***********************************************************************************************************************
    ok: [node1] => 
      msg: Hello world!
    ok: [node2] => 
      msg: Hello world!
    ok: [node3] => 
      msg: Hello world!
    
    PLAY RECAP *************************************************************************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    node1                      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    node2                      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    node3                      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
  • When run with host_set: false in the nodes group:
    PLAY [localhost] *******************************************************************************************************************
    
    TASK [set_fact] ********************************************************************************************************************
    ok: [localhost]
    
    TASK [set_fact] ********************************************************************************************************************
    ok: [localhost]
    
    PLAY [nodes] ***********************************************************************************************************************
    
    TASK [debug] ***********************************************************************************************************************
    ok: [node1] => 
      msg: Hello world!
    
    PLAY [nodes] ***********************************************************************************************************************
    
    TASK [debug] ***********************************************************************************************************************
    ok: [node2] => 
      msg: Hello world!
    
    PLAY [nodes] ***********************************************************************************************************************
    
    TASK [debug] ***********************************************************************************************************************
    ok: [node3] => 
      msg: Hello world!
    
    PLAY RECAP *************************************************************************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    node1                      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    node2                      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    node3                      : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
2021-11-24 11:14:59

Thank you for the extra info!
Radu Stoenescu

In other languages

This page is in other languages

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................