I'm trying to use ansible to loop over a list of lists to install some packages. But {{item}} is returning every element in the sub lists rather than the sublist itself. I have a yaml file which come from a manifest list from outside ansible and it looks like this:
---
modules:
- ['module','version','extra']
- ['module2','version','extra']
- ['module3','version','extra']
My task looks like this:
task:
- include_vars: /path/to/external/file.yml
- name: install modules
yum: name={{item.0}} state=installed
with_items: "{{ modules }}"
When I run that I get:
fatal: [localhost]: FAILED! => {"failed": true, "msg": "ERROR! int object has no element 0"}
When I try:
- debug: msg="{{item}}"
with_items: "{{module}}"
it prints every element (module, version, extra, and so on), not just the sublist (which is what I would expect)
Unfortunately, this is the intended behavior. Please see this discussion on with_tems and nested lists
An alternative way to solve this issue is to use a complex item instead of a list of list. Structure your variables like this:
- modules:
- {name: module1, version: version1, info: extra1}
- {name: module2, version: version2, info: extra2}
- {name: module3, version: version3, info: extra3}
Then you can still use with_items
, like this:
- name: Printing Stuffs...
shell: echo This is "{{ item.name }}", "{{ item.version }}" and "{{ item.info }}"
with_items: "{{modules}}"
@helloV already provided the answer that you can not do this using with_items
, i am going to show you how you can use your current data structure with with_nested
to get the desired output.
Here is an example playbook:
---
- hosts:
- localhost
vars:
- modules:
- ['module1','version1','extra1']
- ['module2','version2','extra2']
- ['module3','version3','extra3']
tasks:
- name: Printing Stuffs...
shell: echo This is "{{ item.0 }}", "{{ item.1 }}" and "{{ item.2 }}"
with_nested:
- modules
Now you will get the following as stdout_lines
:
This is module1, version1 and extra1
This is module2, version2 and extra2
This is module3, version3 and extra3
Replace with_items: "{{ modules }}"
with:
in Ansible 2.5 and later (refer to with_list
porting guide):
loop: "{{ modules }}"
in Ansible 2.0 and later:
with_list: "{{ modules }}"
in any Ansible pre-2.0:
with_items:
- "{{ modules }}"
This way you'd have three levels of nested lists, and the default behaviour flattens only two of them.