Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unset a Variable in Ansible?

Is there a possibility to unset a fact (variable) in Ansible?

Unset in such a way that the check is defined fails.

For execution decisions I regularly check conditions with is defined. However, it may be necessary to unset these before execution, e.g. if a role is used multiple times via include_role or tasks are used multiple times via include_tasks.

Is there a special syntax for this, e.g. to use the set_fact module?

If I understood it correctly, meta: clear_facts takes care of clearing all facts and cannot be restricted to individual ones.

like image 664
phanaz Avatar asked Nov 04 '25 13:11

phanaz


1 Answers

WARNING: vars: on an include_* are considered include params

See:

  • Variable precedence: Where should I put a variable?

  • Modified "vars:" not visible inside include_role

  • include params from the list of variable precedence list has no examples

For example, the vars: below is not task vars (precedence 17.). It is include params (precedence 21.). As a result, potential set_facts (precedence. 19) inside the role will not override the variable test_var

    - include_role:
        name: test_role
      vars:
        test_var: first run

Use apply if you want to provide task vars (precedence 17.) to a role

    - include_role:
        name: test_role
      apply:
        vars:
          test_var: first run

This hasn't been documented yet.


Q: "Is there a possibility to unset a fact (variable) in Ansible?"

A: No. It is not possible to unset variables in Ansible. Instead, it's possible to define variables in various scopes. Such variables won't be defined above the particular scope. See Playbook Keywords. You can define variables in this hierarchy of scopes

  • Play
  • Role
  • Block
  • Task

There are various scenarios on how to solve the use cases: "It may be necessary to unset variables before execution, e.g. if a role is used multiple times via include_role or tasks are used multiple times via include_tasks."

For example, create a role

shell> tree roles/
roles/
└── test_role
    └── tasks
        └── main.yml

with the single task

shell> cat roles/test_role/tasks/main.yml 
- debug:
    var: test_var

Use case 1. A role is used multiple times via include_role

For example, the playbook

- hosts: localhost

  tasks:

    - include_role:
        name: test_role
      vars:
        test_var: first run

    - include_role:
        name: test_role

    - include_role:
        name: test_role
      vars:
        test_var: third run

gives (abridged)

  test_var: first run
  test_var: VARIABLE IS NOT DEFINED!
  test_var: third run

Use case 2. Tasks are used multiple times via include_tasks

In the same way, the playbook below gives the same result

- hosts: localhost

  tasks:

    - include_tasks: roles/test_role/tasks/main.yml
      vars:
        test_var: first run

    - include_tasks: roles/test_role/tasks/main.yml

    - include_tasks: roles/test_role/tasks/main.yml
      vars:
        test_var: third run

Use case 3. Use roles

The playbook below gives also the same result

- hosts: localhost

  roles:

    - role: test_role
      test_var: first run

    - role: test_role

    - role: test_role
      test_var: third run

Notes

  • See Variable Scopes

  • It's good to understand what will happen when you declare an empty variable. For example, the playbook

- hosts: localhost
  vars:
    test_var: default_value
  tasks:
    - debug:
        var: test_var
    - set_fact:
        test_var:
    - debug:
        msg: "test_var is defined: {{ test_var is defined }}"
    - debug:
        var: test_var

shows (abridged) that an empty variable is defined and null. You will receive the same results when you set the variable explicitly to null by test_var: !!null

TASK [debug] **********************************************************************************************
ok: [localhost] => 
  test_var: default_value

TASK [set_fact] *******************************************************************************************
ok: [localhost]

TASK [debug] **********************************************************************************************
ok: [localhost] => 
  msg: 'test_var is defined: True'

TASK [debug] **********************************************************************************************
ok: [localhost] => 
  test_var: null
  • It's also good to understand that default doesn't set the value when the variable is defined. For example,
    - debug:
        var: test_var
    - debug:
        var: test_var|default('default when undef')

shows that the filter default doesn't by default cares the value is null and doesn't set the value because the variable is defined

TASK [debug] **********************************************************************************************
ok: [localhost] => 
  test_var: null

TASK [debug] **********************************************************************************************
ok: [localhost] => 
  test_var|default('default when undef'): ''
  • If you want to set the default value also when the variable is null set the second parameter of the filter True. For example,
    - debug:
        var: test_var
    - debug:
        var: test_var|default('default when undef or null', true)

gives

TASK [debug] **********************************************************************************************
ok: [localhost] => 
  test_var: null

TASK [debug] **********************************************************************************************
ok: [localhost] => 
  test_var|default('default when undef or null', true): default when undef or null
like image 190
Vladimir Botka Avatar answered Nov 06 '25 02:11

Vladimir Botka