Ansible: Exécuter la tâche uniquement lorsqu'une balise est spécifiée

75

Les balises Ansible peuvent être utilisées pour exécuter uniquement un sous-ensemble de tâches / rôles. Cela signifie que par défaut toutes les tâches sont exécutées et que nous ne pouvons empêcher que certaines tâches de s'exécuter.

Pouvons-nous limiter l’exécution d’une tâche uniquement lorsque la balise "foo" est spécifiée? Pouvons-nous utiliser les balises actuelles dans la whensection d’une tâche?

Taha Jahangir
la source
2
cela ressemble à ce dont vous avez besoin est un paramètre de tâche tel que limit_to_tags: foo qui n’existe pas et je ne pense pas que ce soit possible pour le moment. Une implémentation future doit également avoir un plan indiquant si ET ou OU ces balises doivent être combinées.
dgh
Jetez un coup d'oeil à ma réponse dans "Ansible - Tags par défaut / explicites" stackoverflow.com/questions/28789912/…
sirkubax

Réponses:

38

Ansible 2.5 est livré avec des étiquettes spéciales neveret always. Tag neverpeut être utilisé exactement à cette fin. Par exemple:

tasks:
  - debug: msg='{{ showmevar}}'
    tags: [ 'never', 'debug' ]

Dans cet exemple, la tâche ne sera exécutée que lorsque la balise debug(ou never) est explicitement demandée. [Référence sur ansible docs]

Taha Jahangir
la source
20

Bien que ce soit une solution détournée, cela fonctionne.

Dans la liste des tâches, enregistrez une variable lors de l'exécution normale. Ajoutez ensuite une condition when qui vérifie cette variable dans la tâche balisée.

- shell: /bin/true
  register: normal_task_list

- name: Only run when tag is specified
  shell: /bin/echo "Only running because of specified tag"
  when: normal_task_list is not defined
  tags: specified
Chris Chipman
la source
Vous pouvez également utiliser untaggedpour ce faire:- set_fact: untagged_run=true tags: untagged
Pyzo
Pouvez-vous expliquer un peu plus à ce sujet? Un exemple du monde réel?
Quintin Par
17

Je n'ai pas assez de réputation pour voter ou commenter la réponse suggérant l'utilisation de variables en ligne de commande ( --extra-vars), mais je dois ajouter ceci:

La mise en garde à cette méthode est que la lecture sera une erreur et échouera si vous ne définissez pas cette variable supplémentaire.

Vous pouvez empêcher les échecs de lecture en l'absence de --extra-varsdéfinition en définissant une valeur par défaut dans le playbook lui-même:

---
- hosts: ...
# ↓↓↓
  vars:
    thorough: false
# ↑↑↑
  tasks:
  - name: apt - install nfs-common only when thorough is true
    when: thorough | bool
    apt:
      cache_valid_time: 86400
      force: yes
      pkg:
        - nfs-common

La substitution via --extra-varsfonctionnera toujours car les variables définies sur la ligne de commande ont priorité sur toutes les autres définitions.

Le résultat est que la lecture est exécutée sans erreur si elle thoroughn'est pas modifiée truesur la ligne de commande.

Alex Peters
la source
5
La même chose peut être obtenue en utilisant thorough | default('no') | bool.
Costi Ciudatu
2
Ou when: thorough is defined and thoroughsi vous préférez cette syntaxe
KCD le
Merci, aime plus la is defined andsyntaxe. plus que les multiples tuyaux que je ne pense pas sont intuitifs.
Elijah Lynn
10

Vous pouvez utiliser les conditions pour vous protéger contre les tâches en cours d'exécution qui seraient autrement exécutées par inadvertance si vous ne spécifiez pas de balise. La mise en garde à cette méthode est que la lecture sera une erreur et échouera si vous ne définissez pas cette variable supplémentaire.

En utilisant l'argument extra-vars, vous pouvez déclencher l'exécution de votre conditionnel.

De ansible-playbook --help:

 -e EXTRA_VARS, --extra-vars=EXTRA_VARS
    set additional variables as key=value or YAML/JSON

Exemple:

ansible-playbook test.yaml -e "thorough=true"

test.yaml:

...
- name: apt - install nfs-common only when thorough is true
  apt:
    cache_valid_time: 86400
    force: yes
    pkg:
    - nfs-common
  when: thorough | default(False)
...
Ava
la source
2
Pour éviter une erreur si vous ne définissez pas "approfondie", utilisez simplement thorough | default("false") | match("true"). Par défaut ne doit pas être false, juste quelque chose qui ne correspond pas true, mais il améliore la lisibilité.
Tom Wilson
4

Vérifier la variable 'tags' ne fonctionne pas dans Ansible 2.1.1.0. Voir ci-dessous pour le test. J'ai une autre idée pour exécuter la tâche uniquement quand une balise est définie, travaillant à la fois pour Ansible 1.9.X et 2.XY:

- set_fact: foo=true
  tags: bar
- set_fact: foo=false
- name: do something when 'bar' tag is defined
  debug: var=foo
  when: foo
  tags: bar

Avec cela, lors de l'exécution du livre de lecture sans balise, la variable 'foo' sera définie sur true, puis sur false, de sorte que rien n'est exécuté. Si vous ajoutez la balise 'bar', seul le premier paramètre sera appliqué. La variable 'foo' sera donc vraie et votre tâche sera exécutée. Prendre plaisir!


Et voici le test sur la variable 'tags' dans Ansible 2.1.1.0:

Voici le playbook:

- hosts: localhost
  connection: local
  tasks:
    - name: display tags variable
      debug: var=tags
      tags: foo

    - name: do something only when tag 'foo' is provided
      debug: var=tag
      when: tags is defined
      tags: foo

Et voici la sortie:

$ ansible-playbook --version ; ansible-playbook ./test.yml -t foo
ansible-playbook 2.1.1.0
  config file = /home/nootal/projects/ivy/src/ansible/ansible.cfg
  configured module search path = Default w/o overrides

PLAY [localhost] ***************************************************************

TASK [display tags variable] ***************************************************
ok: [localhost] => {
    "tags": "VARIABLE IS NOT DEFINED!"
}

TASK [do something only when tag 'foo' is provided] ****************************

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0   
nootal
la source
2

Oui. Exécuter ansible-playbook avec le --tags foodrapeau garantira que seules les tâches marquées foosont exécutées. Par exemple, supposons que nous ayons un livre de lecture appelé example.yml:

tasks:

  - yum: name={{ item }} state=installed
    with_items:
       - httpd
       - memcached
    tags:
       - packages

  - name: some other task
    ..
    tags:
      - some other tag

fonctionnement:

ansible-playbook example.yml --tags "packages"

S'assurera que seule la tâche yum est exécutée.

Donc, en réalité, vous n'avez pas vraiment besoin d'utiliser des balises dans section pour exécuter une tâche de manière conditionnelle. Notez que selon la complexité de vos playbooks / rôles, vous devrez peut-être utiliser une combinaison de --tags et de --skip-tags pour contrôler les tâches à exécuter. Par exemple, si une tâche à inclure est étiquetée comme "foo" et qu'une tâche du livre de lecture inclus est étiquetée comme "barre" et que vous exécutez

ansible-playbook --tags "foo"

La tâche interne (étiquetée uniquement en tant que "barre") sera exécutée. Pour éviter l'exécution de toutes les tâches internes marquées 'bar', vous devrez exécuter la commande suivante

ansible-playbook --tags foo --skip-tags bar
Shahar
la source
7
Ce n'est pas vrai: "Spécifier une balise sur une tâche signifie que cette tâche ne sera exécutée que lorsque cette balise sera explicitement passée à la commande ansible-playbook."
Gimboland
1
Appuyé, la déclaration n'est pas vraie.
Chris
10
Oui, vous pouvez obtenir ce comportement en vous assurant que vous utilisez toujours les bonnes ansible-playbookoptions, mais je pense que l'OP demande un moyen d'annoter une tâche afin qu'elle ne soit pas exécutée à moins qu'une balise spécifique ne soit explicitement ajoutée à la ansible-playbookcommande.
dgh
4
Oui, cela ne répond pas à la question du PO.
Allen Luce
toutes les actions marquées / non marquées sont exécutées lorsque vous ne spécifiez pas de balise. Les balises ne peuvent pas exclure une action à exécuter, seulement inclure. Il n'y a pas de logique de prédicat à l'exception d'un filtre additif.
bbaassssiiee
1

Il existe une balise spéciale - "jamais" , qui empêchera une tâche de s'exécuter à moins qu'une balise ne soit spécifiquement demandée.

tasks:
  - debug: msg='{{ showmevar}}'
    tags: [ 'never', 'debug' ]
xtoznaxto
la source
Déjà mentionné dans la réponse ci-dessus: serverfault.com/a/907329/105928
Taha Jahangir Le
0

Quand la clause ne peut pas évaluer la présence de balises. En guise de solution de contournement, j'utilise des variables et des balises ensemble pour exécuter des tâches spécifiques à cette balise / variable.

Ex: Imaginez un livre de jeu et un inventaire

# inventaire
[dev]
192.168.1.1

# site.yml
- hôtes: dev
  les rôles:
    - {rôle: commun}

et dans common / tasks / main.yml

# rôles / common / tasks / main.yaml
- nom: installer des liens
  apt: name = links state = present

- inclure: uninstall.yml
  when: uninstall_links est défini
  Mots clés:
    - désinstaller

# rôles / common / tasks / uninstall.yml
- nom: liens de désinstallation
  apt: name = links state = absent

Avec cette approche, vous utilisez la balise pour sélectionner uniquement les tâches dans uninstall.yml, mais vous devez également définir la variable 'uninstall_links' sur quelque chose pour l'activer. Ainsi, si vous exécutez le livre de lecture sans aucun paramètre, il exécutera par défaut la tâche d'installation. Pour désinstaller, vous pouvez définir la balise 'uninstall' sur votre playbook (ou cmdline) et DOIT définir la variable. Si vous ne définissez pas la balise, elle exécutera tout (installation et désinstallation) dans cet ordre, ce qui est utile pour tester l'ensemble du processus.

Comment tout exécuter (il va installer et désinstaller):

$ ansible-playbook -i inventory site.yml -l dev -s -k -e "uninstall_links=true"

Comment exécuter uniquement la balise 'uninstall' sur le groupe dev

$ ansible-playbook -i inventory site.yml -l dev -s -k -e "uninstall_links=true" -t uninstall

Par conséquent, les variables et les balises peuvent également figurer dans les fichiers site.yml / inventory, ce qui vous permet de valider dans votre SCM et d’enregistrer votre intention.

Anderson Goulart
la source
0

nootal a raison, mon approche ne fonctionne pas - ignorez-le :( J'utilise maintenant "lorsque: myvar est défini" et le commutateur de ligne de commande "-e" myvar = X "pour exécuter des tâches uniquement lorsque cela est explicitement demandé.

Encore plus facile (au moins avec ansible 2.1.1.0):

- name: do something only when tag 'foo' is provided
  when: tags is defined
  tags: foo

-> s'exécutera uniquement lorsque les balises auront été fournies ET que les balises incluent "foo"

DrPsychick
la source
0

Sur Ansible 2.3.2.0, voici ma solution au problème:

---
- hosts: localhost
  gather_facts: no
  vars:
    in_tag: yes
  tasks:
    - set_fact: in_tag=no
    - fail:
        msg: "recently_added is set and you're using blah tag"
      when: ( in_tag | bool )
      tags:
        - blah
    - debug:
        msg: "always remember"

Il commence par la mise in_tagà Truealors il y a un set_factqu'il met de nouveau à Falsequand vous ne spécifiez pas tagsde ansible-playbook.

Lorsque vous spécifiez des balises, in_tagreste à Trueet la failtâche est exécutée.

PS: vous pouvez ajouter la logique à toutes les tâches que vous voulez

PS2: vous pouvez également étendre la logique et coder en dur tous les tags que vous avez et set_fact: in_tag_blah=Trueen combinaison avec tags: ["blah"]bien sûr.

tehmoon
la source