由于 include_tasks 不支持 retry/until 循环关键字,因此无法直接实现您的目标。
有人试图通过 teaching ansible a new loop_control.until keyword for 循环来规避该限制,该循环可用于包含。不幸的是,pull request 从 2019 年 9 月开始,至今仍未发布。
好消息是,您可以通过对块使用包含递归来通过一些工作来实现它。下面的例子改编自a blog article on https://dev.to。我修复了一些好的做法并添加了灵活的重试次数和重试之间的延迟等功能。开始了:
要重试的任务进入task_file.yml
---
- name: group of tasks to repeat until success
block:
- name: increment attempts counter
ansible.builtin.set_fact:
attempt_number: "{{ attempt_number | d(0) | int + 1 }}"
- name: dummy task
debug:
msg: "I'm a dummy task"
- name: task to check for success.
# Just for the example. Will return success on attempt number 3
ansible.builtin.command: "[ {{ attempt_number | int }} -eq 3 ]"
changed_when: false
rescue:
- name: "Fail if we reached the max of {{ max_attempts | d(3) }} attempts"
# Default will be 3 attempts if max_attempts is not passed as a parameter
ansible.builtin.fail:
msg: Maximum number of attempts reached
when: attempt_number | int == max_attempts | int | d(3)
- ansible.builtin.debug:
msg: "group of tasks failed on attempt {{ attempt_number }}. Retrying"
- name: add delay if needed
# no delay if retry_delay is not passed as parameter
ansible.builtin.wait_for:
timeout: "{{ retry_delay | int | d(omit) }}"
when: retry_delay is defined
# include ourselves to retry.
- ansible.builtin.include_tasks: task_file.yml
如您所见,该文件会在失败的情况下再次包含自身,直到达到最大尝试成功为止。另外,请注意,如果块内的任何任务失败,都会发生重试,而不仅仅是最后一个。如果您有更复杂的场景,您可以在 rescue 部分中实施更多的失败/未失败检查,如果需要,甚至可以添加 always 部分。见anbile blocks
然后你可以从你的剧本中调用这个文件:
---
- hosts: localhost
gather_facts: false
tasks:
- name: Include tasks to retry. 7 attempts max with 1 second delay
ansible.builtin.include_tasks: task_file.yml
vars:
max_attempts: 7
retry_delay: 1
正如硬编码和预期的那样,第三次尝试播放此示例会成功。 (您可以使用参数来测试失败场景)
$ ansible-playbook playbook.yml
PLAY [localhost] ***********************************************************************************************************************************************************************************************************************
TASK [Include tasks to retry] **********************************************************************************************************************************************************************************************************
included: /tmp/toto/task_file.yml for localhost
TASK [increment attempts counter] ******************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [dummy task] **********************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "I'm a dummy task"
}
TASK [task to check if success.] *******************************************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "cmd": ["[", "1", "-eq", "3", "]"], "delta": "0:00:00.002104", "end": "2022-12-08 14:16:27.850578", "msg": "non-zero return code", "rc": 1, "start": "2022-12-08 14:16:27.848474", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
TASK [Fail if we reached the max of 7 attempts] ****************************************************************************************************************************************************************************************
skipping: [localhost]
TASK [ansible.builtin.debug] ***********************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "group of tasks failed on attempt 1. Retrying"
}
TASK [add delay if needed] *************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [ansible.builtin.include_tasks] ***************************************************************************************************************************************************************************************************
included: /tmp/toto/task_file.yml for localhost
TASK [increment attempts counter] ******************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [dummy task] **********************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "I'm a dummy task"
}
TASK [task to check if success.] *******************************************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "cmd": ["[", "2", "-eq", "3", "]"], "delta": "0:00:00.004009", "end": "2022-12-08 14:16:29.496509", "msg": "non-zero return code", "rc": 1, "start": "2022-12-08 14:16:29.492500", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
TASK [Fail if we reached the max of 7 attempts] ****************************************************************************************************************************************************************************************
skipping: [localhost]
TASK [ansible.builtin.debug] ***********************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "group of tasks failed on attempt 2. Retrying"
}
TASK [add delay if needed] *************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [ansible.builtin.include_tasks] ***************************************************************************************************************************************************************************************************
included: /tmp/toto/task_file.yml for localhost
TASK [increment attempts counter] ******************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [dummy task] **********************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "I'm a dummy task"
}
TASK [task to check if success.] *******************************************************************************************************************************************************************************************************
ok: [localhost]
PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost : ok=14 changed=0 unreachable=0 failed=0 skipped=2 rescued=2 ignored=0