【问题标题】:Looping or repeating through an included playbook based on conditional check in Ansible根据 Ansible 中的条件检查循环或重复包含的剧本
【发布时间】:2022-12-08 21:54:36
【问题描述】:

我目前有一本包含任务文件的剧本。在那个任务文件中,我想检查一个条件。如果该条件的退出代码不等于 0,则应重复任务文件中的所有步骤。我已经尝试了一些块和循环的变体,但我还没有想出一种方法来让它做我上面描述的事情。

目前我有这样的事情:

tasks:
  - name: call task file
    include: task_file.yml

task_file.yml

- name: perform an operations
  shell: do A
    
- name: check
  shell: do B
  register: result

接下来,我想告诉主剧本,如果result.rc != 0,请重复task_file.yml直到result.rc == 0

任何指针将不胜感激

无论退出代码是什么,剧本似乎都会结束。

【问题讨论】:

  • 请避免使用已弃用的 include,并使用特定的 include_<type> 语句,在特定情况下为 include_tasks。此备注对import => import_<type> 也有效。此外,我编辑了您的问题以使用playbooktask file 之间的正确措辞。确保你没有混淆两者。无论如何,您不能包含剧本。您最终可以使用 import_playbook 导入一个,但该语句仅在剧本的顶级列表中可用(基本上代替剧本)并且不支持任何类型的条件。

标签: loops ansible conditional-statements block ansible-2.x


【解决方案1】:

由于 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   

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-24
    • 1970-01-01
    • 1970-01-01
    • 2016-08-05
    • 1970-01-01
    • 2017-11-07
    • 1970-01-01
    相关资源
    最近更新 更多