Search code examples
ansiblefile-globs

ansible looping through the result and finding files


I am using ansible to configire 10-20 linux systems. I have a set of tools that I define in my invetory files with versions, as:

tools:
  - tool: ABC
    version: 7.8
  - tool: XYZ
    version: 8.32.1

Now, in my playback yml file, I would like to loop through them and have the necessay installation logic. Such as:

DEBUG tools loop

  - name: Find installer files
    copy:
      src=
    with_items:
    - "{{ tools }}"
    when:
      tools.tool == "ABC"

In my case, {{tools.tool}}/{{tools.version}} has a tgz file which I need to unarchive at a remote location. Do you know how to do this? I have tried these:

- name: Find installer files
    vars:
      files: {{ lookup("fileglob",'tools/{{item.tool}}/linux/{{item.version}}/*') }}
    unarchive:
      src: "{{ files }}"
      dest: "tools/{{item.tool}}/{{item.version}}/"
    with_items:
    - "{{ tools }}"
    when:
      item.tool == "ABC"

- name: Find installer files
   debug:
     msg: "{{ item}}"
   with_items:
   - "{{ tools }}"
   with_fileglob:
   - "tools/{{item.tool}}/linux/{{item.version}}/*"
   when:
     item.toolchain == "ABC"

But none worked. Thanks for the help.


Solution

  • It's not that simple as Your own solution breaks if there are multiple files in the directory, I assume.
    So if You only have one file in the directory I wouldn't use fileglob at all but define a fixed name for it that You can generate knowing tool and version.

    I also see the need for such sort of things often but did not found any nice solution for that. Only such ugly thing as:

    - name: example book
      hosts: localhost
      become: false
      gather_facts: false
      vars:
        tools:
          - tool: ABC
            version: 7.8
          - tool: XYZ
            version: 8.32.1
        tools_files: []
      tasks:
        - name: prepare facts
          set_fact:
            tools_files: "{{ tools_files + [{'tool': item.tool | string, 'version': item.version | string, 'files': lookup('fileglob', 'tools/' ~ item.tool ~ '/linux/' ~ item.version ~ '/*', wantlist=True)}] }}"
          with_items:
            - "{{ tools }}"
        - name: action loop
          debug:
            msg: "{{ {'src': item[1], 'dest': 'tools/' ~ item[0].tool ~ '/' ~ item[0].version ~ '/'} }}"
          with_subelements:
            - "{{ tools_files }}"
            - files
          when:
            item[0].tool == "ABC"
    

    or

    - name: example book
      hosts: localhost
      become: false
      gather_facts: false
      vars:
        tools:
          - tool: ABC
            version: 7.8
          - tool: XYZ
            version: 8.32.1
        tools_files: []
      tasks:
        - name: prepare facts
          set_fact:
            tools_files: "{{ tools_files + [{'tool': item.tool | string, 'version': item.version | string, 'files': lookup('fileglob', 'tools/' ~ item.tool ~ '/linux/' ~ item.version ~ '/*', wantlist=True)}] }}"
          with_items:
            - "{{ tools }}"
        - name: action loop
          debug:
            msg: "{{ {'src': item[1], 'dest': 'tools/' ~ item[0].tool ~ '/' ~ item[0].version ~ '/'} }}"
          with_items:
            - "{{ tools_files | subelements('files') }}"
          when:
            item[0].tool == "ABC"
    

    Maybe I miss somthing because such things are a very basic feature (looping throug an array generating a result array beeing able to use all functions available and not just map using filters where some important things are just not available or cannot be used because map gives the inport as first argument to filter always).