2016-03-09 16 views
7

Sto utilizzando Ansible per distribuire un sito Web Django nei miei server (produzione, messa in scena, ecc.) E vorrei ricevere una notifica (via allentamento in questo caso) se e solo se qualche attività fallisce.Ansible: esegui attività (o gestore) in caso di qualsiasi attività non riuscita

Posso solo capire come farlo se un compito specificato fallisce (quindi suppongo di poter aggiungere un gestore a tutte le attività), ma l'intuizione mi dice che ci deve essere un'opzione più semplice ed elegante.

Fondamentalmente quello che sto pensando è:

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

Sono stato immersioni nella documentazione Ansible, specialmente nella sezione error handling, e le risposte qui a SO, ma sto lottando per trovare una risposta a la mia domanda. Quindi qualsiasi aiuto sarà molto apprezzato.

risposta

22

Non penso che un gestore sia una soluzione, poiché un gestore riceverà una notifica solo se l'attività riporta uno stato modificato. In caso di errore, il gestore non verrà informato.

Inoltre, i gestori di default non saranno attivati ​​se il playbook fallisce. Ma questo può essere cambiato. Per questo sarà necessario impostare questo nel vostro ansible.cfg:

force_handlers = True 

Ma sì, ci sono opzioni migliori disponibili.

Se si utilizza Ansible 2 è possibile utilizzare la nuova funzione blocks. I blocchi raggruppano le attività insieme e dispongono di una sezione di ripristino che verrà attivata solo se una delle attività ha esito negativo.

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

Un'altra opzione e particolarmente interessante se si sta utilizzando Ansible 1.x potrebbe essere callback plugins. Come suggerisce il nome con questo tipo di plugin, è possibile scrivere callback che possono essere attivati ​​su vari eventi.

Anche in questo caso, se si sta utilizzando Ansible 2 siete fortunati, perché c'è già è un plugin di callback allentamento disponibili: https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/callback/slack.py

Per usare questo plugin è necessario attivarlo nel vostro ansible.cfg:

callback_whitelist = slack 

E definire alcune variabili d'ambiente sul sistema per la configurazione:

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 

Questo plug-in potrebbe essere necessario qualche Modificati ons per soddisfare le tue esigenze. Se questo è il caso copiare il codice sorgente e memorizzarlo relativo alla vostra playbook come callback_plugins/custom_slack.py e quindi attivare nel tuo ansible.cfg:

callback_whitelist = custom_slack 

Se si utilizza Ansible 1.x si dovrà vedere come è possibile convertirlo. L'API è diversa, esempi per la vecchia API possono essere trovati qui: https://github.com/ansible/ansible/tree/v1.9.4-1/plugins/callbacks

+0

Grazie per una risposta così dettagliata. Era quello che stavo cercando esattamente. Mi vergogno di non aver letto "blocchi" nella documentazione – vabada

+1

È facile perdere le nuove funzionalità. Se vuoi vedere tutte le fantastiche novità disponibili, puoi guardare questo video di 30 minuti: https://www.youtube.com/watch?v=sy8i4VXIVEE – udondan

+0

Le richiamate sono l'opzione migliore! –

2

Ho scritto un esempio completo su come utilizzare Block/Rescue e il modulo Slack (non plug-in di callback) che fornisce output di errore significativo con la formattazione:

La prima risposta qui mi ha fatto di parte, ma solo per chiunque altro che viene in questo modo alle prese con la stessa cosa!

Un semplice esempio playbook appare come segue:

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 

E nel mio ruolo slack_handler (per la riusabilità):

ruoli/slack_handler/compiti /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 

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

Problemi correlati