$ 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)]
Stock ansible.cfg
Host de administración macOS 10.12.3
La tarea que he estado usando durante más de 7 meses comenzó a lanzar una advertencia.
- 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
La tarea se ejecutaría sin una advertencia
TASK [win_powershell : install powershell] *************************************
[WARNING]: when statements should not include jinja2 templating delimiters
such as {{ }} or {% %}. Found: {{ ansible_PSVersionTable.Major|int < 5 }}
Se esperaba esto. La advertencia se agregó recientemente a la versión 2.3 a propósito.
Como indica la advertencia, no debe usar delimitadores jinja2 en una declaración when. En su lugar, debería leer:
when: ansible_PSVersionTable.Major|int < 5
Si tiene más preguntas, no dude en utilizar la lista de correo.
Cómo solucionar esta advertencia si la expresión when está almacenada en una variable (por cualquier motivo, por ejemplo, debido a que se usa varias veces en diferentes jugadas).
por ejemplo: mycondition: ansible_PSVersionTable.Major|int < 5
para ser utilizado como when: mycondition
-> Esto no funciona porque mycondition
no se evalúa / expande y se trata como una cadena.
Lo que funciona es declarar mycondition: "{{ ansible_PSVersionTable.Major|int < 5 }}"
o when: "{{ mycondition }}"
pero ambos darán como resultado la ADVERTENCIA antes mencionada.
Esto funciona para mi
when: "(ansible_PSVersionTable.Major|int < 5) and ('Microsoft Windows 7' in ansible_distribution)"
con
$ 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)]
Eso también funciona para mí. Pero ahora mueva la condición a una variable e intente usar la variable en su lugar.
ansible_PSVersionTable es una variable de un hecho personalizado que he instalado en todas las computadoras con Windows.
Intente lo siguiente y supongo que no funcionará (dado que la condición es true
):
mycond: "(ansible_PSVersionTable.Major|int < 5) and ('Microsoft Windows 7' in ansible_distribution)"
...
when: mycond
En ese caso, necesitaría el "{{...}}" - es sólo el condicional 'when' donde el "{{....}}" está implícito, creo.
también podría querer hacer uso de | bool filtro para garantizar que var se almacene como booleano.
Eso es lo que estoy diciendo ... necesitará "{{...}}" dentro de la declaración de la variable o la condición when, ya que de lo contrario no funcionará (correctamente). Y luego obtendrá la ADVERTENCIA mencionada.
Puedes usar algo como:
- set_fact: content1="{{ var1.stdout }}" content2="{{ var2.stdout }}"
y compare eso.
posiblemente un dup de # 23578
También estoy un poco confundido por esto. Entiendo que ahora podemos hacer myvar
lugar de "{{ myvar }}"
o {{ myvar }}
pero hay ciertos casos de uso en los que esto aún no es suficiente. P.ej
when: myvar.stdout != ansible_date_time.date
^ Esto NO devolverá la fecha actual (AAAA-MM-DD). En este caso, no tengo forma de usar nada más que los delimitadores jinja2 con algo como:
- set_fact:
ansible_date: "{{ ansible_date_time.date }}"
Otro caso de uso es, por ejemplo,
- 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 }}"
No tengo forma de simplemente hacer user:apache_user
porque necesito pasar dos puntos y, por lo tanto, tengo que recurrir a, por ejemplo,
- set_fact:
expected_ownership: "{{ user }}:{{ apache_user }}"
Entonces, mi pregunta es: ¿cómo puedo dar cuenta de esos 2 casos de uso si los delimitadores jinja2 están obsoletos a partir de Ansible 2.3? ¿Es set_fact
ahora la opción preferida?
Añadiendo otro caso de uso:
considere la siguiente variable:
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
entonces las siguientes tareas generan la advertencia. No estoy seguro de cómo evitarlo ya que item.name es el resultado de la iteración en la lista
''
nombre: Obtener lista de usuarios
getent:
base de datos: passwd
etiquetas:
- userdel
@PhilEv , puede hacer algo como esto para evitar ese problema (tenga en cuenta que no necesita la verificación verdadera):
`` ---
- 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"```
También estamos viendo estas advertencias, y la eliminación de los delimitadores jinja de when
parece romper esto:
- 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"
¿Alguna sugerencia de una forma alternativa de escribir esto?
@jsuter
when: "redis_is_installed.stdout.find('v=' ~ redis_version) == -1"
@sivel Awesome, gracias. ¿Qué está haciendo la tilde específicamente en este caso? No puedo encontrar los documentos y me encantaría leer.
@jsuter http://jinja.pocoo.org/docs/dev/templates/#other -operators
~
Convierte todos los operandos en cadenas y los concatena.{{"¡Hola" ~ nombre ~ "!" }} devolvería (suponiendo que el nombre se establezca en 'John') ¡Hola John !.
Gracias @streetster como se publicó en el grupo ansible (gracias @sivel y Josh)
when: getent_passwd[item['name']] is defined
estuvo todo bien para mi caso
Honestamente, no veo cómo se puede escribir un libro de jugadas significativo sin activar este nuevo mensaje de advertencia. El objetivo de Ansible es que las cosas se pueden modularizar en roles. Si desea evitar que se active esta advertencia, no tiene ninguna posibilidad a menos que esté escribiendo libros de jugadas planos con expresiones feas.
Ejemplos que aparentemente no se pueden solucionar:
valores predeterminados
auth_service : none
auth_service_aws : aws
auth_service_is_aws: '{{ (auth_service == auth_service_aws) | bool }}'
meta
dependencies:
- { role: apollo/auth/aws, when: auth_service_is_aws }
lanza advertencias ....
Y finalmente (¡esto es realmente difícil de solucionar!)
Función principal: valores predeterminados
bootstrap_ping : true
Rol de padre - meta
dependencies:
- { role: apollo/platform/ping, ping: '{{ bootstrap_ping }}' }
Rol del niño - tareas
- name: execute
when: ping
win_ping:
Espero en serio estar siendo estúpido y me estoy perdiendo algo simple, o este cambio se revertirá en la próxima versión.
Colorame confundido también. Todo lo demás en Ansible, hasta donde puedo ver, usa delimitadores Jinja. ¿Cuál es la diferencia entre "cambiado_cuando" y el resto? Hablar como alguien que está aprendiendo Ansible hace que las cosas sean más difíciles de entender.
Consulte PR arriba. Probablemente me abofetearán con bastante fuerza, pero si está afectando a suficientes personas, muestre su apoyo y tal vez las advertencias se eliminen (ya sea de esta manera u otra).
En lugar de decir qué no hacer, debería decir ¡QUÉ HACER! No somos magos. Gracias.
Ahora recibo esta advertencia por todas partes. Tengo un rol genérico que se 'extiende' en roles especializados al especificar algunas variables al definir este genérico como una dependencia como esta en meta/main.yml
:
dependencies:
- role: generic_role
_configuration_needed: "{{custom_configuration_needed}}"
El custom_configuration_needed
es entonces un valor predeterminado o se puede anular por host o por grupo cuando se incluye el rol especializado.
Luego, en el rol genérico tengo pasos como este:
- name: "configure package if necessary"
include: configure.yml
when: _configuration_needed
Sin embargo, ahora, en cada paso del configure.yml
en el rol genérico 'base' ejecutado para ese rol especializado, recibo advertencias como esta:
[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:
dependencias:
Sin embargo, esto no funciona, ya que cuando depuro imprimir esa variable _configuration_needed, veo esta "custom_configuration_needed" como una cadena (no vacía), que siempre se evalúa como "True". Este ciertamente no es un comportamiento esperado o deseado y no tengo idea de cómo eliminar estas advertencias.
Si hay una solución que funcione para prevenir estas advertencias en este caso, que también tienen el comportamiento esperado, por favor comparta - pero ahora mismo, no puedo encontrar ninguna forma de hacerlo.
Además, para ansible 3, considere hacer que las plantillas jinja sean consistentes en todos los ámbitos. En todas partes o en ninguna {{}}
, pero esto es una tontería.
No puedo desarrollar una variable dinámica sin {{}} , no puedo hacer que esto funcione sin las llaves:
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}}"
Sin los corchetes, es solo una cadena que se evaluará como VERDADERA.
Es realmente decepcionante ver que desea eliminar la única forma de evaluar la variable dentro de when
.
@bartmeuris en su ejemplo, esa advertencia ya no aparecerá en ansible v2.4, que pronto se lanzará
@MichalTaratuta , deberías usar lo siguiente en su lugar:
when: vars[item.1 ~ '_wnn_' ~ item.0] is defined
El hecho de que su ejemplo haya funcionado antes no fue intencional y no es la mejor práctica para crear un nombre de variable para verificar.
¿Qué sucede cuando se prueba la presencia de una cadena, parte de la cual contiene una variable?
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
Es muy posible que me esté perdiendo una forma mejor o más apropiada de escribir eso, pero hasta ahora, el único método que funciona parece ser usar los corchetes dentro de la cadena entre comillas.
EDITAR
Perdón por abarrotar el hilo. Después de volver a leer algunos de los ejemplos y realizar más pruebas, fue capaz de hacerlo funcionar separando la cita y usando la concatenación. Lo hace un poco más largo pero cumple su función.
when: '"username " ~ localauth.emergency.name ~ " privilege 0 secret" not in item'
Veo que la advertencia es útil, pero, por ejemplo, se pueden escribir expresiones más largas como la siguiente sin delimitadores de plantilla:
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 }}
Esto puede ayudar a personas nuevas
No podemos usar variables dentro de la condición cuando porque tiene algunas restricciones y se mostrará una advertencia a continuación
ADVERTENCIA: cuando las declaraciones no deben incluir delimitadores de plantilla jinja2 como {{}} o {%%}
así que para evitar tales cosas mientras verificamos la condición pasando la variable, primero necesitamos registrar esa variable en particular y luego usarla. A continuación está el pequeño ejemplo
La VERSIÓN ya está definida o pasada explícitamente mientras se ejecuta un libro de jugadas.
- 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
Hola,
¿Qué pasa con el caso en el que paso un nombre de grupo de inventario basado en la variable predefinida?
En este escenario basado en la variable "sync_source", invoco al grupo de inventario que es pasado como una variable por el usuario.
- 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]"
Comentario más útil
Honestamente, no veo cómo se puede escribir un libro de jugadas significativo sin activar este nuevo mensaje de advertencia. El objetivo de Ansible es que las cosas se pueden modularizar en roles. Si desea evitar que se active esta advertencia, no tiene ninguna posibilidad a menos que esté escribiendo libros de jugadas planos con expresiones feas.
Ejemplos que aparentemente no se pueden solucionar:
valores predeterminados
meta
lanza advertencias ....
Y finalmente (¡esto es realmente difícil de solucionar!)
Función principal: valores predeterminados
Rol de padre - meta
Rol del niño - tareas
Espero en serio estar siendo estúpido y me estoy perdiendo algo simple, o este cambio se revertirá en la próxima versión.