Search code examples
linuxansibleyamlredhat

Testing a task result which uses a loop?


So the first task is always skipped because RedHat 8 is detected which should trigger the fail module to run but this gets skipped also. Is works fine without the loop though.

- name: installing packages
  hosts: ansible2
  ignore_errors: true
  vars_files: varsfile
  tasks:
  - name: install software based on OS distro and version
    yum:
      name: "{{ item.name }}"
      state: latest
    loop: "{{ packages }}"
    when: >
       ( ansible_distribution == "RedHat" and ansible_distribution_major_version is version('12', '>=')  )
       or
       ( ansible_distribution == "CentOS" and ansible_distribution_major_version | int >= 8 )
    register: result
  - fail:
      msg: error {{ ansible_hostname }} does not meet minimum requirements
    when: result is skipped

Solution

  • Regarding

    So the first task is always skipped because RedHat 8 is detected which should trigger the fail module to run but this gets skipped also.

    with a small test setup and a debug task for the variable name to debug

    ---
    - hosts: test.example.com
      become: false
      gather_facts: true
    
      tasks:
    
      - name: Install software based on OS distro and version
        debug:
          msg: "{{ ansible_distribution }} {{ ansible_distribution_major_version }}"
        register: result
        when: ansible_distribution == "RedHat" and ansible_distribution_major_version is version('12', '>=')
        with_items: ['pkg1', 'pkg2']
    
      - name: Show result
        debug:
          var: result
    
      - fail:
          msg: "Error: {{ ansible_hostname }} does not meet minimum requirements"
        when: result.results[0].skipped
    

    resulting into an output of

    TASK [Gathering Facts] ********************************
    ok: [test.example.com]
    
    TASK [Show result] ************************************
    ok: [test.example.com] =>
      result:
        changed: false
        msg: All items completed
        results:
        - ansible_loop_var: item
          changed: false
          item: pkg1
          skip_reason: Conditional result was False
          skipped: true
       ...
    
    TASK [fail] *******************************************
    fatal: [test.example.com]: FAILED! => changed=false
      msg: 'Error: test does not meet minimum requirements'
    

    you can see that the loop will create a list.

      - name: Show result
        debug:
          var: result.results | type_debug
    
    TASK [Show result] ****************
    ok: [test.example.com] =>
      result.results | type_debug: list
    

    Therefore you need to set the Conditional to when: result.results[0].skipped.


    Regarding

    Is works fine without the loop though.

    it is recommended to simplify your use case with the following approach

      - name: Install software based on OS distro and version
        yum:
          name: "{{ packages }}"
          state: latest
    

    according the yum module Notes

    When used with a loop: each package will be processed individually, it is much more efficient to pass the list directly to the name option.

    and as it is faster and consumes less resources. Furthermore the result set and conditionals are less complex.