Ansible - Utiliser la valeur par défaut si une variable n'est pas définie

98

Je personnalise la userscréation Linux dans mon rôle. Je dois permettre aux utilisateurs de mon rôle customize home_directory, group_name, name, password.

Je me demandais s'il existe un moyen plus flexible de gérer les valeurs par défaut.

Je sais que le code ci-dessous est possible:

- name: Create default
  user:
    name: "default_name"
  when: my_variable is not defined

 - name: Create custom
  user:
    name: "{{my_variable}}"
  when: my_variable is defined

Mais comme je l'ai mentionné, il y a beaucoup de variables optionnelles et cela crée beaucoup de possibilités.

Y a-t-il quelque chose comme le code ci-dessus?

user:
  name: "default_name", "{{my_variable}}"

Le code doit être défini name="default_name"lorsqu'il my_variablen'est pas défini.

Je pourrais définir toutes les variables defaults/main.ymlet créer l'utilisateur comme ça:

- name: Create user
  user:
    name: "{{my_variable}}"

Mais ces variables sont à l'intérieur d'un très gros hachage et il y a des hachages à l'intérieur de ce hachage qui ne peuvent pas être une valeur par défaut.

Bernardo Vale
la source
en relation: stackoverflow.com/questions/19614027/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Réponses:

190

Vous pouvez utiliser ceux de Jinja default:

- name: Create user
  user:
    name: "{{ my_variable | default('default_value') }}"
faneuse42
la source
10
Et si la variable par défaut dépend d'une autre variable. Par exemple default('/home/' {{ anothervar }}), existe-t-il un moyen de concaténer ces valeurs?
Bernardo Vale
8
Supprimez simplement le 'autour du default_valueet il utiliserait une variable appelée default_value
dagonza
7
Ne fonctionne pas si la variable est imbriquée comme {{ dict.key | default(5) }}. Il échouera s'il dictn'est pas défini.
Jordan Stewart
1
Pour info, cela va maintenant générer une erreur:[WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or {% %}.
bryan kennedy
1
@JordanStewart J'ai eu le même cas - avec des variables imbriquées. J'ai posté une réponse avec des solutions possibles ci-dessous.
Roman Kruglov
11

Pas totalement lié, mais vous pouvez également vérifier les deux variables undefinedAND empty(par exemple my_variable:). (REMARQUE: fonctionne uniquement avec la version ansible> 1.9, voir: lien )

- name: Create user
  user:
    name: "{{ ((my_variable == None) | ternary('default_value', my_variable)) \
    if my_variable is defined else 'default_value' }}"
Tommy Nguyen
la source
2
C'est génial, très utile.
eagle33322
5

Si quelqu'un recherche une option qui gère les variables imbriquées, il existe plusieurs de ces options dans ce problème github .

En bref, vous devez utiliser le filtre "par défaut" pour chaque niveau de variables imbriquées. Pour une variable "a.nested.var", cela ressemblerait à:

- hosts: 'localhost'
  tasks:
    - debug:
        msg: "{{ ((a | default({})).nested | default({}) ).var | default('bar') }}"

ou vous pouvez définir les valeurs par défaut des dictionnaires vides pour chaque niveau de variables, peut-être en utilisant le filtre "Combiner". Ou utilisez le filtre "json_query". Mais l'option que j'ai choisie me semble plus simple si vous n'avez qu'un seul niveau d'imbrication.

Roman Kruglov
la source
4

Si vous avez une seule lecture que vous souhaitez boucler sur les éléments, définissez cette liste dans group_vars / all ou ailleurs qui a du sens:

all_items:
  - first
  - second
  - third
  - fourth

Ensuite, votre tâche peut ressembler à ceci:

  - name: List items or default list
    debug:
      var: item
    with_items: "{{ varlist | default(all_items) }}"

Passez varlist en tant que tableau JSON:

ansible-playbook <playbook_name> --extra-vars='{"varlist": [first,third]}'

Avant cela, vous souhaiterez peut-être également une tâche qui vérifie que chaque élément de varlist est également dans all_items :

  - name: Ensure passed variables are in all_items
    fail:
      msg: "{{ item }} not  in all_items list"
    when: item not in all_items
    with_items: "{{ varlist | default(all_items) }}"
Jack
la source
3

Si vous utilisez la recherche pour définir la lecture par défaut à partir de l'environnement, vous avez également défini le deuxième paramètre par défaut sur true:

- set_facts:
    ansible_ssh_user: "{{ lookup('env', 'SSH_USER') | default('foo', true) }}"

Vous pouvez également concaténer plusieurs définitions par défaut:

- set_facts:
    ansible_ssh_user: "{{ some_var.split('-')[1] | default(lookup('env','USER'), true) | default('foo') }}"
panticz
la source
1

La question est assez ancienne, mais qu'en est-il:

- hosts: 'localhost'
  tasks:
    - debug:
        msg: "{{ ( a | default({})).get('nested', {}).get('var','bar') }}"

Cela me semble moins encombrant ...

chasseur
la source
1

Si vous attribuez une valeur par défaut à un fait booléen, assurez-vous qu'aucun guillemet n'est utilisé dans default ().

- name: create bool default
  set_fact:
    name: "{{ my_bool | default(true) }}"

Pour les autres variables, la même méthode est utilisée dans la réponse vérifiée.

- name: Create user
  user:
    name: "{{ my_variable | default('default_value') }}"
Samselvaprabu
la source