Ansible: ejecuta la tarea solo cuando se especifica una etiqueta

75

Las etiquetas de Ansible se pueden usar para ejecutar solo un subconjunto de tareas / roles. Esto significa que, de forma predeterminada, todas las tareas se ejecutan y solo podemos evitar que se ejecuten algunas tareas.

¿Podemos limitar la ejecución de una tarea solo cuando se especifica la etiqueta "foo"? ¿Podemos usar etiquetas actuales en la whensección de una tarea?

Taha Jahangir
fuente
2
parece que lo que necesita es una configuración de tarea como limit_to_tags: foo que no existe y no creo que sea posible en este momento. Una implementación futura también debe tener un plan para AND u OR esas etiquetas juntas.
dgh
Eche un vistazo a mi respuesta en "Ansible - Etiquetas predeterminadas / explícitas" stackoverflow.com/questions/28789912/…
sirkubax

Respuestas:

38

Ansible 2.5 viene con etiquetas especiales nevery always. La etiqueta neverse puede usar exactamente para este propósito. P.ej:

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

En este ejemplo, la tarea solo se ejecutará cuando se solicite explícitamente la etiqueta debug(o never). [Referencia sobre documentos ansibles]

Taha Jahangir
fuente
20

Aunque esta es una solución indirecta, funciona.

Dentro de la lista de tareas, registre una variable cuando se ejecute la ejecución normal. Luego, agregue una condición when que verifique esa variable a la tarea etiquetada.

- 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
fuente
También puede utilizar untaggedpara lograr esto:- set_fact: untagged_run=true tags: untagged
Pyzo
¿Puedes explicar un poco más sobre esto? ¿Un ejemplo del mundo real?
Quintin Par
17

No tengo suficiente reputación para votar o comentar sobre la respuesta que sugiere el uso de variables de línea de comandos ( --extra-vars), pero tengo que agregar esto:

La advertencia de este método es que la reproducción fallará y fallará si no define esa variable adicional.

Puede evitar el fracaso del juego en ausencia de una --extra-varsdefinición definiendo un valor predeterminado en el libro de jugadas en sí:

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

Anular vía --extra-varsseguirá funcionando porque las variables definidas en la línea de comando tienen prioridad sobre todas las demás definiciones.

El resultado es que la reproducción se ejecuta sin error cuando thoroughno se cambia a trueen la línea de comando.

Alex Peters
fuente
55
Lo mismo se puede lograr usando thorough | default('no') | bool.
Costi Ciudatu
2
O when: thorough is defined and thoroughsi prefiere esa sintaxis
KCD
Gracias, amo la is defined andsintaxis más. más que las múltiples tuberías que no siento son intuitivas.
Elijah Lynn
10

Puede usar condicionales para protegerse contra la ejecución accidental de tareas que de otro modo se ejecutarían si no especifica una etiqueta. La advertencia de este método es que la reproducción fallará y fallará si no define esa variable adicional.

Usando el argumento extra-vars, puede activar la ejecución de su condicional.

De ansible-playbook --help:

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

Ejemplo:

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
fuente
2
Para evitar un error si no define "exhaustivo" simplemente use thorough | default("false") | match("true"). El valor predeterminado no tiene que ser false, simplemente cualquier cosa que no coincida true, pero mejora la legibilidad.
Tom Wilson
4

Comprobar la variable 'etiquetas' no funciona en Ansible 2.1.1.0. Vea a continuación la prueba. Tengo otra idea para ejecutar la tarea solo cuando se define una etiqueta, que funciona tanto para Ansible 1.9.X como para 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

Con eso, cuando se ejecuta el libro de jugadas sin ninguna etiqueta, la variable 'foo' se establecerá en verdadero y luego en falso, por lo que no se ejecuta nada. Si agrega la etiqueta 'barra', solo se aplicará la primera configuración, por lo que la variable 'foo' será verdadera, entonces su tarea se ejecutará. ¡Disfrutar!


Y aquí está la prueba sobre la variable 'etiquetas' en Ansible 2.1.1.0:

Aquí está el libro de jugadas:

- 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

Y aquí está el resultado:

$ 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
fuente
2

Si. Ejecutar ansible-playbook con la --tags foobandera asegurará que solo foose ejecuten las tareas etiquetadas . Por ejemplo, supongamos que tenemos un libro de jugadas llamado example.yml:

tasks:

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

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

corriendo:

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

Se asegurará de que solo se ejecute la tarea yum.

Entonces, en realidad no es necesario usar etiquetas en la sección when para ejecutar condicionalmente una tarea. Tenga en cuenta que, según la complejidad de sus libros de jugadas / roles, es posible que necesite usar una combinación de --tags y --skip-tags para controlar qué tareas se ejecutan. Por ejemplo, si una tarea de inclusión se etiqueta como 'foo' y alguna tarea dentro del libro de jugadas incluido se etiqueta como 'barra' y ejecuta

ansible-playbook --tags "foo"

La tarea interna (etiquetada solo como 'barra') se ejecutará. Para evitar la ejecución de todas las tareas internas etiquetadas como 'barra', deberá ejecutar el siguiente comando

ansible-playbook --tags foo --skip-tags bar
Shahar
fuente
77
Esto no es cierto: "Especificar una etiqueta en una tarea significa que solo cuando esta etiqueta se pasa explícitamente al comando ansible-playbook esa tarea se ejecutará".
gimboland
1
Secundada, la declaración no es verdadera.
Chris
10
sí, puede lograr el comportamiento asegurándose de usar siempre las ansible-playbookopciones correctas , pero creo que el OP está pidiendo una forma de anotar una tarea para que no se ejecute a menos que se agregue explícitamente una etiqueta específica en el ansible-playbookcomando.
dgh
44
Sí, esto no responde a la pregunta del OP.
Allen Luce
todas las acciones etiquetadas / sin etiquetar se ejecutan cuando no especifica una etiqueta. Las etiquetas no pueden excluir una acción para ejecutar, solo incluir. No hay lógica de predicado excepto un filtro aditivo.
bbaassssiiee
1

Hay una etiqueta especial: "nunca" , que impedirá que se ejecute una tarea a menos que se solicite específicamente una etiqueta.

tasks:
  - debug: msg='{{ showmevar}}'
    tags: [ 'never', 'debug' ]
xtoznaxto
fuente
Ya mencionado en la respuesta anterior: serverfault.com/a/907329/105928
Taha Jahangir
0

cuando la cláusula no puede evaluar la presencia de etiquetas. Como solución alternativa, utilizo variables y etiquetas juntas para ejecutar tareas específicas de esa etiqueta / variable.

Ej: imagina un libro de jugadas e inventario

# inventario
[dev]
192.168.1.1

# site.yml
- hosts: dev
  roles:
    - {rol: común}

y en común / tareas / main.yml

# roles / common / tareas / main.yaml
- nombre: Instalar enlaces
  apt: nombre = estado de enlaces = presente

- incluye: uninstall.yml
  cuando: uninstall_links está definido
  etiquetas:
    - desinstalar

# roles / common / tareas / uninstall.yml
- nombre: desinstalar enlaces
  apt: nombre = estado de los enlaces = ausente

Con este enfoque, utiliza la etiqueta para seleccionar solo las tareas en uninstall.yml, pero también necesita establecer la variable 'uninstall_links' en algo para habilitarla. Entonces, si ejecuta el libro de jugadas sin ningún parámetro, de forma predeterminada, ejecutará la tarea de instalación. Para desinstalar, puede configurar la etiqueta 'desinstalar' en su libro de jugadas (o cmdline) y DEBE configurar la variable. Si no configura la etiqueta, ejecutará todo (instalar y desinstalar) en ese orden, lo cual es bueno para probar todo el proceso.

Cómo ejecutar todo (se instalará y desinstalará):

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

Cómo ejecutar solo la etiqueta 'desinstalar' en el grupo de desarrollo

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

Por lo tanto, las variables y las etiquetas también pueden estar en los archivos site.yml / Inventory, lo que le permite comprometerse en su SCM y registrar su intención.

Anderson Goulart
fuente
0

nootal es correcto, mi enfoque no funciona - ignórelo :( Ahora uso "cuando: myvar está definido" y el interruptor de línea de comando "-e" myvar = X "para ejecutar tareas solo cuando se solicita explícitamente.

Aún más fácil (al menos con ansible 2.1.1.0):

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

-> solo se ejecutará cuando se hayan proporcionado etiquetas Y las etiquetas incluyen "foo"

DrPsychick
fuente
0

Encendido Ansible 2.3.2.0, aquí está mi solución al problema:

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

Se inicia estableciendo in_taga Truecontinuación, hay una set_factque pone de nuevo a Falsecuando no se especifica ninguna tagsde ansible-playbook.

Cuando especifica etiquetas, in_tagpermanece en Truey se failejecuta la tarea.

PD: puedes agregar la lógica a cualquier tarea que desees

PS2: también puedes extender la lógica y codificar todas las etiquetas que tienes y set_fact: in_tag_blah=Trueen combinación con, tags: ["blah"]por supuesto.

tehmoon
fuente