Ansible: выполнить задачу (или обработчик), если какая-либо задача не удалась


Я использую Ansible для развертывания веб-сайта Django на моих серверах (production, staging и т. д.), И я хотел бы получить уведомление (в данном случае через slack), если и только если какая-либо задача не будет выполнена.

Я могу понять, как это сделать, только если определенная задача не выполняется (поэтому я думаю, что могу добавить обработчик ко всем задачам), но интуиция подсказывает мне, что должен быть более простой и элегантный вариант.

В основном то, о чем я думаю, это:

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

Я нырял в Ансибль. документация, особенно в разделеобработка ошибок , и ответы здесь в SO, но я изо всех сил пытаюсь найти ответ на свой вопрос. Так что любая помощь будет очень признательна.

2 15

2 ответа:

Я не думаю, что обработчик является решением, потому что обработчик будет уведомлен только в том случае, если задача сообщает об измененном состоянии. При сбое обработчик не будет уведомлен.

Кроме того, обработчики по умолчанию не будут уволены, если книга воспроизведения не удалась. Но это можно изменить. Для этого вам нужно будет установить это в вашем 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 может быть плагинами обратного вызова . Как следует из названия, с помощью таких плагинов вы можете писать обратные вызовы, которые могут быть запущены на различных событиях.

Опять же, если вы используете Ansible 2, вам повезло, потому что уже есть плагин slack callback: 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

Этот плагин может нуждаться в некоторых модификациях, чтобы соответствовать вашим потребностям. Если это так, скопируйте источник и сохраните его относительно вашего playbook как callback_plugins/custom_slack.py , а затем включите его в вашем ansible.cfg:

callback_whitelist = custom_slack

Если вы используете Ansible 1.икс вы должны посмотреть, как вы можете преобразовать его. API отличается, примеры для старого API можно найти здесь: https://github.com/ansible/ansible/tree/v1.9.4-1/plugins/callbacks

Я написал полный пример того, как использовать Block / Rescue и модуль Slack (не плагин обратного вызова), который обеспечивает значимый вывод ошибок с форматированием:

Первый ответ здесь дал мне часть пути, но только для любого другого, кто идет этим путем, борясь с тем же самым!

Простой пример из playbook выглядит следующим образом:

Playbook / 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 / задачи / сбой.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

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