Ansible: définir conditionnellement des variables dans le fichier vars si une certaine condition est remplie

19

En fonction de la valeur (True / False) d'une variable définie dans le group_vars, j'essaie de définir certaines variables dans un fichier vars. Leur valeur dépend de la valeur du groupe var.

Mon fichier var actuel ressemble à ceci:

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

Pour chacun de mes rôles, j'utilise une variable définie dans ce fichier.

Mon playbook de test ressemble à ci-dessous:

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

L'erreur que je reçois après avoir exécuté le playbook est:

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

Suis-je en train de faire quelque chose de stupide ici ou ce n'est même pas supporté? J'ai essayé de trouver une autre façon de définir ces vars (j'en ai beaucoup) mais je n'ai pas réussi à obtenir quelque chose de fonctionnel ici. Aucune suggestion?

pandoJohn
la source
Où ces vars finissent-ils par être utilisés? Cela peut être inutile si vous ne les utilisez que dans le cadre d'un templateappel de module.
84104
Si testdépend du groupe, il doit être placé dans group_vars.
Konstantin Suvorov
Malheureusement, le test ne dépend pas du groupe. Comme mentionné dans la description, le test dépend de la valeur d'une variable group_var.
pandoJohn

Réponses:

11

Je ne pense pas que vous puissiez, je crée généralement des fichiers séparés pour contenir les collections de variables conditionnelles et j'utilise une whenclause pour les inclure à une condition spécifique:

- 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
la source
2
C'est quelque chose que j'essayais d'éviter. Je ne veux pas utiliser d'include vars ou définir 2 fichiers var supplémentaires pour mes tâches.
pandoJohn
Je ne comprends pas ... quand il est possible d'utiliser include_vars avec condition, pourquoi ne pas définir une variable avec condition?
GP92
10

Ansible permet à l'une des formes suivantes de définir une variable de manière conditionnelle:

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

En combinant la syntaxe ci-dessus avec la recherche de variables, nous pouvons charger des variables complexes (liste dans ce cas):

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')}}"

Il existe une autre façon d'effectuer un chargement d'arbre conditionnel avec la recherche vars. Cette méthode est pratique lorsque vous avez besoin d'implémenter une logique de cas (c'est-à-dire que la variable de condition a plus de deux valeurs possibles):

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
la source
2

Malgré ce serait bien, je crains que votre chemin ne soit pas possible (ou je ne suis pas au courant de la bonne façon).

Je suggère de préparer d'abord le fichier vars à partir du modèle jinja, puis de l'inclure avec include_vars. Voir l'exemple de playbook:

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

Le contenu de l'exemple de modèle jinja /tmp/vars.yaml.j2 est:

{% if my_group_var %}                                                                                                                                                                                             
test:                                                                                                                                                                                                             
   var1: value                                                                                                                                                                                                    
   var2: value                                                                                                                                                                                                    
{% else %}                                                                                                                                                                                                        
test:                                                                                                                                                                                                             
   var1: other_value                                                                                                                                                                                              
   var2: other_value                                                                                                                                                                                              
{% endif %}
Jaroslav Kucera
la source
J'aime cela, mais le problème est qu'après avoir généré le fichier .yml à partir du modèle jinja, ce n'est pas disponible pour les tâches suivantes de mon playbook.
pandoJohn
Pourquoi? Lorsque j'ai essayé d'étendre le playbook de test avec une tâche de débogage, - debug: var=testje peux voir qu'il y a des définitions test.var1et des test.var2valeurs attendues. Vous devriez donc pouvoir utiliser ces variables dans d'autres tâches du playbook.
Jaroslav Kucera
0

AFAIK, cette {} chose que vous essayez est pour les modèles Jinja2 et non pour les fichiers yml. De la documentation :

ansible autorise les boucles et les conditions Jinja2 dans les modèles, mais dans les playbooks, nous ne les utilisons pas.

Vous pouvez préparer un fichier .yml séparé avec un jeu qui définit les variables dont vous avez besoin en utilisant des clauses when, puis en les important (ou en les incluant) dans votre livre de jeu principal. De cette façon, vous pouvez avoir toutes les variables définies conditionnellement dans un seul fichier.

OU: Utilisez des rôles. Je pense que les rôles sont l'approche la plus adéquate pour résoudre votre problème.

Niglesias
la source
0

Ce que j'ai fait à la fin était de créer 2 fichiers var distincts - appelons-les type_a.ymlet type_b.yml- et j'ai défini une variable de groupe qui indique quel fichier utiliser - quelque chose comme type_of_file: a. Voici à quoi ressemble mon playbook maintenant:

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

Merci pour toutes les réponses. Je les trouve vraiment utiles.

pandoJohn
la source
0

J'espère que le snip suivant (tiré de la documentation Ansible ) pourra apporter un complément utile aux contributions utiles des autres ci-dessus.

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