È possibile modificare il valore predefinito in base a una condizione


16

È possibile modificare il valore predefinito di una variabile di ruolo in base a una condizione (ovvero il valore di un'altra variabile)?

Dettagli

Ho due variabili correlate per un comando enve composer_opts.

Se entrambi sono lasciati al default ( env = "prod"e composer_opts = "--no-dev") tutto è ok.

Se cambio enva dev, l'impostazione predefinita per l'altra interromperà il mio comando, quindi devo sempre impostare entrambe. Sarebbe possibile evitarlo impostando un valore predefinito condizionale con uno script personalizzato / if?

Importante: non voglio impostare sempre il composer_optsvalore in base al envvalore. Voglio impostarlo solo se non è già impostato (ovvero un valore predefinito dinamico).

pseudocodice

Vorrei fare qualcosa del genere (il seguente codice non è valido, solo pseudocodice per esprimere il mio bisogno)

---
# defaults/main.yml

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

Risposte:


12

Suggerisco questa soluzione:

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

Imposterà la composer_optsvariabile su stringa ""quando la variabile envè uguale a ' dev'.

Ecco un esempio di playbook basato sulla domanda aggiornata:

$ 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

Uscita campione:

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
Questa è una parte della soluzione. Verrà sempre impostato composer_optssu stringa vuota quando envè "dev", sovrascrivendo qualsiasi set di valori effettivi. Credo che il condizionale dovrebbe essere estesa in questo modo: when: "{{env}}" == 'dev' and "{{composer_opts}}" is undefined. Sembra buono? Puoi rispondere alla tua domanda di conseguenza?
Francesco Abeni,

composer_opts sarà definito perché ha il suo valore predefinito. Hai bisogno di un'altra espressione per risolvere il tuo compito. Ad esempio variabile custom_composer_opts.
Navern

Si prega di elaborare con pseudocodice cosa si desidera fare. Aggiornerò la mia risposta di conseguenza.
Navern,

Ho aggiornato la mia domanda con spiegazioni aggiuntive e esempio di pseudocodice. Grazie.
Francesco Abeni,

Ho aggiornato la mia risposta. Controllalo. Credo di aver capito di cosa hai bisogno.
Navern,

4

Mentre la risposta di @ Navern funziona, ho trovato la notazione Jinja2 ( "{% if env == 'prod' %} ...) incorporata estremamente sensibile alla notazione e quindi piuttosto fragile. Ad esempio, quando si avvolge la riga in questione per una migliore leggibilità come in questo codice non testato :

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

Ho finito con risultati inaspettati, come spazi bianchi aggiuntivi o \nin composer_opts.

L'approccio che uso è molto più stupido, ma anche più stabile:

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

Ho anche trovato utile questo post sul blog che segue essenzialmente lo stesso approccio.


@sec se usi al |posto >tuo potresti non avere il problema degli spazi bianchi. (o ne otterrai di più LOL)
Michael,

@sec Usa '> -' e controlla le specifiche rispondibili. Ha molte opzioni per manipolare correttamente le stringhe multilinea. yaml-multiline.info Notare, in particolare, l'indicatore di blocco dei blocchi.
DylanYoung,

Si noti che questa soluzione presentava anche problemi di precedenza. Un fatto non è un valore predefinito.
DylanYoung,

2

Ansible set_fact basato sulla condizione in un liner:

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

Stessi problemi di precedenza delle altre soluzioni (un dato di fatto non è un valore predefinito), tuttavia, se si inserisce questo diritto nel file defaults.yml, questa soluzione funzionerà. Diventa davvero brutto molto velocemente se hai un numero di impostazioni predefinite dipendenti dalla condizione
DylanYoung
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.