Implementar una carpeta de archivos de plantilla usando ansible

47

¿Hay una manera fácil de implementar una carpeta llena de carpeta de plantilla .j2 en un cuadro de Linux, usando el mismo nombre que la plantilla, pero sin la extensión .j2, en lugar de usar el módulo de plantilla para cada archivo?

En este momento tengo una larga lista de:

- name: create x template
  template:
    src=files/x.conf.j2
    dest=/tmp/x.conf
    owner=root
    group=root
    mode=0755
  notify:
    - restart myService
Trololololol
fuente

Respuestas:

68

Puede usar with_fileglobpara obtener la lista de archivos de su directorio de plantillas y usar filtros para eliminar la extensión j2 de esta manera ...

- name: create x template
  template:
    src: {{ item }}
    dest: /tmp/{{ item | basename | regex_replace('\.j2','') }}
  with_fileglob:
    - ../templates/*.j2
Russell
fuente
11
note with_fileglobsiempre opera desde files/, puede acceder a plantillas con ../templates/mytemplate/*. stackoverflow.com/a/27407566/1695680
ThorSummoner
2
Gracias, esto es super útil. Descubrí que tenía que usar dos barras invertidas para escapar del período literal en la función regex_replace. Tal vez porque tenía toda la parte de la plantilla de dest entre comillas dobles para poder usar el formato YAML para la definición de la tarea (que prefiero sobre el formato de una línea).
Tony Cesaro
1
esto supone que solo los archivos viven dentro de la carpeta de plantillas, si necesita admitir tanto directorios como archivos dentro de la carpeta de plantillas, entonces necesita with_filetree - consulte stackoverflow.com/questions/41667864/…
danday74
Una nota que regex_replacedebe coincidir al final de la línea \.j2$para los casos en que el patrón pueda existir dentro del nombre del archivo.
Brett Ryan el
20

Michael DeHaan (creador de Ansible) hizo una publicación en CoderWall que habla sobre un problema muy similar. Puede ajustarlo y expandirlo de acuerdo con sus necesidades (como permisos y propiedad). La parte relevante de la publicación está aquí:


Esto se puede simplificar usando " with_items" y una sola notifydeclaración. Si alguna de las tareas cambia, se notificará al servicio exactamente de la misma manera que debe reiniciarse al final de la ejecución del libro de jugadas.

 - name:  template everything for fooserv
   template: src={{item.src}} dest={{item.dest}}
   with_items:
      - { src: 'templates/foo.j2', dest: '/etc/splat/foo.conf' }
      - { src: 'templates/bar.j2', dest: '/etc/splat/bar.conf' }
   notify: 
      - restart fooserv

Tenga en cuenta que, dado que tenemos tareas que requieren más de un argumento único, no solo decimos " item" en la template:línea ' ', sino que lo usamos with_itemscon una variable hash (diccionario). También puede mantenerlo un poco más corto usando listas, si lo desea. Esta es una preferencia estilística:

 - name:  template everything for fooserv
   template: src={{item.0}} dest={{item.1}}
   with_items:
      - [ 'templates/foo.j2', '/etc/splat/foo.conf' ]
      - [ 'templates/bar.j2', '/etc/splat/bar.conf' ]
   notify: 
      - restart fooserv

Por supuesto, también podríamos definir la lista sobre la que estaba caminando en otro archivo, como un " groupvars/webservers" archivo para definir todas las variables necesarias para el webserversgrupo, o un archivo YAML cargado desde la varsfilesdirectiva " " dentro del libro de jugadas. Mira cómo esto puede limpiarse si lo hacemos.

- name: template everything for fooserv
  template: src={{item.src}} dest={{item.dest}}
  with_items: {{fooserv_template_files}}
  notify: 
      - restart fooserv
Mxx
fuente
55
Un método más sencillo podría ser la de escribir template: src=templates/{{item}}.j2 dest=/etc/splat/{{item}}.conf, y luego usar una lista simple de los objetos:with_items: - foo - bar
Ethan
Esto realmente se ve mal ahora. La línea de plantilla correcta sería template: src={{item.src}} dest={{item.dest}}(es decir, no ${var}más bien {{var}})
Fabiano Francesconi
@FabianoFrancesconi actualizado.
Mxx
9

La respuesta de Russel funciona pero necesita mejorar

- name: create x template
- template: src={{ item }} dest=/tmp/{{ item | basename | regex_replace('.j2','') }}
- with_fileglob:
   - files/*.j2

Los abetos de todos los $ deben irse, ya que era incorrecto regex en el regex_replace. En segundo lugar, todos los archivos deben estar en el directorio de archivos en lugar del directorio de plantillas

HJ_VORTEX
fuente
44
¡Bienvenido a Server Fault! Su respuesta sugiere que una solución viable a la pregunta está disponible a través de una respuesta previa, por lo tanto, sería más apropiado como una edición de esa respuesta. Considere eliminar su respuesta actual y sugerir una edición a la respuesta de Russell.
Paul
7

Escribí un complemento de búsqueda de filetree que puede ayudar con las acciones en los árboles de archivos.

Puede recurrir sobre archivos en un árbol de archivos y, según las propiedades del archivo, realizar acciones (por ejemplo, plantilla o copia). Como se devuelve la ruta relativa, puede volver a crear el árbol de archivos en los sistemas de destino con facilidad.

- name: Template complete tree
  template:
    src: '{{ item.src }}'
    dest: /web/{{ item.path }}
    force: yes
  with_filetree: some/path/
  when: item.state == 'file'

Hace que los libros de jugadas sean más legibles.

Dag Wieers
fuente
Todavía no se ha fusionado :-(
Morgan Christiansson
2
Se ha fusionado.
Dag Wieers
¿Hay alguna manera de filtrar solo archivos * .conf?
Andrey
Claro, en la parte "cuándo:" puede escribir una expresión que se ajuste a sus necesidades.
Dag Wieers
1
El complemento no es lento, es el proceso de crear plantillas y copiar cada archivo individualmente lo que lo hace lento. Pero eso casi no tiene nada que ver con el complemento, el complemento podría ser útil para otras cosas que no sean plantillas o copias.
Dag Wieers
3

El siguiente comando me funcionó para hacer una búsqueda recursiva de archivos j2 en plantillas y moverlo al destino. Espero que ayude a alguien que busca una copia recursiva de plantillas en el destino.

     - name: Copying the templated jinja2 files
       template: src={{item}} dest={{RUN_TIME}}/{{ item | regex_replace(role_path+'/templates','') | regex_replace('\.j2', '') }}
       with_items: "{{ lookup('pipe','find {{role_path}}/templates -type f').split('\n') }}"
Robin
fuente
1

Existe la posibilidad de tomar la lista de archivos reales del directorio automáticamente e iterarlos después.

- name:         get the list of templates to transfer
  local_action: "shell ls templates/* | sed 's~.*/~~g'"
  register:     template_files

- name:         iterate and send templates
  template:     src=templates/{{ item }} dest=/mydestination/{{ item }}
  with_items:
  - "{{ template_files.stdout.splitlines() }}"
Roman Dolejsi
fuente
Tenga en cuenta la advertencia estándar sobre la división en nueva línea: los nombres de archivo pueden contener nuevas líneas. Una solución más segura es usar una utilidad de shell que admita print0, como find, y luego dividirse \u0000.
Dejay Clayton