È 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.