Odpowiedź: warunkowo zdefiniuj zmienne w pliku vars, jeśli spełniony zostanie określony warunek

19

W zależności od wartości (True / False) zmiennej zdefiniowanej w group_vars Próbuję zdefiniować niektóre zmienne w pliku vars. Ich wartość zależy od wartości grupy var.

Mój aktualny plik var wygląda następująco:

{% if my_group_var %}
test:
   var1: value
   var2: value
   ...
   varn: value
{% else %}
test:
   var1: other_value
   var2: other_value
   ...
   varn: other_value
{% endif %}

Do każdej z moich ról używam zmiennej zdefiniowanej w tym pliku.

Mój testowy podręcznik wygląda następująco:

- name: blabla
  hosts: blabla
  vars_files:
     - <path>/test_vars.yml
  roles: blabla 

Błąd, który otrzymuję po uruchomieniu playbooka to:

{% if my_group_var %}
 ^ here

exception type: <class 'yaml.scanner.ScannerError'>
exception: while scanning for the next token
found character that cannot start any token
  in "<unicode string>"

Czy robię tu coś głupiego, czy to nawet nie jest obsługiwane? Próbowałem znaleźć inny sposób na zdefiniowanie tych zmiennych (mam ich wiele), ale nie udało mi się uzyskać tutaj czegoś funkcjonalnego. Jakieś sugestie?

pandoJohn
źródło
Gdzie ostatecznie używane są te zmienary? Może to być niepotrzebne, jeśli wszystko, czego będziesz ich używać, to część templatewywołania modułu.
84104
Jeśli testjest zależny od grupy, powinien zostać umieszczony w zmiennym group_vars.
Konstantin Suworow
Niestety test nie jest zależny od grupy. Jak wspomniano w opisie, test zależy od wartości zmiennej group_var.
pandoJohn

Odpowiedzi:

11

Nie sądzę, że możesz, zwykle tworzę osobne pliki do przechowywania kolekcji zmiennych warunkowych i używam whenklauzuli, aby uwzględnić je pod określonym warunkiem:

- include_vars: test_environment_vars.yml
  when: global_platform == "test"

- include_vars: staging_environment_vars.yml
  when: global_platform == "staging"

- include_vars: prod_environment_vars.yml
  when: 
    - global_platform != "test" 
    - global_platform != "staging" 
HBruijn
źródło
2
Tego chciałem uniknąć. Nie chcę używać dołączania zmiennych ani definiowania 2 dodatkowych plików var dla moich zadań.
pandoJohn
Nie rozumiem ... kiedy można użyć opcji include_vars z warunkiem, dlaczego zmiennej nie można zdefiniować z warunkiem?
GP92
10

Ansible pozwala warunkowo zdefiniować zmienną jedną z następujących form:

    test:
      var1: "{% if my_group_var %}value{% else %}other_value{% endif %}"
      var2: "{{'value' if (my_group_var) else 'other_value'}}"

Łącząc powyższą składnię z wyszukiwaniem zmiennych, możemy załadować złożone zmienne (w tym przypadku podaj listę):

test_value_when_my_group_var_is_true:
   var1: value
   var2: value

test_value_when_my_group_var_is_false:
   var1: other_value
   var2: other_value

test: "{{ lookup('vars','test_value_when_my_group_var_is_true') if (my_group_var) else lookup('vars','test_value_when_my_group_var_is_false')}}"

Istnieje inny sposób wykonywania warunkowego ładowania drzewa za pomocą funkcji vars. Jest to przydatne, gdy potrzebujesz zaimplementować logikę wielkości liter (tzn. Zmienna warunku ma więcej niż dwie możliwe wartości):

test_value_when_my_group_var_is_foo:
   var1: value
   var2: value

test_value_when_my_group_var_is_bar:
   var1: other_value
   var2: other_value

test_value_when_my_group_var_is_baz:
   var1: yet_another_value
   var2: yet_another_value

test: "{{ lookup('vars','test_value_when_my_group_var_is_' + my_group_var) }}"
Vladimir
źródło
2

Mimo, że byłoby miło, obawiam się, że twoja droga nie jest możliwa (lub nie jestem świadomy właściwej drogi).

Proponuję najpierw przygotować plik vars z szablonu jinja, a następnie dołączyć go do pliku include_vars. Zobacz przykładowy podręcznik:

---
- name: -Test-
  hosts: local
  vars:
    my_group_var: False
#    my_group_var: True

  tasks:

  - name: Prepare vars file from template.
    template: src=/tmp/vars.yaml.j2
              dest=/tmp/vars.yaml

  - name: Include vars
    include_vars: "/tmp/vars.yaml"

Zawartość przykładowego szablonu jinja /tmp/vars.yaml.j2 to:

{% if my_group_var %}                                                                                                                                                                                             
test:                                                                                                                                                                                                             
   var1: value                                                                                                                                                                                                    
   var2: value                                                                                                                                                                                                    
{% else %}                                                                                                                                                                                                        
test:                                                                                                                                                                                                             
   var1: other_value                                                                                                                                                                                              
   var2: other_value                                                                                                                                                                                              
{% endif %}
Jaroslav Kucera
źródło
Podoba mi się to, ale problem polega na tym, że po wygenerowaniu pliku .yml z szablonu jinja nie jest on dostępny dla kolejnych zadań z mojego playbooka.
pandoJohn
Dlaczego? Kiedy próbowałem rozszerzyć testowy podręcznik z zadaniem debugowania - debug: var=test, widzę, że istnieją zarówno wartości oczekiwane, jak test.var1i test.var2oczekiwane. Dlatego powinieneś być w stanie używać tych zmiennych w innych zadaniach podręcznika.
Jaroslav Kucera,
0

AFAIK, ta {} rzecz, której próbujesz, dotyczy szablonów Jinja2, a nie plików yml. Z dokumentacji :

ansible zezwala na zapętlanie i warunkowe Jinja2 w szablonach, ale w podręcznikach nie używamy ich.

Możesz przygotować osobny plik .yml ze sztuką, która konfiguruje zmienne, których potrzebujesz, używając klauzul when, a następnie importując je (lub włączając) do głównego podręcznika. W ten sposób możesz warunkowo zdefiniować wszystkie zmienne w jednym pliku.

LUB: Użyj ról. Myślę, że role są najbardziej odpowiednim podejściem do rozwiązania twojego problemu.

Niglesias
źródło
0

Ostatecznie zrobiłem 2 osobne pliki var - nazwijmy je type_a.ymli type_b.yml- i zdefiniowałem zmienną grupową, która wskazuje, którego pliku użyć - coś podobnego type_of_file: a. Tak teraz wygląda mój poradnik:

- name: blabla
  hosts: blabla
  vars_files:
     - <path>/type_{{ type_of_file }}.yml
  roles: blabla

Dziękuję za wszystkie odpowiedzi. Uważam je za bardzo pomocne.

pandoJohn
źródło
0

Mam nadzieję, że następujący fragment (wzięty z Ansible Documentation ) może być wartościowym dodatkiem do przydatnych wkładów innych osób powyżej.

- name: Show value of 'variablename'
  debug: msg="{{ lookup('vars', 'variabl' + myvar)}}"
  vars:
    variablename: hello
    myvar: ename
Peter Smallwood
źródło