$ ansible --version
ansible 2.3.0 (devel a8910e78ca) last updated 2017/03/08 02:46:53 (GMT -500)
config file =
configured module search path = Default w/o overrides
python version = 2.7.10 (default, Jul 30 2016, 19:40:32) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)]
Сток ansible.cfg
Хост управления macOS 10.12.3
Задача, которую я использую более 7 месяцев, начала выдавать предупреждение.
- name: install powershell
win_chocolatey:
name: '{{ item }}'
state: 'present'
upgrade: True
with_items:
- "powershell"
register: check_powershell5
when: "{{ ansible_PSVersionTable.Major|int < 5 }}"
tags: win_powershell
Задача будет выполняться без предупреждения
TASK [win_powershell : install powershell] *************************************
[WARNING]: when statements should not include jinja2 templating delimiters
such as {{ }} or {% %}. Found: {{ ansible_PSVersionTable.Major|int < 5 }}
Это ожидаемо. Предупреждение было специально добавлено в выпуск 2.3.
Как указано в предупреждении, вы не должны использовать разделители jinja2 в выражении when. Вместо этого следует читать:
when: ansible_PSVersionTable.Major|int < 5
Если у вас есть дополнительные вопросы, воспользуйтесь списком рассылки.
Как обойти это предупреждение, если выражение when хранится в переменной (по какой-либо причине, например, из-за того, что оно использовалось несколько раз в разных играх).
например: mycondition: ansible_PSVersionTable.Major|int < 5
для использования как when: mycondition
.
-> Это не работает, потому что mycondition
не оценивается / расширяется и рассматривается как строка.
Что работает, так это объявить mycondition: "{{ ansible_PSVersionTable.Major|int < 5 }}"
или when: "{{ mycondition }}"
но оба результата приведут к вышеупомянутому ПРЕДУПРЕЖДЕНИЮ.
Это работает для меня
when: "(ansible_PSVersionTable.Major|int < 5) and ('Microsoft Windows 7' in ansible_distribution)"
с участием
$ ansible --version
ansible 2.4.0 (devel 53c52cf65f) last updated 2017/03/30 07:29:39 (GMT -500)
config file =
configured module search path = [u'/Users/tanner/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
python version = 2.7.10 (default, Jul 30 2016, 19:40:32) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)]
Для меня это тоже работает. Но теперь переместите условие в переменную и попробуйте вместо нее использовать переменную.
ansible_PSVersionTable - это переменная из настраиваемого факта, который я установил на всех компьютерах с Windows.
Попробуйте следующее, и я предполагаю, что это не сработает (при условии, что условие равно true
):
mycond: "(ansible_PSVersionTable.Major|int < 5) and ('Microsoft Windows 7' in ansible_distribution)"
...
when: mycond
В этом случае вам понадобится "{{...}}" - это только условие "когда", где, я думаю, подразумевается "{{....}}".
также может захотеть использовать | bool, чтобы гарантировать, что var хранится как логическое значение.
Вот что я говорю ... вам понадобится либо "{{...}}" в объявлении переменной, либо условие when, иначе оно не будет работать (правильно). И тогда вы получите указанное ПРЕДУПРЕЖДЕНИЕ.
Вы можете использовать что-то вроде:
- set_fact: content1="{{ var1.stdout }}" content2="{{ var2.stdout }}"
и сравните это.
возможно дублирование # 23578
Меня это тоже немного смущает. Я понимаю, что теперь мы можем использовать myvar
вместо "{{ myvar }}"
или {{ myvar }}
но в некоторых случаях использования этого все еще недостаточно. Например
when: myvar.stdout != ansible_date_time.date
^ Это НЕ вернет текущую дату (ГГГГ-ММ-ДД). В этом случае у меня нет возможности использовать что-либо еще, кроме разделителей jinja2 с чем-то вроде:
- set_fact:
ansible_date: "{{ ansible_date_time.date }}"
Другой вариант использования, например,
- name: "TEST: The files directory should have correct ownership"
shell: stat -c %U:%G {{ files_dir }}
register: styles_dir_ownership
changed_when: styles_dir_ownership.stdout != "{{ user }}:{{ apache_user }}"
failed_when: styles_dir_ownership.stdout != "{{ user }}:{{ apache_user }}"
У меня нет возможности просто сделать user:apache_user
потому что мне нужно передать двоеточие и, следовательно, прибегнуть, например, к
- set_fact:
expected_ownership: "{{ user }}:{{ apache_user }}"
Итак, мой вопрос: как я могу учесть эти 2 варианта использования, если разделители jinja2 устарели, начиная с Ansible 2.3? set_fact
теперь предпочтительный вариант?
Добавление еще одного варианта использования:
рассмотрим следующую переменную:
to_be_removed_users:
- name: 'adm'
remove: False
- name: 'ftp'
remove: True
- name: 'games'
remove: False
- name: 'gopher'
remove: True
- name: 'operator'
remove: False
- name: 'uucp'
remove: True
то следующие задачи генерируют предупреждение. Не уверен, как этого избежать, поскольку item.name является результатом итерации в списке
``
name: Получить список пользователей
getent:
база данных: passwd
теги:
- userdel
@PhilEv , вы можете сделать что-то вроде этого, чтобы избежать этой проблемы (обратите внимание, что вам не нужна настоящая проверка):
`` ---
- name: Favourite colours!
command: echo "I like {{ item }}"
# when: COLOURS.{{item}} is defined and COLOURS.{{item}}
when: item in COLOURS and COLOURS[item]
with_items:
- "GREEN"
- "BLUE"
- "PURPLE"
- "YELLOW"```
Мы также видим эти предупреждения, и удаление разделителей jinja из when
похоже, нарушает это:
- name: Check if redis is installed
shell: redis-server --version || /bin/true
register: redis_is_installed
- include: redis_build.yml
when: "redis_is_installed.stdout.find('v={{ redis_version }}') == -1"
Есть предложения по альтернативному способу написания этого?
@jsuter
when: "redis_is_installed.stdout.find('v=' ~ redis_version) == -1"
@sivel Отлично, спасибо. Что конкретно делает тильда в этом случае? Я не могу найти по нему документы и хотел бы прочитать.
@jsuter http://jinja.pocoo.org/docs/dev/templates/#other -operators
~
Преобразует все операнды в строки и объединяет их.{{"Привет" ~ имя ~ "!" }} вернет (при условии, что имя установлено на 'John') Hello John !.
Спасибо @streetster, как опубликовано в группе ansible (спасибо
when: getent_passwd[item['name']] is defined
все было хорошо в моем случае
Честно говоря, я не понимаю, как можно написать содержательный сценарий игры, не вызвав это новое предупреждающее сообщение. Весь смысл Ansible в том, что вещи можно разделить на роли. Если вы хотите, чтобы это предупреждение не срабатывало, у вас нет шансов, если вы не пишете плоские playbook с уродливыми выражениями when.
Примеры, которые, казалось бы, невозможно обойти:
значения по умолчанию
auth_service : none
auth_service_aws : aws
auth_service_is_aws: '{{ (auth_service == auth_service_aws) | bool }}'
мета
dependencies:
- { role: apollo/auth/aws, when: auth_service_is_aws }
выдает предупреждения ....
И наконец (это действительно сложно обойти!)
Родительская роль - по умолчанию
bootstrap_ping : true
Родительская роль - мета
dependencies:
- { role: apollo/platform/ping, ping: '{{ bootstrap_ping }}' }
Дочерняя роль - задачи
- name: execute
when: ping
win_ping:
Я серьезно надеюсь, что поступаю глупо и упускаю что-то простое, либо это изменение будет отменено в следующем выпуске.
Цвет меня тоже смутил. Все остальное в Ansible, насколько я понимаю, использует разделители Jinja. В чем разница между "changed_when" и остальными? Говоря как человек, изучающий Ansible, это усложняет понимание.
См. Выше PR. Я, вероятно, получу довольно сильный удар по рыбе, но если это затрагивает достаточно людей, пожалуйста, покажите свою поддержку, и, возможно, предупреждения будут удалены (так или иначе).
Вместо того, чтобы говорить, чего не следует делать, следует сказать, ЧТО ДЕЛАТЬ! Мы не волшебники. Благодарю.
Теперь я получаю это предупреждение повсюду. У меня есть общая роль, которая «расширяется» в специализированных ролях путем указания некоторых переменных при определении этой общей роли как такой зависимости в meta/main.yml
:
dependencies:
- role: generic_role
_configuration_needed: "{{custom_configuration_needed}}"
custom_configuration_needed
тогда используется по умолчанию или может быть переопределено для каждого хоста или группы при включении специализированной роли.
Затем в общей роли у меня есть такие шаги:
- name: "configure package if necessary"
include: configure.yml
when: _configuration_needed
Однако теперь я на каждом шаге в configure.yml
в 'базовой' общей роли, выполняемой для этой специализированной роли, получаю такие предупреждения:
[WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: {{custom_configuration_needed}}
```
This is due to the implicit 'when' clause that's added to every step in that included file, but I'm not sure how to solve this-one. The `_configuration_needed` isn't the only case, it's just the one spamming most warnings right now. Now for this `_configuration_needed` I tried defining the dependency like this:
зависимости:
Однако это не работает, поскольку, когда я отлаживаю печать этой переменной _configuration_needed, я вижу эту «custom_configuration_needed» как (непустую) строку, которая всегда принимает значение «True». Это, конечно, нежелательное или нежелательное поведение, и я не знаю, как удалить эти предупреждения.
Если есть рабочее решение для предотвращения появления этих предупреждений в этом случае, которое также имеет ожидаемое поведение, пожалуйста, поделитесь - но прямо сейчас я не могу найти способ сделать это.
Кроме того, для ansible 3, пожалуйста, подумайте о том, чтобы сделать шаблоны jinja единообразными по всем направлениям. Везде или нигде {{}}
, но это просто глупо.
Я не могу выделить динамическую переменную без {{}} , я не могу получить эту работу без фигурных скобок:
vars:
host_name: ['foo', 'bar']
foo_wwn_2: "This exist"
tasks:
- debug:
var: "{{item.1}}_wwn_{{item.0}}"
when: ({{item.1 + '_wwn_' + item.0}}) is defined
with_nested:
- ['1', '2']
- "{{host_name}}"
Без скобок это просто строка, которая будет оценена как ИСТИНА.
Очень досадно видеть, что вы хотите удалить единственный способ оценки переменной в when
.
@bartmeuris в вашем примере, это предупреждение больше не будет отображаться в ansible v2.4, который скоро будет выпущен
@MichalTaratuta, вы должны вместо этого использовать следующее:
when: vars[item.1 ~ '_wnn_' ~ item.0] is defined
Тот факт, что ваш пример работал раньше, был непреднамеренным и не является лучшей практикой для создания имени переменной для проверки.
А как насчет проверки на наличие строки, часть которой содержит переменную?
vars:
acct:
name: example_name
tasks:
- name: Emergency Account | Gather list of usernames
ios_command:
commands: show run | i ^username
register: ios_usernames
- name: Emergency Account | Remove non-emergency account users
ios_config:
lines:
- no {{ item }}
with_flattened:
- "{{ ios_usernames.stdout_lines }}"
when: '"username {{ acct.name }} privilege 0 secret" not in item'
no_log: True
Вполне возможно, что мне просто не хватает лучшего или более подходящего способа написать это, но пока что единственный работающий метод, похоже, использует скобки в цитируемой строке.
РЕДАКТИРОВАТЬ
Извините за загромождение темы. После перечитывания нескольких примеров и дальнейшего тестирования он смог заставить его работать, разбив цитату на части и используя конкатенацию. Делает это немного дольше, но выполняет свою работу.
when: '"username " ~ localauth.emergency.name ~ " privilege 0 secret" not in item'
Я вижу, что предупреждение полезно, но можно, например, написать более длинные выражения, подобные следующему, без каких-либо шаблонных разделителей:
when: |-
{%- set certs = {'sync': False} -%}
{% if gen_node_certs[inventory_hostname] or
(not etcdcert_node.results[0].stat.exists|default(False)) or
(not etcdcert_node.results[1].stat.exists|default(False)) or
(etcdcert_node.results[1].stat.checksum|default('') != etcdcert_master.files|selectattr("path", "equalto", etcdcert_node.results[1].stat.path)|map(attribute="checksum")|first|default('')) -%}
{%- set _ = certs.update({'sync': True}) -%}
{% endif %}
{{ certs.sync }}
Это может помочь новым людям,
Мы не можем использовать переменные внутри условия when, потому что оно имеет некоторые ограничения, и ниже будет отображаться предупреждение
ПРЕДУПРЕЖДЕНИЕ: операторы
поэтому, чтобы избежать таких вещей при проверке условия путем передачи переменной, сначала нам нужно зарегистрировать эту конкретную переменную, а затем использовать ее. Ниже приведен небольшой пример
ВЕРСИЯ уже определена или передана явно при запуске книги воспроизведения
- name: Check the java version
shell: java -version 2>&1 | grep version | awk '{print $3}' | sed 's/"//g' | cut -d "_" -f1
register: java_versios
- name: testing senario
shell: echo '{{ VERSION }}'
register: r
- name: testing
file:
path: /root/Karthik/JAVATEST
state: directory
owner: root
group: root
mode: 0755
recurse: yes
when: java_version.stdout >= r.stdout
Здравствуйте,
Как насчет случая, когда я передаю имя группы инвентаря на основе предопределенной переменной?
В этом сценарии, основанном на переменной «sync_source», я вызываю группу инвентаризации, которая передается как переменная пользователем.
- debug:
msg:
- "source instance: {{ inventory_hostname }}"
- "{{ dir }} size is {{ result_dir_size }} GB"
when: "inventory_hostname in groups.{{ sync_source }}"
@linlinas
when: "inventory_hostname in groups[sync_source]"
Самый полезный комментарий
Честно говоря, я не понимаю, как можно написать содержательный сценарий игры, не вызвав это новое предупреждающее сообщение. Весь смысл Ansible в том, что вещи можно разделить на роли. Если вы хотите, чтобы это предупреждение не срабатывало, у вас нет шансов, если вы не пишете плоские playbook с уродливыми выражениями when.
Примеры, которые, казалось бы, невозможно обойти:
значения по умолчанию
мета
выдает предупреждения ....
И наконец (это действительно сложно обойти!)
Родительская роль - по умолчанию
Родительская роль - мета
Дочерняя роль - задачи
Я серьезно надеюсь, что поступаю глупо и упускаю что-то простое, либо это изменение будет отменено в следующем выпуске.