1

I am trying to include multiple tasks based on some values defined in one hostvar but some fatal errors are thrown even if I'm using the block-rescue block. I have the variable profiles defined in host_vars/hostname.yml:

profiles: '["profile1","trap1"]'

and the role test_profiles in /etc/ansible/roles. Here, into the tasks directory I have the following .yml files: profile1.yml, profile2.yml, main.yml.

The content of main.yml file is:

- name: import profiles
   block:
     - include_tasks: "{{ item }}.yml"
       with_items: "{{ profiles|default([]) }}"
   rescue:
     - debug: msg='Error encountered while trying to include a .yml file corresponding to a defined profile from profiles variable. Profiles - "{{ profiles }}"'
   when: profiles is defined

Playbook's content is:

 - name: Test profiles config
   hosts: myhost
   roles:
     - test_profiles

The output is something like this:

TASK [test_profiles : include_tasks] ***********************************************************************************************************************************************************************
included: /etc/ansible/roles/test_profiles/tasks/profile.yml for <my_host>
fatal: [<my_host>]: FAILED! => {"reason": "Unable to retrieve file contents\nCould not find or access '/etc/ansible/trap1.yml'"}

TASK [test_profiles : Ensure that profile directory exists into the D:\profiles directory] ************************************************************************************************
ok: [<my_host>]

TASK [test_profiles : Update profile.properties file] ***************************************************************************************************************************************************
ok: [<my_host>]

TASK [test_profiles : debug] *******************************************************************************************************************************************************************************
ok: [<my_host>] => {
    "msg": "Error encountered while trying to include a .yml file corresponding to a defined profile from profiles variable. Profiles - \"[\"profile1\",\"trap1\"]\""
}
        to retry, use: --limit @/etc/ansible/playbook_test_profiles.retry

PLAY RECAP ********************************************************************************************************************************************************************************************************
<my_host>                 : ok=5    changed=0    unreachable=0    failed=1

From my point of view that fatal error should not appear. What am I doing wrong here and how can I get rid of this? I've also tried with a when conditional but without success.

I'm using Ansible 2.4.2.0 and the tasks are performed for some windows hosts.

pandoJohn
  • 415
  • 1
  • 5
  • 8

2 Answers2

1

block/rescue does not prevent error from happening. It detects failed task and execute rescue block to recover from the error. But the failed task is still there and will be visible in play recap.

I'd recommend to use fail fast approach when designing playbooks. In your case you can scan your local files to test if user input (supplied configuration) is valid: whether profiles files are in place. User assert/fail modules.

Konstantin Suvorov
  • 3,996
  • 1
  • 12
  • 13
0

In the end I removed the block-rescue block. I've found out a way to check if my .yml file exists. This is using the role_path variable (which will return the current role’s path - available since Ansible 1.8 - this works only inside a role) and the test is_file.

My main.yml for the above described role is looking like this:

- name: Import profiles
   include_tasks: "{{ item }}.yml"
   with_items: "{{ profiles|default([]) }}"
   when: (role_path + '/tasks/' + item + '.yml') | is_file

Because of this check a fatal exception will no longer be thrown - the trap1.yml file will be skipped.

The output will be something like:

TASK [test_profiles : Import profiles] ***********************************************************
skipping: [<my_host>] => (item=trap1)
included: /etc/ansible/roles/test_profiles/tasks/profile1.yml for <my_host>

TASK [test_profiles : Ensure that profile directory exists into the D:\profiles directory] *******
ok: [<my_host>]

TASK [test_profiles : Update profile.properties file] ********************************************
changed: [<my_host>]
        to retry, use: --limit @/etc/ansible/playbook_test_profiles.retry

PLAY RECAP ***************************************************************************************
<my_host>                 : ok=4    changed=1    unreachable=0    failed=0

I'm OK with this solution but I'm open to some other suggestions too.

pandoJohn
  • 415
  • 1
  • 5
  • 8