ansible with_items list of lists is flattening

2019-02-12 12:16发布

问题:

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)

回答1:

Unfortunately, this is the intended behavior. Please see this discussion on with_tems and nested lists



回答2:

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}}"


回答3:

@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


回答4:

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.



标签: yaml ansible