Ansible zmień wartość domyślną zgodnie z warunkiem

16

Czy można zmienić domyślną wartość zmiennej roli zgodnie z pewnym warunkiem (tj. Wartością innej zmiennej)?

Detale

Mam dwie powiązane zmienne dla polecenia envi composer_opts.

Jeśli oba są pozostawione domyślnie ( env = "prod"i composer_opts = "--no-dev") wszystko jest w porządku.

Jeśli zmienię envna dev, ustawienie domyślne dla drugiego zepsuje moje polecenie, więc zawsze muszę ustawić oba. Czy można tego uniknąć, ustawiając domyślną wartość warunkową za pomocą skryptu niestandardowego / if?

Ważne: nie chcę zawsze ustawiać composer_optswartości zgodnie z envwartością. Chcę to ustawić tylko wtedy, gdy nie jest jeszcze ustawione (tj. Dynamiczna wartość domyślna).

Pseudo kod

Chciałbym zrobić coś takiego (poniższy kod jest nieprawidłowy, wystarczy pseudokod, aby wyrazić moją potrzebę)

---
# defaults/main.yml

env: prod
composer_opts: 
    when: "{{env}}" = 'prod'
        '--no-dev --optimize-autoloader --no-interaction'
    when: "{{env}}" = 'dev'
        '' 
Francesco Abeni
źródło

Odpowiedzi:

12

Proponuję to rozwiązanie:

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

Ustawi composer_optszmienną na string, ""gdy zmienna envjest równa „ dev”.

Oto przykład poradnika opartego na zaktualizowanym pytaniu:

$ 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

Przykładowe dane wyjściowe:

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   
Navern
źródło
1
To jest część rozwiązania. Zawsze będzie ustawiony composer_optsna pusty ciąg znaków, gdy envjest „dev”, zastępując wszelkie ustawione wartości rzeczywiste. Myślę, że warunkowy powinien zostać rozszerzony tak: when: "{{env}}" == 'dev' and "{{composer_opts}}" is undefined. Czy to dobrze wygląda? Czy potrafisz odpowiednio udoskonalić swoje pytanie?
Francesco Abeni
composer_opts zostaną zdefiniowane, ponieważ mają wartość domyślną. Potrzebujesz innego wyrażenia, aby rozwiązać swoje zadanie. Na przykład zmienna custom_composer_opts.
Navern,
Proszę wyjaśnić za pomocą pseudokodu, co chcesz zrobić. Odpowiednio zaktualizuję swoją odpowiedź.
Navern,
Zaktualizowałem moje pytanie o dodatkowe wyjaśnienia i przykład pseudokodu. Dziękuję Ci.
Francesco Abeni
Zaktualizowałem swoją odpowiedź. Sprawdź to. Wierzę, że zrozumiałem, czego potrzebujesz.
Navern,
4

Podczas gdy odpowiedź @ Navern działa, znalazłem osadzoną notację Jinja2 ( "{% if env == 'prod' %} ...), która jest bardzo podatna na notację, a zatem raczej delikatna. Na przykład podczas owijania danego wiersza dla lepszej czytelności, na przykład w tym nietestowanym kodzie :

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

Skończyło się na nieoczekiwanych wynikach, takich jak dodatkowe białe znaki lub \nin composer_opts.

Podejście, które stosuję jest znacznie głupsze, ale także bardziej stabilne:

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

Uznałem również, że ten post na blogu jest przydatny i zasadniczo opiera się na tym samym podejściu.

ssc
źródło
@sec, jeśli używasz |zamiast tego, >możesz nie mieć problemu z białymi znakami . (lub dostaniesz więcej LOL)
Michael
@sec Użyj „> -” i sprawdź specyfikację ansible. Ma wiele opcji poprawnego manipulowania ciągami wielowierszowymi. yaml-multiline.info Uwaga, w szczególności wskaźnik chompingowania bloku.
DylanYoung,
Pamiętaj, że w tym rozwiązaniu występowały również problemy z pierwszeństwem. Fakt nie jest domyślny.
DylanYoung,
2

Ansible set_fact na podstawie warunku w jednym wkładce:

- name: "set composer_opts based on environment"
  set_fact:
     composer_opts:  "{{ '--no-dev --optimize-autoloader --no-interaction' if (env == 'prod') else '' }}"
SK Venkat
źródło
Te same problemy z pierwszeństwem jak inne rozwiązania (fakt nie jest domyślny), jednak jeśli umieścisz ten warunek bezpośrednio w pliku defaults.yml, to rozwiązanie będzie działać. Robi się naprawdę brzydko bardzo szybko, jeśli masz wiele domyślnych ustawień zależnych od warunku
DylanYoung,