В зависимости от значения (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.
Есть только один Эмпайр-стейт-билдинг. Одна Мона Лиза и т. Д. Выясните, где определить переменную, и не усложняйте ее.
Есть отличный упорядоченный список приоритетов переменных Вот.