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?
set_fact
will overwrite a role variable if it actually is a role variable and not a role parameter. Excerpt from Understanding variable precedence:
...
- role vars (defined in role/vars/main.yml)
...
- 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.