web-dev-qa-db-fra.com

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

balises Ansible peut être utilisé 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 nous ne pouvons empêcher que certaines tâches de s'exécuter.

Pouvons-nous limiter une tâche à exécuter uniquement lorsque la balise "foo" est spécifiée? Pouvons-nous utiliser les balises actuelles dans la section when d'une tâche?

79
Taha Jahangir

Ansible 2.5 est fourni avec des balises spéciales never et always. La balise never peut être utilisée exactement à cette fin. Par exemple:

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

Dans cet exemple, la tâche ne s'exécutera que lorsque la balise debug (ou never) est explicitement demandée. [Référence sur les documents ansible]

46
Taha Jahangir

Bien qu'il s'agisse d'une solution détournée, cela fonctionne.

Dans la liste des tâches, enregistrez une variable lors de l'exécution normale. Ensuite, ajoutez 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
20
Chris Chipman

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

La mise en garde à cette méthode est que le jeu va échouer et échouer si vous ne définissez pas cette variable supplémentaire.

Vous pouvez éviter l'échec de la lecture en l'absence d'un --extra-vars dé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

Remplacement via --extra-vars fonctionnera 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 s'exécute sans erreur lorsque thorough n'est pas remplacé par true sur la ligne de commande.

17
Alex Peters

Vous pouvez utiliser Conditions pour vous protéger contre l'exécution de tâches accidentelles qui seraient sinon exécutées si vous ne spécifiez pas de balise. La mise en garde à cette méthode est que le jeu va échouer et échouer 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)
...
10
Ava

La vérification de 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 lorsqu'une balise est définie, fonctionnant à la fois pour Ansible 1.9.X et 2.X.Y:

- 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 playbook sans aucune balise, la variable 'foo' sera définie sur true puis sur false, donc rien n'est exécuté. Si vous ajoutez la balise 'bar', seul le premier paramètre sera appliqué, donc la variable 'foo' sera vraie, alors 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   
4
nootal

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

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

Oui. Exécuter ansible-playbook avec le --tags foo flag garantira que seules les tâches marquées avec foo seront exécutées. Par exemple, supposons que nous ayons un playbook 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 la section when pour exécuter une tâche de manière conditionnelle. Notez qu'en fonction de la complexité de vos playbooks/rôles, vous devrez peut-être utiliser une combinaison de --tags et --skip-tags pour contrôler les tâches à exécuter. Par exemple, si une tâche d'inclusion est étiquetée comme 'foo' et qu'une tâche à l'intérieur du playbook inclus est étiquetée comme 'bar' et que vous exécutez

ansible-playbook --tags "foo"

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

ansible-playbook --tags foo --skip-tags bar
2
Shahar
tasks:
  - debug: msg='{{ showmevar}}'
    tags: [ 'never', 'debug' ]

C'est la bonne réponse, mais ce qui déroute souvent les gens, c'est comment obtenir Ansible pour ajouter cette balise, car si vous mettez --tags debug sur la ligne de commande puis la seule chose qui s'exécute est les tâches de débogage. La solution est --tags all,debug par exemple.

ansible-playbook play.yaml --tags all,debug

Le documents Ansible sur les balises a cette ligne:

Par défaut, Ansible s'exécute comme si --tags all avait été spécifié.

0
Wookie

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 définir in_tag à True puis il y a set_fact qui le redéfinit sur False lorsque vous ne spécifiez pas tags de ansible-playbook.

Lorsque vous spécifiez des balises, in_tag reste à True et la tâche fail s'exécute.

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

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

0
tehmoon

when clause ne peut pas évaluer la présence de balises. Pour contourner ce problème, 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 
 rôles: 
 - {rôle: commun} 
 
 et dans commun/tâches/main.yml 
 
 # rôles/commun/tâches/main.yaml 
 - nom: installer les liens 
 apt: nom = liens état = présent 
 
 - inclure: uninstall.yml 
 quand: uninstall_links est défini 
 balises: 
 - désinstaller 
 
 # rôles/communs/tâches/uninstall.yml 
 - nom: désinstaller les liens 
 apt: nom = état des liens = 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. Donc, si vous exécutez le playbook sans aucun paramètre, il exécutera par défaut la tâche d'installation. Pour désinstaller, vous pouvez définir le tag "désinstaller" sur votre playbook (ou cmdline) et [~ # ~] doit [~ # ~] définir le variable. Si vous ne définissez pas la balise, elle exécutera tout (installation et désinstallation) dans cet ordre, ce qui est bon 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 de développeurs

$ 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 se trouver dans les fichiers site.yml/inventaire, vous permettant de vous engager dans votre SCM et d'enregistrer votre intention.

0
Anderson Goulart

Une manière peut-être plus idiomatique et élégante consiste à ajouter une condition when à la tâche, comme celle-ci:

tasks:
  - debug: msg='{{ showmevar}}'
    tags: [ 'debug' ]
    when: "'debug' in ansible_run_tags"

Cela utilise la variable magique ansible_run_tags qui contient la liste des balises fournies via l'argument CLI --tags (ou synonyme -t) et a pour effet d'exécuter la tâche ci-dessus si et seulement si la balise debug est donnée.

Il semble que cette variable magique ait été introduite dans ansible 2.5

0

nootal a raison, mon approche ne fonctionne pas - ignorez-le :( J'utilise maintenant "quand: myvar est défini" et le commutateur de ligne de commande "-e" myvar = X "pour exécuter des tâches uniquement quand 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

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

0
DrPsychick