Ansible:如果任何任务失败,则执行任务(或处理程序)

时间:2016-03-09 13:05:21

标签: ansible ansible-playbook

我正在使用Ansible将Django网站部署到我的服务器(生产,登台等),我希望当且仅当任何任务失败时才会收到通知(在这种情况下通过松弛)。

如果指定的任务失败,我只能弄清楚如何做到(所以我想我可以为所有任务添加一个处理程序),但是直觉告诉我必须有一个更简单,更优雅的选项。

基本上我的想法是:

---
- hosts: "{{hosts_to_deploy}}"

- tasks: 

   [...]

  - name: notify slack of deploy failure
    local_action:
      module: slack
      token: "{{slack_token}}"
      msg: "Deploy failed on {{inventory_hostname}}"
    when: # any task failed

我一直在深入探讨Ansible文档,特别是在error handling部分,并在SO处回答,但我很难找到问题的答案。所以任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:37)

我认为处理程序不是解决方案,因为只有在任务报告更改状态时才会通知处理程序。在失败状态下,将不会通知处理程序。

此外,如果剧本失败,将不会触发默认处理程序。但这可以改变。为此,您需要在ansible.cfg

中进行设置
force_handlers = True

但是,有更好的选择。

如果您使用Ansible 2,则可以使用新的blocks功能。阻止将任务组合在一起,并设置一个救援部分,只有在任何任务失败时才会触发。

tasks:
  - block:
      - here
      - go
      - all
      - your
      - tasks
    rescue:
      - name: notify slack of deploy failure
        local_action:
          module: slack
          token: "{{slack_token}}"
          msg: "Deploy failed on {{inventory_hostname}}"

另一个选项,如果您使用Ansible 1.x特别有趣,可能是callback plugins。顾名思义,这些插件可以编写回调,可以在各种事件中触发。

同样,如果您使用Ansible 2,那么您很幸运,因为已经有一个松弛的回调插件可用:https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/callback/slack.py

要使用此插件,您需要在ansible.cfg

中启用它
callback_whitelist = slack

在系统上定义一些环境变量以进行配置:

 This plugin makes use of the following environment variables:
    SLACK_WEBHOOK_URL (required): Slack Webhook URL
    SLACK_CHANNEL     (optional): Slack room to post in. Default: #ansible
    SLACK_USERNAME    (optional): Username to post as. Default: ansible
    SLACK_INVOCATION  (optional): Show command line invocation
                                  details. Default: False

该插件可能需要进行一些修改才能满足您的需求。如果是这种情况,请复制源并将其相对于您的剧本存储为callback_plugins/custom_slack.py,然后在ansible.cfg中启用它:

callback_whitelist = custom_slack

如果你使用Ansible 1.x,你必须看看如何转换它。 API不同,可以在此处找到旧API的示例:https://github.com/ansible/ansible/tree/v1.9.4-1/plugins/callbacks

答案 1 :(得分:4)

我写了一个关于如何使用Block / Rescue和Slack模块(不是回调插件)的完整示例,该模块通过格式化提供有意义的错误输出:

这里的第一个答案让我成为了我的一部分,但是对于其他任何以这种方式挣扎同样事情的人来说!

一个简单的剧本示例如下:

<强>剧本/ playbook.yml

- hosts: "{{ target_host | default('127.0.0.1') }}"
  gather_facts: true

  tasks:
  - block:
    - include_role:
        name: install_app
    - name: Greet the world
      shell: echo "hello world!"
    - fail:
       msg: "I've gone and failed the play!"
    rescue:
      - include_role:
          name: slack_handler
          tasks_from: failure

我的slack_handler角色(可重用性):

<强>角色/ slack_handler /任务/ failure.yml

- name: Notify Slack of Playbook Failure
  slack:
    username: 'Ansible'
    color: danger
    token: "{{ slack_webhook.split('https://hooks.slack.com/services/')[1] }}"
    channel: "#deployment-alerts"
    msg: "Ansible failed on *{{ ansible_hostname }} ({{ inventory_hostname }})* \n
    *Task*: {{ ansible_failed_task.name }} \n
    *Action*: {{ ansible_failed_task.action }} \n
    *Error Message*: \n ```{{ ansible_failed_result | to_nice_json }}``` "
  delegate_to: localhost

参考:http://www.petewilcock.com/ansible-slack-failure-handler/