ansibleconditional-statementsskip

How do I add a custom message if a task does not meet the 'when' condition and is skipped?


In this task, I am searching for a file. If there is no file, the task will be skipped. My question is, how do I write a custom message to output when the task is skipped?

- name: Search for files 
  win_find:
    paths: C:\dataset\
  register: data

- debug:
    msg: "Data exists"
  when: data | json_query('files[*].exists')

- name: set_fact
  set_fact:
    exists: "{{ data | json_query('files[*].exists') }}"

In a different playbook:

- name: Run if file exists
  block:
    - name: read content from file
      win_shell: C:\day.txt  
      register: day
  when: hostvars['10.11.18.190']['exists']

- name: print message
  debug:
    msg: "{{ hostvars['10.12.201.20']['day'] }}"

As there is no file, the task is skipped:

TASK [Run if file exists] *********************
skipping: [10.11.18.190] => {
    "changed": false,
    "skip_reason": "Conditional result was False"
}

TASK [print message] **************************************************************************************
ok: [10.11.18.190] => {
    "msg": {
        "changed": false,
        "skip_reason": "Conditional result was False",
        "skipped": true
    }
}

As you can see from the output, the variable hostvars['10.12.201.20']['day'] is showing "changed": false, skip_reason, etc. But I do not want this, I want it to output a message like, "File does not exist".

How can I create a custom message for this variable hostvars['10.12.201.20']['day']?


Solution

  • A: Use the 'Do It Yourself' callback plugin community.general.diy. See

    shell> ansible-doc -t callback community.general.diy
    

    (or the online documentation)

    For example, if the file /tmp/day.txt does not exist the playbook

    shell> cat pb.yml
    - hosts: localhost
      tasks:
        - stat:
            path: /tmp/day.txt
          register: stat_day
        - command: cat /tmp/day.txt
          register: day
          when: stat_day.stat.exists
          vars:
            ansible_callback_diy_runner_on_skipped_msg: |
              skipping: [{{ inventory_hostname }}]
              msg: File does not exist.
            ansible_callback_diy_runner_on_skipped_msg_color: green
    

    will display the custom message

    shell> ANSIBLE_STDOUT_CALLBACK=community.general.diy ansible-playbook pb.yml
    
    PLAY [localhost] *****************************************************************************
    
    TASK [stat] **********************************************************************************
    ok: [localhost]
    
    TASK [command] *******************************************************************************
    skipping: [localhost]
    msg: File does not exist.
    
    PLAY RECAP ***********************************************************************************
    localhost: ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
    

    Optionally, you can use the block/rescue construct. See Handling errors with blocks.

    For example, in Linux (I don't have access to Windows atm) when you try to access a nonexistent file by the module command on the localhost

        - command: cat /tmp/day.txt
          register: day
    

    the command will fail

    fatal: [localhost]: FAILED! => changed=true 
      ansible_facts:
        discovered_interpreter_python: /usr/bin/python3
      cmd:
      - cat
      - /tmp/day.txt
      delta: '0:00:00.010884'
      end: '2023-02-14 07:21:50.664051'
      msg: non-zero return code
      rc: 1
      start: '2023-02-14 07:21:50.653167'
      stderr: 'cat: /tmp/day.txt: No such file or directory'
      stderr_lines: <omitted>
      stdout: ''
      stdout_lines: <omitted>
    

    Put the command into the block and use the section rescue

        - block:
            - command: cat /tmp/day.txt
              register: day
            - debug:
                var: day.stdout
          rescue:
            - debug:
                var: ansible_failed_result
    

    Now, if the command fails you'll see

      ansible_failed_result:
        ansible_facts:
          discovered_interpreter_python: /usr/bin/python3
        changed: true
        cmd:
        - cat
        - /tmp/day.txt
        delta: '0:00:01.007972'
        end: '2023-02-14 07:24:43.791343'
        failed: true
        invocation:
          module_args:
            _raw_params: cat /tmp/day.txt
            _uses_shell: false
            argv: null
            chdir: null
            creates: null
            executable: null
            removes: null
            stdin: null
            stdin_add_newline: true
            strip_empty_ends: true
        msg: non-zero return code
        rc: 1
        start: '2023-02-14 07:24:42.783371'
        stderr: 'cat: /tmp/day.txt: No such file or directory'
        stderr_lines:
        - 'cat: /tmp/day.txt: No such file or directory'
        stdout: ''
        stdout_lines: []
    

    You can reduce the output to the standard error

          rescue:
            - debug:
                var: ansible_failed_result.stderr
    

    If the file exists

    shell> echo 'This is the content of /tmp/day.txt' > /tmp/day.txt
    

    The next task in the block will display the standard output of the command

      day.stdout: This is the content of /tmp/day.txt
    

    Of course, there will be differences in the error messages among the operating systems. Take a look at the data you get and fit the messages to your needs.