Ansible: [ADVERTENCIA]: cuando las declaraciones no deben incluir delimitadores de plantilla jinja2 como {{}} o {%%}.

Creado en 8 mar. 2017  ·  31Comentarios  ·  Fuente: ansible/ansible

TIPO DE PROBLEMA

  • Informe de error
NOMBRE DEL COMPONENTE
VERSION ANSIBLE
$ 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)]
CONFIGURACIÓN


Stock ansible.cfg

SO / MEDIO AMBIENTE


Host de administración macOS 10.12.3

RESUMEN


La tarea que he estado usando durante más de 7 meses comenzó a lanzar una advertencia.

PASOS PARA REPRODUCIR

- 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
RESULTADOS PREVISTOS


La tarea se ejecutaría sin una advertencia

RESULTADOS ACTUALES

TASK [win_powershell : install powershell] *************************************
 [WARNING]: when statements should not include jinja2 templating delimiters
such as {{ }} or {% %}. Found: {{ ansible_PSVersionTable.Major|int < 5 }}
affects_2.3 bug

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

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.

Todos 31 comentarios

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

  • nombre: asegúrese de eliminar los siguientes usuarios
    usuario:
    nombre: "{{item.name}}"
    estado: ausente
    eliminar: "{{item.remove}}"
    with_items: '{{to_be_removed_users}}'
    cuando: getent_passwd. {{item.name}} está definido
    etiquetas:

    • userdel

      ''

@PhilEv , puede hacer algo como esto para evitar ese problema (tenga en cuenta que no necesita la verificación verdadera):

`` ---

  • Hospedadores:

    • localhost

      Tareas:

    • set_fact:

      COLORES:

      ROJO: Verdadero

      AZUL: Verdadero

      AMARILLO: Falso

- 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).

https://github.com/ansible/ansible/pull/24974

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:

  • rol: rol_genérico
    _configuration_needed: custom_configuration_needed
    ''

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]"
¿Fue útil esta página
0 / 5 - 0 calificaciones