web-dev-qa-db-fra.com

Ansible: exécuter la tâche (ou le gestionnaire) en cas d'échec d'une tâche

J'utilise Ansible pour déployer un site Web Django sur mes serveurs (production, staging, etc.), et j'aimerais recevoir une notification (via slack dans ce cas) si et seulement si une tâche échoue.

Je ne peux comprendre comment le faire que si une tâche spécifiée échoue (donc je suppose que je pourrais ajouter un gestionnaire à toutes les tâches), mais l'intuition me dit qu'il doit y avoir une option plus simple et plus élégante.

Fondamentalement, je pense à:

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

J'ai plongé dans la documentation Ansible, spécialement dans la section gestion des erreurs , et les réponses ici à SO, mais j'ai du mal à trouver une réponse à ma question. Donc, toute aide sera très appréciée.

19
vabada

Je ne pense pas qu'un gestionnaire soit une solution, car un gestionnaire ne sera informé que si la tâche signale un état modifié. En cas d'échec, le gestionnaire ne sera pas averti.

De plus, les gestionnaires par défaut ne seront pas déclenchés si le playbook a échoué. Mais cela peut être changé. Pour cela, vous devrez définir cela dans votre ansible.cfg:

force_handlers = True

Mais oui, de meilleures options sont disponibles.

Si vous utilisez Ansible 2, vous pouvez utiliser la nouvelle fonctionnalité blocks . Les blocs regroupent les tâches et ont une section de sauvetage qui ne sera déclenchée que si l'une des tâches a échoué.

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

Une autre option et particulièrement intéressante si vous utilisez Ansible 1.x pourrait être plugins de rappel . Comme son nom l'indique avec ce type de plugins, vous pouvez écrire des rappels qui peuvent être déclenchés sur divers événements.

Encore une fois, si vous utilisez Ansible 2, vous avez de la chance, car un plug-in de rappel est déjà disponible: https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/ callback/slack.py

Pour utiliser ce plugin, vous devez l'activer dans votre ansible.cfg:

callback_whitelist = slack

Et définissez certaines variables d'environnement sur votre système pour la configuration:

 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

Ce plugin peut nécessiter quelques modifications pour répondre à vos besoins. Si tel est le cas, copiez la source et stockez-la par rapport à votre playbook en tant que callback_plugins/custom_slack.py puis activez-le dans votre ansible.cfg:

callback_whitelist = custom_slack

Si vous utilisez Ansible 1.x, vous devrez voir comment vous pouvez le convertir. L'API est différente, des exemples de l'ancienne API peuvent être trouvés ici: https://github.com/ansible/ansible/tree/v1.9.4-1/plugins/callbacks

37
udondan

J'ai écrit un exemple complet sur la façon d'utiliser Block/Rescue et le module Slack (pas le plugin de rappel) qui fournit une sortie d'erreur significative avec le formatage:

La première réponse ici m'a donné une partie du chemin, mais juste pour quelqu'un d'autre qui vient de cette façon aux prises avec la même chose!

Un exemple de playbook simple se présente comme suit:

playbooks/playbook.yml

 - hôtes: "{{target_Host | default ('127.0.0.1')}}" 
 rassembler_facts: vrai 
 
 tâches: 
 - block: 
 - include_role: 
 nom: install_app 
 - nom: Salut le monde 
 Shell: echo "hello world!" 
 - échec: 
 msg: "Je suis parti et j'ai échoué le jeu!" 
 sauvetage: 
 - include_role: 
 nom: slack_handler 
 tâches_de: échec 

Et dans mon rôle slack_handler (pour la réutilisabilité):

roles/slack_handler/tasks/failure.yml

 - nom: Notify Slack of Playbook Failure 
 slack: 
 nom d'utilisateur: 'Ansible' 
 couleur: danger 
 jeton: "{{slack_webhook. split ('https://hooks.slack.com/services/') [1]}} "
 canal:" # déploiement-alertes "
 msg:" Ansible a échoué sur * {{ ansible_hostname}} ({{inventaire_hostname}}) *\n 
 * Tâche *: {{ansible_failed_task.name}}\n 
 * Action *: {{ansible_failed_task.action}}\n 
 * Message d'erreur *:\n `` {{ansible_failed_result | to_Nice_json}} `` `" 
 Delegate_to: localhost 

Réf: http://www.petewilcock.com/ansible-slack-failure-handler/

4
monkeymatrix