¿Cuál es la diferencia entre valores predeterminados y variables en un rol Ansible?

151

Al crear una nueva función Ansible, la plantilla crea varsun defaultsdirectorio ay un directorio con un main.ymlarchivo vacío . Al definir mi rol, puedo colocar definiciones variables en cualquiera de estos, y estarán disponibles en mis tareas.

¿Cuál es la diferencia entre poner las definiciones en defaultsy vars? ¿Qué debería entrar defaultsy qué debería entrar vars? ¿Tiene sentido usar ambos para los mismos datos?

Sé que hay una diferencia de precedencia / prioridad entre los dos, pero me gustaría entender qué debería ir a dónde.

Digamos que mi rol crearía una lista de directorios en el sistema de destino. Me gustaría proporcionar una lista de directorios predeterminados que se crearán, pero me gustaría permitir que el usuario los anule al usar el rol.

Así es como se vería esto:

---
- directories:
  - foo
  - bar
  - baz

Podría colocar esto en el defaults/main.ymlo en el vars/main.yml, desde una perspectiva de ejecución, no haría ninguna diferencia, pero ¿a dónde debería ir?

nwinkler
fuente

Respuestas:

113

La documentación de Ansible sobre precedencia variable resume este niceley:

Si se definen múltiples variables del mismo nombre en diferentes lugares, ganan en un cierto orden, que es:

  • los vars adicionales (-e en la línea de comando) siempre ganan
  • luego vienen las variables de conexión definidas en el inventario (ansible_ssh_user, etc.)
  • luego viene "casi todo lo demás" (cambios de línea de comando, vars en juego, vars incluidos, vars de roles, etc.)
  • luego viene el resto de las variables definidas en el inventario
  • luego vienen hechos descubiertos sobre un sistema
  • luego "valores predeterminados de roles", que son los más "predeterminados" y pierden prioridad en todo.

Supongamos que tiene una función de "tomcat" que utiliza para instalar Tomcat en un grupo de servidores web, pero necesita diferentes versiones de tomcat en un par de hosts, necesita ejecutarse como usuarios diferentes en otros casos, etc. El defaults/main.ymlarchivo puede verse algo como esto:

tomcat_version: 7.0.56
tomcat_user: tomcat

Dado que esos son solo valores predeterminados, significa que se usarán si esas variables no están definidas en otro lugar para el host en cuestión. Puede anularlos a través de variables adicionales, a través de hechos en su archivo de inventario, etc. para especificar diferentes valores para estas variables.

Editar: Tenga en cuenta que la lista anterior es para Ansible 1.x. En Ansible 2.x, la lista se ha ampliado. Como siempre, la documentación de Ansible proporciona una descripción detallada de la precedencia variable para 2.x.

Bruce P
fuente
44
Gracias, esa es una página excelente, eso es lo que estaba buscando. Entro en muchos más detalles sobre qué poner defaultsy qué varsmás abajo.
nwinkler
42
vale la pena enfatizar: los vars de roles tienen una precedencia muy alta . en mi experiencia son más altos que play vars, lo cual es realmente molesto.
tedder42
5 años después, pero ... tiendo a mirarlo de esta manera: los valores predeterminados de roles son cosas que espero que un usuario del rol anule en sus variables en alguna parte. Role vars, OTOH, me permite evitar la codificación de información en una tarea, pero es probable que solo sea anulada para la prueba y modificada por un mantenedor de roles. Como ejemplo, un nombre de usuario administrador inicial estaría predeterminado, pero las versiones de dependencia estarían en vars.
ntwrkguru
41

Las variables de rol definidas en vartienen una prioridad muy alta: solo se pueden sobrescribir pasándolas en la línea de comando, en la tarea específica o en un bloque. Por lo tanto, casi todas sus variables deben definirse en defaults.

En el artículo " Precedencia variable: dónde colocar sus variables de rol ", el autor da un ejemplo de qué poner vars: constantes específicas del sistema que no cambian mucho. Por lo tanto, puede tener vars/debian.ymly vars/centos.ymlcon los mismos nombres de variables pero valores diferentes e incluirlos condicionalmente.

chiborg
fuente
3

En mi humilde opinión no es práctico y no razonable que lugares Ansible tan alta prioridad de la configuración en vars de papeles . La configuración en vars/main.ymly defaults/main.ymldebe ser baja y probablemente la misma prioridad.

¿Hay ejemplos de la vida real de casos en los que queremos este tipo de comportamiento?

Hay ejemplos de que no queremos esto.

El punto a defaults/main.ymldestacar aquí es que la configuración no puede ser dinámica. Configuración en vars/main.ymllata. Entonces, por ejemplo, puede incluir la configuración para un sistema operativo específico y una versión dinámica como se muestra en geerlingguy.postgresql

Pero debido a que la precedencia es tan extraña y poco práctica en Ansible, geerlingguy necesita introducir pseudo variables como se puede ver en variables.yml

- name: Define postgresql_packages.
  set_fact:
    postgresql_packages: "{{ __postgresql_packages | list }}"
  when: postgresql_packages is not defined

Este es un ejemplo concreto de la vida real que demuestra que la precedencia no es práctica.

Otro punto a destacar aquí es que queremos que los roles sean configurables. Los roles pueden ser externos, gestionados por otra persona. Como regla general, no desea que la configuración en roles tenga alta prioridad.

onknows
fuente
Esto debería ser un comentario, no una respuesta.
ntwrkguru
3

Básicamente, todo lo que entra en los "valores predeterminados de roles" (la carpeta de valores predeterminados dentro del rol) es el más maleable y fácilmente reemplazado. Cualquier cosa en el directorio vars del rol anula las versiones anteriores de esa variable en el espacio de nombres. La idea a seguir aquí es que cuanto más explícito sea el alcance, más prioridad tendrá con la línea de comandos: los vars extra siempre ganan. Las variables de host y / o inventario pueden ganar los valores predeterminados de roles, pero no incluye explícitamente como el directorio vars o una tarea include_vars. Doc

pauljolsen
fuente
-4

Las variables y los valores predeterminados van de la mano. aquí hay un ejemplo

-name: install package
 yum: name=xyz{{package_version}} state=present

en su archivo predeterminado tendría algo como:

package_version: 123

Lo que ansible hará es tomar el valor de package_versiony colocarlo junto al nombre del paquete para que se lea en alguna parte como:

-name: install package
 yum: name=xyz123 state=present

De esta manera se instalará xyz123y no xyz123.4o lo que sea que esté en el gran repositorio de xyz's.

Al final lo hará yum install -y xyz123

Entonces, básicamente, los valores predeterminados son los valores presentes; si no establece un valor específico para las variables, el espacio no puede permanecer vacío.

qubsup
fuente
Vota abajo porque no aborda la pregunta. Obviamente defaultsse usan cuando no hay varsdefinidos, pero la respuesta no explica por qué definiría un valor como uno u otro, que es lo que solicitó el OP. Compare con la explicación a continuación.
Thomas Hirsch