5
votes

exécuter une tâche accessible uniquement si la balise n'est PAS spécifiée

Dites que je souhaite exécuter une tâche uniquement lorsqu'une balise spécifique est PAS dans la liste des balises fournies sur la ligne de commande, même si d'autres balises sont spécifiées. Parmi ceux-ci, seul le dernier fonctionnera comme prévu dans toutes les situations:

- name: check and perhaps reboot
  block:
  - name: Check if a reboot is required
    stat:
      path: /var/run/reboot-required
      get_md5: no
    register: reboot
    tags: always,reboot

  - name: Alert if a reboot is required
    fail:
      msg: "NOTE: a reboot required to finish uppdates."
    when:
      - ('reboot' not in ansible_run_tags)
      - reboot.stat.exists
    tags: always

  - name: Reboot the server
    reboot:
      msg: rebooting after Ansible applied system updates
    when: reboot.stat.exists or ('force-reboot' in ansible_run_tags)
    tags: never,reboot,force-reboot

Essayez-le avec différentes options CLI et vous verrez, espérons-le, pourquoi je trouve cela un peu déroutant: p >

ansible-playbook tags-test.yml -l HOST
ansible-playbook tags-test.yml -l HOST -t TAG
ansible-playbook tags-test.yml -l HOST -t OTHERTAG

Questions: (a) est-ce le comportement attendu? et (b) y a-t-il un meilleur moyen ou une logique qui me manque?

Je suis surpris d'avoir dû creuser dans la variable (non documentée, AFAICT) ansible_run_tags .


Amendement: il a été suggéré que je publie mon cas d'utilisation réel. J'utilise ansible pour conduire des mises à jour système sur les systèmes de la famille Debian. J'essaye de notifier à la fin si un redémarrage est nécessaire à moins que la balise reboot n'ait été fournie, auquel cas provoquer un redémarrage (et attendre que le système revienne) ). Voici l'extrait de code pertinent:

- hosts: all
  tasks:
    - debug:
        msg: 'not TAG (won't work if other tags specified)'
      tags: not TAG

    - debug:
        msg: 'always, but not if TAG specified (doesn't work; always runs)'
      tags: always,not TAG

    - debug:
        msg: 'ALWAYS, but not if TAG in ansible_run_tags'
      when: "'TAG' not in ansible_run_tags"
      tags: always

Je pense que mes questions d'origine ont encore du mérite, mais je suis également prêt à accepter d'autres méthodes pour réaliser cette même fonctionnalité.


4 commentaires

Les balises ne sont pas censées être utilisées de cette façon. Si vous fournissez -t TAG , vous vous attendez généralement à ce que toutes les tâches marquées soient exécutées et non les tâches qui ont des marques «not TAG».


Je comprends que je pourrais contourner les règles d'utilisation des balises, mais j'aurais espéré que le premier exemple ( tags: not TAG ) s'exécuterait à chaque fois qu'aucune balise ni aucune combinaison de balises SAUF TAG a été spécifié. Je peux vous donner un exemple précis des raisons pour lesquelles je trouverais cela utile, si vous le souhaitez.


Oui s'il vous plaît. Parce que cela semble être un problème XY .


modifié avec le cas d'utilisation réel.


3 Réponses :


1
votes

Je sais que c'est une vieille question (ish), mais j'avais une exigence similaire.

C'est probablement quelque chose de mieux implémenté d'une autre manière ... mais ... parfois cela peut être utile.

J'y parviendrais en définissant un fait si la balise EST spécifiée, puis en émettant le message uniquement si le fait n'est pas défini, quelque chose comme:

---
- name: "test task runs only if tag missing"
  hosts: all
  tasks:
    - name: "suppress message if tag given"
      set_fact: suppress_message=yes
      tags: reboot,never

    - name: "message"
      debug:
        msg: "You didn't say 'reboot'"
      when: suppress_message is not defined


3 commentaires

J'aime la pensée, cependant, et je suis sûr que c'est une préférence personnelle, que la propagation du «comportement» à travers plusieurs tâches est une chose contre laquelle j'ai tendance à me battre (incliner?).


Bien sûr, ne soyez pas en désaccord avec cela comme objectif, mais je ne connais pas un moyen de le faire en une seule tâche, et cela répond à vos exigences et vous avez dit "Je suis également prêt à accepter d'autres méthodes pour accomplir la même chose Fonctionnalité." :-)


Nous le faisons de cette façon pour contourner les capacités manquantes lors de l'utilisation de balises pour CONTRÔLER quelque chose. Et pendant que nous faisons set_fact avec des balises pour définir des indicateurs pour contrôler le déroulement du jeu, nous essayons de travailler contre la nature d'ansible, qui est déclarative plutôt que impérative. En d'autres termes: faire cela est une programmation impérative, pas une déclaration d'états.



7
votes

Par souci d'exhaustivité, et puisque seul @ paul-sweeney a proposé une solution alternative, je répondrai à ma propre question avec ma meilleure solution actuelle et je laisserai les gens choisir / voter leur favori:

---
- name: run only if 'TAG' not specified
  debug:
    msg: 'ALWAYS, but not if TAG in ansible_run_tags'
  when: "'TAG' not in ansible_run_tags"
  tags: always


0 commentaires

0
votes

Je pense que nous avons des états pour contrôler (exemple: démarré, redémarré, arrêté), des états pour l'installation (présent, absent) et des composants (serveur web, db, ...). Ansible ne dispose pas d'une bonne séparation de ces 3 dimensions et mélanger ces 3 dimensions dans un seul système de balises est source de confusion.

Par exemple, si vous avez une balise "webserver" et "DB", vous souhaitez "redémarrer" la base de données et non le serveur Web en utilisant une balise "restart". Mais cela ne fonctionnera pas si les tâches de 'redémarrage' de la base de données et du serveur Web sont dans le même fichier de tâches avec la même balise 'restart' que la balise 'restart' lancera à la fois la base de données et le serveur Web ...

Vous devrez donc probablement séparer les tâches du serveur Web et de la base de données dans 2 fichiers séparés et utiliser la balise au niveau de l'inclusion.

L'utilisation de balises signifie que vous avez un arbre d'options, pas une matrice d'options.

J'aime le concept de balise mais le fait qu'il ne soit pas possible de l'utiliser dans des expressions conditionnelles le rend moins attrayant.

Ce que je recommande, c'est de déclarer des balises dans un rôle, mais de les mapper en variables comme première tâche. Ainsi, les balises 'restart' et 'db' deviendraient des variables booléennes dans mon rôle et utiliseraient when: au lieu de balises:


0 commentaires