web-dev-qa-db-fra.com

Comment puis-je quitter le livre Ansible sans erreur sur une condition

Je souhaite quitter sans erreur (je connais les modules assert et fail ) lorsque je remplis certaines conditions. Le code suivant se termine mais avec un échec:

  tasks:

    - name: Check if there is something to upgrade
      Shell: if apt-get --dry-run upgrade | grep -q "0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded"; then echo "no"; else echo "yes"; fi
      register: upgrading

    - name: Exit if nothing to upgrade
      fail: msg="Nothing to upgrade"
      when: upgrading.stdout == "no"
19
jreisinger

Dans Ansible 2.2, vous pouvez utiliser end_play avec le module meta :

- meta: end_play

Vous pouvez également spécifier when pour mettre fin au jeu de manière conditionnelle:

- meta: end_play
  when: upgrading.stdout == "no"

Notez cependant que la tâche ne figure pas dans la sortie de ansible-playbook, que la lecture se termine ou non. En outre, la tâche n'est pas comptée dans le récapitulatif. Donc, vous pourriez faire quelque chose comme:

- block:
    - name: "end play if nothing to upgrade"
      debug:
        msg: "nothing to upgrade, ending play"

    - meta: end_play
  when: upgrading.stdout == "no"

qui annoncera la fin du jeu juste avant de le terminer, uniquement lorsque la condition est remplie. Si la condition n'est pas remplie, la tâche nommée end play if nothing to upgrade est correctement ignorée, ce qui fournirait plus d'informations à l'utilisateur sur la raison pour laquelle la lecture se termine ou non.

Bien entendu, cela ne fera que mettre fin à la lecture en cours et pas à tous lectures restantes dans le livre de lecture.

39
snapfla

Utilisons ce que Tymoteusz a suggéré pour les rôles:

Divisez votre jeu en deux rôles où le premier rôle exécutera le contrôle (et définira le résultat du contrôle de détention variable) et le second agira en fonction du résultat du contrôle.

J'ai créé aaa.yaml avec ce contenu:

---
- hosts: all
  remote_user: root
  roles:
    - check
    - { role: doit, when: "check.stdout == '0'" }
...

puis rôle check dans roles/check/tasks/main.yaml:

---
- name: "Check if we should continue"
  Shell:
    echo $(( $RANDOM % 2 ))
  register: check
- debug:
    var: check.stdout
...

puis rôle doit dans roles/doit/tasks/main.yaml:

---
- name: "Do it only on systems where check returned 0"
  command:
    date
...

Et ce fut la sortie:

TASK [check : Check if we should continue] *************************************
Thursday 06 October 2016  21:49:49 +0200 (0:00:09.800)       0:00:09.832 ****** 
changed: [capsule.example.com]
changed: [monitoring.example.com]
changed: [satellite.example.com]
changed: [docker.example.com]

TASK [check : debug] ***********************************************************
Thursday 06 October 2016  21:49:55 +0200 (0:00:05.171)       0:00:15.004 ****** 
ok: [monitoring.example.com] => {
    "check.stdout": "0"
}
ok: [satellite.example.com] => {
    "check.stdout": "1"
}
ok: [capsule.example.com] => {
    "check.stdout": "0"
}
ok: [docker.example.com] => {
    "check.stdout": "0"
}

TASK [doit : Do it only on systems where check returned 0] *********************
Thursday 06 October 2016  21:49:55 +0200 (0:00:00.072)       0:00:15.076 ****** 
skipping: [satellite.example.com]
changed: [capsule.example.com]
changed: [docker.example.com]
changed: [monitoring.example.com]

Ce n'est pas parfait: vous verrez sans cesse l'état skipping pour toutes les tâches des systèmes ignorés, mais cela pourrait faire l'affaire.

2
jhutar

Ce qui suit m'a été utile, car meta: end_play semble arrêter l'exécution pour tous les hôtes, pas seulement pour celui qui correspond.

D'abord établir un fait:

- name: Determine current version
  become: yes
  Slurp:
    src: /opt/app/CHECKSUM
  register: version_check
  ignore_errors: yes

- set_fact:
  is_update_needed: "{{ ( version_check['checksum'] | b64decode != installer_file.stat.checksum)  }}"

Incluez maintenant cette partie qui ne devrait être exécutée qu'à cette condition:

# update-app.yml can be placed in the same role folder
- import_tasks: update-app.yml
  when: is_update_needed
1
reto

Une solution meilleure et plus logique consiste à inverser la procédure et à ne pas échouer s'il n'y a rien à mettre à niveau (une étape distincte ne faisant que cela), vous pouvez ajouter toutes vos tâches de mise à niveau avec une condition dépendante de la upgrade. variable. En substance, il suffit d'ajouter 

when: upgrading.changed

tâches qui ne doivent être exécutées que lors d’une mise à niveau.

C’est un peu plus de travail, mais cela apporte aussi de la clarté et contient la logique qui affecte une tâche donnée en elle-même, plutôt que de dépendre de quelque chose au-dessus de laquelle peut ou non terminer la tâche plus tôt.

1
Tymoteusz Paul