2

I have an Ansible task which loops through a list and for each item in the list runs a role, using include_role. For each iteration of loop I want to pass a different set of variables. Currently, I am trying to do this by creating the list as a list of dictionaries which can be specified using --extra-vars at runtime.

For example, I have task:

- name: Run the test role include_role: name: test_role loop: '{{ input_list }}' 

And the input_list:

input_list: - var1: foo var2: bar var3: baz - var1: hello var3: world 

But at this point how would I go about passing the current set of variables to the role? I initially tried defining each variable separately:

- name: Run the test role include_role: name: test_role vars: var1: '{{ item.var1 }}' var2: '{{ item.var2 }}' var3: '{{ item.var3 }}' loop: '{{ input_list }}' 

This works, but if one variable is missing from the input_list (i.e. should fall back to default value specified in the role defaults or at the start of the playbook for that variable) the play will fail. So I tried using Jinja2's default filter:

- name: Run the test role include_role: name: test_role vars: var1: '{{ item.var1 | default('foo') }}' var2: '{{ item.var2 | default('bar') }}' var3: '{{ item.var3 | default('baz') }}' loop: '{{ input_list }}' 

Again, this works, but it is a bit messy as every variable needs to be defined, and it doesn't use the default values from the role. Is there a better way of doing something like this?

1 Answer 1

0

One of the options is to create alternative defaults. For example, create a minimal role for testing

shell> cat roles/test_role/defaults/main.yml var1: default_1 var2: default_2 var3: default_3 shell> cat roles/test_role/tasks/main.yml - debug: msg: "{{ var1 }} {{ var2 }} {{ var3 }}" 

The task

 - include_role: name: test_role 

gives

 msg: default_1 default_2 default_3 

Let's create alternative defaults, e.g.

shell> cat roles/test_role/defaults/alt.yml var1: "{{ alt.var1|default('default_1') }}" var2: "{{ alt.var2|default('default_2') }}" var3: "{{ alt.var3|default('default_3') }}" 

and use it in the include. The task below gives the same result

 - include_role: name: test_role defaults_from: alt.yml 

Now, let's define the dictionary with the alternate defaults

 - include_role: name: test_role defaults_from: alt.yml loop: '{{ input_list }}' vars: alt: "{{ item }}" 

gives

 msg: foo bar baz msg: hello default_2 world 

The next option is to create and use alternate vars

shell> cat roles/test_role/vars/alt.yml var1: "{{ alt.var1|default('default_1') }}" var2: "{{ alt.var2|default('default_2') }}" var3: "{{ alt.var3|default('default_3') }}" 

For example, the task below gives the same result. The only difference is the precedence.

 - include_role: name: test_role vars_from: alt.yml loop: '{{ input_list }}' vars: alt: "{{ item }}" 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.