如何编写可以在失败时运行任务的ansible处理程序?

时间:2018-05-14 01:45:47

标签: ansible handler

我想使用ansible 2.5.2来执行一些升级任务,如果失败则回滚到之前的安装。我对所有配置更改使用notify,以防止在没有更改的情况下进行升级。我最初想在该通知的处理程序中使用block:rescue:语句。

然而,由于尚未支持(https://github.com/ansible/ansible/issues/14270),我采用了建议的解决方法,在通知块中包含另一个任务,最终得到与以下内容等效的内容:

upgrade
|-handlers
  main.yml
  - name: upgrade task
    include: upgrade.yml
|-tasks
  main.yml
  - name: Update configuration 1
    template: src=conf.j2 dest={{ conf_dir }}/conf.conf
    notify: upgrade task
  - name: Update configuration 2
    template: src=conf2.j2 dest={{ conf_dir }}/conf2.conf
    notify: upgrade task

  upgrade.yml
  - block:
    - debug: msg="Starting upgrade"
    - name: Simulate failure of first of many upgrade tasks
      command: /bin/false
    rescue:
    - debug: msg="Upgrade failed, rolling back now"
    - name: Rollback deploy
      include: rollback.yml
    always:
    - debug: msg="Upgrade complete"

  rollback.yml
    ....

正如预期的那样,失败了:

RUNNING HANDLER [upgrade : Simulate failure of first of many upgrade tasks] 
fatal: [hostname]: FAILED!

但不会打印Upgrade failedUpgrade complete,并且不会执行rollback.yml

可能性似乎是:

  1. 我的任务中存在一个错误,它会无声地阻止救援块运行。
  2. 在包含的游戏中,有一个尚未提出块的ansible错误。
  3. 我不想支持我想做的事。
  4. 任何人都可以发现问题或者以支持的方式给我一些关于构建此问题的指示吗?我能想到的唯一选择是使用listen对处理程序进行分组,将它们标记为已更改但在失败时不会失败,并让它们通知回滚任务,但乍一看这似乎是非常的脆弱。

1 个答案:

答案 0 :(得分:1)

答案似乎是2和3.如果示例块被移动到main.yml中,它将完美地运行,排除1。

在我在问题中链接的功能请求的评论中,另一个人在2016年提到了相同的问题,所以我现在提出了一个新的错误:https://github.com/ansible/ansible/issues/40130

要回答关于我建议的解决方法的更好替代方法的问题,可以使用register:作为条件允许将块移动到tasks/main.yml:< / p>

- name: Update configuration 1
  template: src=conf.j2 dest={{ conf_dir }}/conf.conf
  register: update1

- name: Update configuration 2
  template: src=conf2.j2 dest={{ conf_dir }}/conf2.conf
  register: update2

- block:
  - debug: msg="Starting upgrade"
    when: update1.changed or update2.changed

  - name: Simulate failure of first of many upgrade tasks
    command: /bin/false
    when: update1.changed or update2.changed

  rescue:
  - debug: msg="Upgrade failed, rolling back now"

  - name: Rollback deploy
    include: rollback.yml

  always:
  - debug: msg="Upgrade complete"

这仍然很脆弱,因为每次添加配置任务时都需要记住更新块中的所有内容。如果您可以手动刷新处理程序,则以下方法可以消除此问题,并且有点清洁恕我直言:

- name: Update configuration 1
  template: src=conf.j2 dest={{ conf_dir }}/conf.conf
  notify: trigger upgrade

- name: Update configuration 2
  template: src=conf2.j2 dest={{ conf_dir }}/conf2.conf
  notify: trigger upgrade

- meta: flush_handlers

- block:
  - debug: msg="Starting upgrade"
    when: upgrade is defined and upgrade.changed
    ...

其中trigger upgradehandlers/main.yml中的一个虚拟更改的处理程序,即:

- name: trigger upgrade
  shell: echo "Upgrading"
  register: upgrade

我认为在修复错误或处理程序允许阻止之前,这是最好的。