tower - Una tarea ansible de inclusión solo si el archivo existe
ansible tutorial (8)
¡Gracias a todos por su ayuda! Estoy respondiendo a mi propia pregunta después de finalmente intentar todas las respuestas y el código de mi propia pregunta en Ansible de hoy: ansible 2.0.1.0
Mi código original parece funcionar ahora, excepto que el archivo opcional que estaba buscando estaba en mi máquina local, por lo que tuve que ejecutar stat a través de local_action y establecer become: no
para esas tareas particulares, por lo que ansible no intentaría hacer sudo en mi máquina local y error con: "sudo: se requiere una contraseña / n"
- local_action: stat path=/home/user/optional/file.yml
register: optional_file
become: no
- include: /home/user/optional/file.yml
when: optional_file.stat.exists
Estoy tratando de incluir un archivo solo si existe. Esto permite "tareas / roles" personalizados entre "tareas / roles" existentes si el usuario de mi rol lo necesita. Encontré esto:
- include: ...
when: condition
Pero los documentos de Ansible afirman que:
"Todas las tareas se evalúan, pero el condicional se aplica a todas y cada una de las tareas" - http://docs.ansible.com/playbooks_conditionals.html#applying-when-to-roles-and-includes
Asi que
- stat: path=/home/user/optional/file.yml
register: optional_file
- include: /home/user/optional/file.yml
when: optional_file.stat.exists
Fallará si el archivo que se incluye no existe. Supongo que podría haber otro mecanismo para permitir que un usuario agregue tareas a una receta existente. No puedo permitir que el usuario agregue un rol después del mío, porque no tendrían el control de la orden: su rol se ejecutará después del mío.
Al usar ansible-2.1.0, puedo usar fragmentos de código como este en mi libro de jugadas:
- hosts: all
gather_facts: false
tasks:
- name: Determine if local playbook exists
local_action: stat path=local.yml
register: st
- include: local.yml
when: st.stat.exists
No obtengo errores / fallas cuando local.yml
no existe, y el libro de jugadas se ejecuta (como un libro de jugadas, lo que significa que comienza con los hosts:
línea, etc.)
Puedes hacer lo mismo en el nivel de tarea con un código similar. El uso de stat
parece funcionar correctamente.
El condicional with_first_found
puede lograr esto sin un stat
o local_action
. Este condicional pasará por una lista de archivos locales y ejecutará la tarea con el item
establecido en la ruta del primer archivo que existe. Incluir skip: true
en las opciones with_first_found
evitará que falle si el archivo no existe.
Ejemplo:
- hosts: localhost
connection: local
gather_facts: false
tasks:
- include: "{{ item }}"
with_first_found:
- files:
- /home/user/optional/file.yml
skip: true
La mejor opción que he encontrado hasta ahora es esta:
- include: "{{ hook_variable | default(lookup(''pipe'', ''pwd'') ~ ''/hooks/empty.yml'') }}"
No es exactamente un "si existe", pero le da a los usuarios de su rol el mismo resultado. Cree algunas variables dentro de su rol y un archivo vacío predeterminado. Los filtros Jinja "por defecto" y "búsqueda" se encargan de retroceder en el archivo vacío en caso de que la variable no se haya configurado.
Para mayor comodidad, un usuario podría usar la variable {{ playbook_dir }}
para configurar las rutas:
hook_variable: "{{ playbook_dir }}/hooks/tasks-file.yml"
Podría pasar tiempo aquí para descifrar las disposiciones de manejo de errores, pero en resumen, tiene razón y no puede usar el módulo de stat
para este propósito debido a razones declaradas.
La solución más simple para la mayoría de los problemas ansible es hacerlo fuera de ansible. P.ej
- shell: test -f /home/user/optional/file.yml # or use -r if you''re too particular.
register: optional_file
failed_when: False
- include: /home/user/optional/file.yml
when: optional_file.rc == 0
- debug: msg="/home/user/optional/file.yml did not exist and was not included"
when: optional_file.rc != 0
* failed_when
agregado para evitar que el host sea excluido de otras tareas cuando el archivo no existe.
Si no estoy equivocado, ¿quieres continuar con el libro de jugadas incluso cuando la afirmación es falsa?
Si es así, por favor agregue esta línea después de when:
ignore_errors: True
Para que tus tareas se vean así:
- stat: path=/home/user/optional/file.yml
register: optional_file
- include: /home/user/optional/file.yml
when: optional_file.stat.exists
ignore_errors: True
Por favor, avíseme si entiendo su pregunta correctamente o si puedo ayudarlo. Gracias
También existe la opción de usar un filtro Jinja2 para eso:
- set_fact: optional_file="/home/user/optional/file.yml"
- include: ....
when: optional_file|exists
Usando algo similar, pero para el módulo de archivo y lo que me sirvió para comprobar la definición de la variable, intente algo como:
when: optional_file.stat.exists is defined and optional_file.stat.exists
la tarea se ejecutará solo cuando exista la variable.