Modification possible de la valeur par défaut en fonction d'une condition


16

Est-il possible de changer la valeur par défaut d'une variable de rôle en fonction d'une condition (c'est-à-dire la valeur d'une autre variable)?

Détails

J'ai deux variables liées pour une commande, envet composer_opts.

Si les deux sont laissés par défaut ( env = "prod"et composer_opts = "--no-dev") tout va bien.

Si je passe envà dev, la valeur par défaut pour l'autre casse ma commande, j'ai donc toujours besoin de définir les deux. Serait-il possible d'éviter cela en définissant une valeur conditionnelle par défaut avec un script personnalisé / if?

Important: je ne veux pas toujours définir la composer_optsvaleur en fonction de la envvaleur. Je veux le définir uniquement s'il n'est pas déjà défini (c'est-à-dire une valeur dynamique par défaut).

Pseudocode

Je voudrais faire quelque chose comme ça (le code suivant n'est pas valide, juste un pseudocode pour exprimer mon besoin)

---
# defaults/main.yml

env: prod
composer_opts: 
    when: "{{env}}" = 'prod'
        '--no-dev --optimize-autoloader --no-interaction'
    when: "{{env}}" = 'dev'
        '' 

Réponses:


12

Je suggère cette solution:

---
 - set_fact:
     composer_opts: ""
   when: "{{env}}" == 'dev'

Il mettra composer_optsvariable à chaîne ""lorsque la variable envest égale à ' dev'.

Voici un exemple de playbook basé sur une question mise à jour:

$ cat test.yml

---
- hosts: 127.0.0.1
  connection: local
  tasks:
  - set_fact:
      composer_opts: "{% if env == 'prod' %} '--no-dev --optimize-autoloader --no-interaction' {% else %} '' {% endif %}"

  - debug: var=composer_opts

Exemple de sortie:

sudo ansible-playbook test.yml -e env=dev

PLAY [127.0.0.1] ************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [127.0.0.1]

TASK: [set_fact ] ************************************************************* 
ok: [127.0.0.1]

TASK: [debug var="{{composer_opts}}"] ***************************************** 
ok: [127.0.0.1] => {
    "var": {
        " '' ": " '' "
    }
}

PLAY RECAP ******************************************************************** 
127.0.0.1                  : ok=3    changed=0    unreachable=0    failed=0   


sudo ansible-playbook test.yml -e env=prod

PLAY [127.0.0.1] ************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [127.0.0.1]

TASK: [set_fact ] ************************************************************* 
ok: [127.0.0.1]

TASK: [debug var="{{composer_opts}}"] ***************************************** 
ok: [127.0.0.1] => {
    "var": {
        " '--no-dev --optimize-autoloader --no-interaction' ": " '--no-dev --optimize-autoloader --no-interaction' "
    }
}

PLAY RECAP ******************************************************************** 
127.0.0.1                  : ok=3    changed=0    unreachable=0    failed=0   

1
Cela fait partie de la solution. Il sera toujours défini composer_optssur une chaîne vide lorsque envest "dev", écrasant tout ensemble de valeurs réelles. Je pense que le conditionnel devrait être étendue comme ceci: when: "{{env}}" == 'dev' and "{{composer_opts}}" is undefined. Ça a l'air bien? Pouvez-vous mettre à jour votre question en conséquence?
Francesco Abeni

composer_opts sera défini car il a sa valeur par défaut. Vous avez besoin d'une autre expression pour résoudre votre tâche. Par exemple, variable custom_composer_opts.
Navern

Veuillez élaborer avec pseudocode ce que vous voulez faire. Je mettrai à jour ma réponse en conséquence.
Navern

J'ai mis à jour ma question avec des explications supplémentaires et un échantillon de pseudocode. Je vous remercie.
Francesco Abeni

J'ai mis à jour ma réponse. Vérifie ça. Je crois avoir compris ce dont vous avez besoin.
Navern

4

Bien que la réponse de @ Navern fonctionne, j'ai trouvé que la notation Jinja2 intégrée ( "{% if env == 'prod' %} ...) était extrêmement sensible à la notation et donc plutôt fragile. Par exemple, lors de l'habillage de la ligne en question pour une meilleure lisibilité, comme dans ce code non testé :

composer_opts: >
               "{% if env == 'prod' %}
                   '--no-dev --optimize-autoloader --no-interaction'
                {% else %}
                   ''
                {% endif %}"

Je me suis retrouvé avec des résultats inattendus, tels que des espaces supplémentaires ou \ndans composer_opts.

L'approche que j'utilise est beaucoup plus stupide, mais aussi plus stable:

- name: set composer_opts for dev env
  set_fact:
     composer_opts: ''
     when: "{{env}}" == 'dev'

- name: set composer_opts for prod env
  set_fact:
     composer_opts: '--no-dev --optimize-autoloader --no-interaction'
     when: "{{env}}" == 'prod'

J'ai également trouvé cet article de blog utile qui suit essentiellement la même approche.


@sec si vous utilisez à la |place de >vous pourriez ne pas avoir de problème d'espace. (ou vous en aurez plus LOL)
Michael

@sec Utilisez '> -' et consultez la spécification ansible. Il a de nombreuses options pour manipuler correctement les chaînes multilignes. yaml-multiline.info Notez, en particulier, l'indicateur de blocage de bloc.
DylanYoung

Notez que cette solution avait également des problèmes de priorité. Un fait n'est pas un défaut.
DylanYoung

2

Ansible set_fact basé sur la condition dans une doublure:

- name: "set composer_opts based on environment"
  set_fact:
     composer_opts:  "{{ '--no-dev --optimize-autoloader --no-interaction' if (env == 'prod') else '' }}"

Mêmes problèmes de priorité que les autres solutions (un fait n'est pas une valeur par défaut), cependant, si vous mettez ce droit conditionnel dans votre fichier defaults.yml, cette solution fonctionnera. Cela devient très laid très vite si vous avez un certain nombre de défauts dépendant de la condition
DylanYoung
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.