最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

ansible - Combining rescuse-handlers and run_once in roles - Stack Overflow

programmeradmin2浏览0评论

I came across something interesting while refactoring an existing Ansible playbook.
Here is a reduced version of it:

|_ showcase.yml
\_ sc_role
    \_ tasks
        |_ main.yml
        \_ block-with-rescue.yml

File contents:

  • showcase.yml
    ---
    - hosts: [a, b]
      gather_facts: false
      tasks:
      - include_role:
          name: sc_role
    
  • sc_role/tasks/main.yml
    ---
    - include_tasks:
        file: block-with-rescue.yml
    - debug:
        msg: "run_once task"
      run_once: true
      delegate_to: localhost
    
  • sc_role/tasks/block-with-rescue.yml
    ---
    - block:
        - debug:
            msg: "Provoke exception {{ u_n_d_e_f_i_n_e_d }}"
          when: inventory_hostname == "a"
      rescue:
        - debug:
            msg: "rescue task"
    

Usecase: In the original playbook the include block-with-rescue.yml contains tasks that do maintance on a couple of hosts (simulated by "a" and "b" here). The maintance produces logfiles that are moved to a ZIP and send out to a reporting server. This is simulated by the debug task with the "run_once task" message here.

The reduced playbook can be executed in a vanilla Ansible setup without further configuration (I used Ansible 2.10.8 + Python 3.10.12) like this:

ansible-playbook -c local -i a,b, showcase.yml

When the playbook executes and host "a" fails at the provoked exception, execution continues for "b" at the "run_once" task. Then the rescue handler is run for "a" and the "run_once" task is executed a second time. This is of course not intended, because it messes up the already send out reporting data.

I am aware of the differences between "include" and "import". But the effect is the same for both.

This does not happen, when I include the role within a "roles" section of "showcase.yml" or when the "run_once" task is moved to "showcase.yml" behind the "[import/include]_role" statement.

So I know how to work around this, but I want to understand WHY it is happening. I don't feel confident using roles with rescue-handlers, if their behavior depends on the way, they have been included.

Here is an example job-output:

PLAY [a,b] ******************************************************************************************************************************************************************************************************************************************************************

TASK [include_role : sc_role] ***********************************************************************************************************************************************************************************************************************************************

TASK [sc_role : include_tasks] **********************************************************************************************************************************************************************************************************************************************
included: (..)/sc_role/tasks/block-with-rescue.yml for a, b

TASK [sc_role : debug] ******************************************************************************************************************************************************************************************************************************************************
fatal: [a]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'u_n_d_e_f_i_n_e_d' is undefined\n\nThe error appears to be in '(..)/sc_role/tasks/block-with-rescue.yml': line 3, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n- block:\n    - debug:\n      ^ here\n"}
skipping: [b]

TASK [sc_role : debug] ******************************************************************************************************************************************************************************************************************************************************
ok: [b] => {
    "msg": "run_once task"  <===== First execution for "b"
}

TASK [sc_role : debug] ******************************************************************************************************************************************************************************************************************************************************
ok: [a] => {
    "msg": "rescue task"
}

TASK [sc_role : debug] ******************************************************************************************************************************************************************************************************************************************************
ok: [a] => {
    "msg": "run_once task"  <===== Second execution for "a"
}

PLAY RECAP ******************************************************************************************************************************************************************************************************************************************************************
a                          : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=1    ignored=0   
b                          : ok=2    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
发布评论

评论列表(0)

  1. 暂无评论