Назад | Перейти на главную страницу

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

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

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" 

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

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

---
- 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 в шаблонах, но в playbooks мы их не используем.

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

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

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

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

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

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

- name: Show value of 'variablename'
  debug: msg="{{ lookup('vars', 'variabl' + myvar)}}"
  vars:
    variablename: hello
    myvar: ename

Код 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 для каждой playbook или набора playbooks.

Согласно документации Ansible на Использование переменных (Приоритет переменной: где мне поместить переменную?):

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

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

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

Есть отличный упорядоченный список приоритетов переменных Вот.