Ansible: условно определить переменные в файле vars, если выполняется определенное условие

19

В зависимости от значения (True / False) переменной, определенной в group_vars, я пытаюсь определить некоторые переменные в файле vars. Их значение зависит от значения группы var.

Мой текущий файл var выглядит так:

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

Для каждой из моих ролей я использую переменную, определенную в этом файле.

Моя тестовая книга выглядит следующим образом:

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

Ошибка, которую я получаю после запуска playbook:

{% 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>"

Я делаю что-то глупое здесь или это даже не поддерживается? Я пытался найти другой способ определения этих переменных (у меня их много), но мне не удалось получить что-то функциональное здесь. Какие-либо предложения?

pandoJohn
источник
Где эти переменные в конечном итоге используются? Это может быть ненужным, если все, для чего вы собираетесь их использовать, является частью templateвызова модуля.
84104
Если testэто зависит от группы, он должен быть помещен в group_vars.
Константин Суворов
К сожалению, тест не зависит от группы. Как упомянуто в описании, проверка зависит от значения переменной group_var.
pandoJohn

Ответы:

11

Я не думаю, что вы можете, я обычно создаю отдельные файлы для хранения коллекций условных переменных и использую whenпредложение, чтобы включить их в определенное условие:

- 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
источник
2
Это то, чего я пытался избежать. Я не хочу использовать include vars или определить 2 дополнительных файла var для моих задач.
pandoJohn
Я не понимаю .. когда можно использовать include_vars с условием, почему переменная не может быть определена с условием?
GP92
10

Ansible позволяет одной из следующих форм определять переменную условно:

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

Комбинируя приведенный выше синтаксис с поиском vars, мы можем загружать сложные vars (список в этом случае):

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')}}"

Есть другой способ сделать условную загрузку дерева с помощью поиска vars. Этот способ удобен, когда вам нужно реализовать логику регистра (то есть переменная условия имеет более двух возможных значений):

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) }}"
Владимир
источник
2

Несмотря на то, что это было бы хорошо, я боюсь, что ваш путь невозможен (или я не знаю правильный путь).

Я бы предложил сначала подготовить файл vars из шаблона jinja, а затем включить его с помощью include_vars. Смотрите пример playbook:

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

Содержимое примера шаблона jinja /tmp/vars.yaml.j2:

{% if my_group_var %}                                                                                                                                                                                             
test:                                                                                                                                                                                                             
   var1: value                                                                                                                                                                                                    
   var2: value                                                                                                                                                                                                    
{% else %}                                                                                                                                                                                                        
test:                                                                                                                                                                                                             
   var1: other_value                                                                                                                                                                                              
   var2: other_value                                                                                                                                                                                              
{% endif %}
Ярослав Кучера
источник
Мне это нравится, но проблема в том, что после создания файла .yml из шаблона jinja он недоступен для последующих задач из моей книги воспроизведения.
pandoJohn
Почему? Когда я попытался расширить тестовую пьесу с помощью задачи отладки, - debug: var=testя увидел, что там определены test.var1и test.var2ожидаемые значения. Таким образом, вы должны быть в состоянии использовать эти переменные в других задачах сборника.
Ярослав Кучера
0

AFAIK, это {}, что вы пытаетесь для шаблонов Jinja2, а не для файлов YML. Из документации :

ansible допускает циклы Jinja2 и условные выражения в шаблонах, но в книгах воспроизведения мы их не используем.

Вы можете подготовить отдельный файл .yml для игры, в которой задаются переменные, которые вам нужны при использовании предложений when, и затем импортировать (или включать) их в основную книгу. Таким образом, вы можете условно определить все переменные в одном файле.

ИЛИ: используйте роли. Я думаю, что роли являются наиболее адекватным подходом для решения вашей проблемы.

niglesias
источник
0

В итоге я создал 2 отдельных файла var - давайте назовем их type_a.ymlи type_b.yml- и я определил переменную группы, которая указывает, какой файл использовать - что-то вроде type_of_file: a. Вот так выглядит моя книга игр:

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

Спасибо за ответы на все вопросы. Я считаю их действительно полезными.

pandoJohn
источник
0

Я надеюсь, что следующий фрагмент (взятый из Ansible Documentation ) может стать полезным дополнением к полезным вкладам других выше.

- name: Show value of 'variablename'
  debug: msg="{{ lookup('vars', 'variabl' + myvar)}}"
  vars:
    variablename: hello
    myvar: ename
Питер Смоллвуд
источник