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

Я использую Ansible для развертывания веб-сайта Django на своих серверах (производство, постановка и т.д.), и я хотел бы получить уведомление (через 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

Я погружался в документацию Ansible, особенно в разделе

Ответ 1

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

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

Ответ 2

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

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

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

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

Ответ 3

@monkeymatrix Я делаю то же самое, мое спасение не выполняется после сбоя игры.