Ansible: definir condicionalmente las variables en el archivo vars si se cumple una determinada condición

19

Dependiendo del valor (Verdadero / Falso) de una variable definida en group_vars, estoy tratando de definir algunas variables en un archivo vars. Su valor depende del valor del grupo var.

Mi archivo var actual se ve así:

{% if my_group_var %}
test:
   var1: value
   var2: value
   ...
   varn: value
{% else %}
test:
   var1: other_value
   var2: other_value
   ...
   varn: other_value
{% endif %}

Para cada uno de mis roles, estoy usando una variable definida en este archivo.

Mi libro de jugadas de prueba se ve a continuación:

- name: blabla
  hosts: blabla
  vars_files:
     - <path>/test_vars.yml
  roles: blabla 

El error que recibo después de ejecutar el libro de jugadas es:

{% if my_group_var %}
 ^ here

exception type: <class 'yaml.scanner.ScannerError'>
exception: while scanning for the next token
found character that cannot start any token
  in "<unicode string>"

¿Estoy haciendo algo estúpido aquí o esto ni siquiera es compatible? Traté de encontrar otra forma de definir estos vars (tengo muchos de ellos) pero no pude conseguir algo funcional aquí. ¿Alguna sugerencia?

pandoJohn
fuente
¿Dónde terminan siendo utilizados estos vars? Esto podría ser innecesario si todo lo que va a utilizar es parte de una templatellamada de módulo.
84104
Si testdepende del grupo, debe colocarse en group_vars.
Konstantin Suvorov
Desafortunadamente, la prueba no depende del grupo. Como se menciona en la descripción, la prueba depende del valor de una variable group_var.
pandoJohn

Respuestas:

11

No creo que pueda, generalmente creo archivos separados para contener colecciones de variables condicionales y uso una whencláusula para incluirlos en una condición específica:

- include_vars: test_environment_vars.yml
  when: global_platform == "test"

- include_vars: staging_environment_vars.yml
  when: global_platform == "staging"

- include_vars: prod_environment_vars.yml
  when: 
    - global_platform != "test" 
    - global_platform != "staging" 
HBruijn
fuente
2
Esto es algo que estaba tratando de evitar. No quiero usar include vars ni definir 2 archivos var adicionales para mis tareas.
pandoJohn
No lo entiendo ... cuando es posible usar include_vars con condición, ¿por qué no se puede definir variable con condición?
GP92
10

Ansible permite que una de las siguientes formas defina variables condicionalmente:

    test:
      var1: "{% if my_group_var %}value{% else %}other_value{% endif %}"
      var2: "{{'value' if (my_group_var) else 'other_value'}}"

Combinando la sintaxis anterior con la búsqueda de variables, podemos cargar variables complejas (lista en este caso):

test_value_when_my_group_var_is_true:
   var1: value
   var2: value

test_value_when_my_group_var_is_false:
   var1: other_value
   var2: other_value

test: "{{ lookup('vars','test_value_when_my_group_var_is_true') if (my_group_var) else lookup('vars','test_value_when_my_group_var_is_false')}}"

Hay otra forma de realizar la carga de árbol condicional con la búsqueda de vars. Esta manera es útil cuando necesita implementar la lógica de caso (es decir, la variable de condición tiene más de dos valores posibles):

test_value_when_my_group_var_is_foo:
   var1: value
   var2: value

test_value_when_my_group_var_is_bar:
   var1: other_value
   var2: other_value

test_value_when_my_group_var_is_baz:
   var1: yet_another_value
   var2: yet_another_value

test: "{{ lookup('vars','test_value_when_my_group_var_is_' + my_group_var) }}"
Vladimir
fuente
2

A pesar de que sería bueno, me temo que tu camino no es posible (o no estoy al tanto).

Sugeriría preparar primero el archivo vars de la plantilla jinja y luego incluirlo con include_vars. Vea el ejemplo de libro de jugadas:

---
- name: -Test-
  hosts: local
  vars:
    my_group_var: False
#    my_group_var: True

  tasks:

  - name: Prepare vars file from template.
    template: src=/tmp/vars.yaml.j2
              dest=/tmp/vars.yaml

  - name: Include vars
    include_vars: "/tmp/vars.yaml"

El contenido de la plantilla de ejemplo jinja /tmp/vars.yaml.j2 es:

{% if my_group_var %}                                                                                                                                                                                             
test:                                                                                                                                                                                                             
   var1: value                                                                                                                                                                                                    
   var2: value                                                                                                                                                                                                    
{% else %}                                                                                                                                                                                                        
test:                                                                                                                                                                                                             
   var1: other_value                                                                                                                                                                                              
   var2: other_value                                                                                                                                                                                              
{% endif %}
Jaroslav Kucera
fuente
Me gusta, pero el problema es que después de generar el archivo .yml a partir de la plantilla jinja, esto no está disponible para las tareas posteriores de mi libro de jugadas.
pandoJohn
¿Por qué? Cuando traté de extender el libro de jugadas de prueba con la tarea de depuración - debug: var=test, puedo ver que están definidos ambos test.var1y test.var2con los valores esperados. Por lo tanto, debería poder usar estas variables en otras tareas del libro de jugadas.
Jaroslav Kucera
0

AFAIK, esta {} cosa que estás intentando es para las plantillas Jinja2 y no para archivos yml. De la documentación :

ansible permite bucles y condicionales Jinja2 en las plantillas, pero en los libros de jugadas, no los usamos.

Puede preparar un archivo .yml separado con una reproducción que configura las variables que necesita utilizando las cláusulas when, y luego importarlas (o incluirlas) en su libro de jugadas principal. De esa manera, puede tener todos los vars definidos condicionalmente en un solo archivo.

O: use roles. Creo que los roles son el enfoque más adecuado para resolver su problema.

niglesias
fuente
0

Lo que hice al final fue crear 2 archivos var separados, llamémoslos type_a.ymly type_b.yml, y definí una variable de grupo que indica qué archivo usar, algo así type_of_file: a. Así es como se ve mi libro de jugadas ahora:

- name: blabla
  hosts: blabla
  vars_files:
     - <path>/type_{{ type_of_file }}.yml
  roles: blabla

Gracias por todas las respuestas. Los encuentro realmente útiles.

pandoJohn
fuente
0

Espero que el siguiente fragmento (tomado de la Documentación Ansible ) pueda ser una valiosa adición a las útiles contribuciones de los anteriores.

- name: Show value of 'variablename'
  debug: msg="{{ lookup('vars', 'variabl' + myvar)}}"
  vars:
    variablename: hello
    myvar: ename
Peter Smallwood
fuente