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

В зависимости от значения (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>"

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

8 ответов

Решение

В итоге я создал 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

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

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

Я не думаю, что вы можете, я обычно создаю отдельные файлы для хранения коллекций условных переменных и использую 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" 

Почему об этом никто не упоминает?

      _dist: "{{ ansible_lsb.id|lower if ansible_lsb.id == 'Raspbian' else ansible_distribution|lower }}"

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

Я бы предложил сначала подготовить файл 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 %}

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

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

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

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

Код Jinja2 ожидается в файлах.j2 для шаблонов и встроенных playbooks, где применяются некоторые правила. Вот почему вы получаете эти синтаксические ошибки.

В Ansible есть множество способов решения одних и тех же задач.

Если вы хотите определить переменные для каждой роли, один из подходов заключается в использовании отдельного файла var для каждой роли:

roles/
    some_role/            # this hierarchy represents a "role"
        vars/             #
            main.yml      #  <-- variables associated with this role
        defaults/         #
            main.yml      #  <-- default lower priority variables for this role

Вышеупомянутый метод не требует условных выражений (предложение "когда").

Если вы действительно хотите иметь один-единственный файл со всеми определениями переменных, вы получите файл шаблона для генерации окончательного файла var, а затем включите / импортируйте его в свою книгу.

Я настоятельно рекомендую понять концепции повторного использования кода и динамического и статического контента.

Кроме того, если нет конфликтов пространств имен или не слишком много переменных, следует рассмотреть один единственный статический глобальный файл var для каждой книги воспроизведения или набора книг воспроизведения.

Что касается документации Ansible по использованию переменных (приоритет переменных: где я должен поместить переменную?):

Многие могут спросить, как переменные перекрывают другие. В конечном счете, философия Ansible состоит в том, что вам лучше знать, куда поместить переменную, и тогда вам нужно гораздо меньше думать об этом.

Избегайте определения переменной "x" в 47 местах и ​​затем задавайте вопрос "какой x используется". Почему? Потому что это не дзен-философия Ansible.

Есть только один Эмпайр-стейт-билдинг. Одна Мона Лиза и т. Д. Выясните, где определить переменную, и не усложняйте это.

Там отличный упорядоченный список переменных старшинства здесь.

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

- name: Show value of 'variablename'
  debug: msg="{{ lookup('vars', 'variabl' + myvar)}}"
  vars:
    variablename: hello
    myvar: ename
Другие вопросы по тегам