ansibleansible-2.x

How can I modify/overwrite a role variable inside the role in Ansible?


I'm writing a role, to which the user can pass a list. Inside that role, I want to add items to this list conditionally, before processing it in my role. The role variable is called my_list. It is passed to the role like this:

---
- name: Do something
  hosts: all
  roles:
    - role: my.role
      my_list:
        - { name: test1, url: 'http://foo.bar' }
        - { name: test2, url: 'http://foo.bar' }

Inside my role, I try to modify the role variable like this:

---
- name: Do something
  ansible.builtin.set_fact:
    my_list: "{{ my_list + internal_list }}"
  when: condition_is_met

- debug:
    var: my_list

But it does not work; the list does not get modified. If I use a new variable name, it works:

---
- name: Do something
  ansible.builtin.set_fact:
    my_new_list: "{{ my_list + internal_list }}"
  when: condition_is_met

- debug:
    var: my_new_list

So I think it is related to variable scopes. set_fact will set a host variable, which has a lower priority than the role variable. If set_fact is not suitable to modify role variables, how can it be done then?


Solution

  • set_fact will overwrite a role variable if it actually is a role variable and not a role parameter. Excerpt from Understanding variable precedence:

    ...

    1. role vars (defined in role/vars/main.yml)

    ...

    1. role (and include_role) params

    ...

    With:

    - role: my.role
      my_list:
        - { name: test1, url: 'http://foo.bar' }
        - { name: test2, url: 'http://foo.bar' }
    

    I was passing my_list as a role parameter. If I pass it as a role variable, set_fact works:

    - role: my.role
      vars:
        my_list:
          - { name: test1, url: 'http://foo.bar' }
          - { name: test2, url: 'http://foo.bar' }
    

    According to Role argument evaluation and validation behaving inconsistently #75098, it is recommended to not use custom role params, but to use role variables instead.