Can the templates module handle multiple templates / directories?
Asked Answered
W

5

22

I believe the Ansible copy module can take a whole bunch of "files" and copy them in one hit. This I believe can be achieved by copying a directory recursively.

Can the Ansible template module take a whole bunch of "templates" and deploy them in one hit? Is there such a thing as deploying a folder of templates and applying them recursively?

Wuhu answered 16/1, 2017 at 0:21 Comment(0)
C
72

The template module itself runs the action on a single file, but you can use with_filetree to loop recursively over a specified path:

- name: Ensure directory structure exists
  ansible.builtin.file:
    path: '{{ templates_destination }}/{{ item.path }}'
    state: directory
  with_community.general.filetree: '{{ templates_source }}'
  when: item.state == 'directory'

- name: Ensure files are populated from templates
  ansible.builtin.template:
    src: '{{ item.src }}'
    dest: '{{ templates_destination }}/{{ item.path }}'
  with_community.general.filetree: '{{ templates_source }}'
  when: item.state == 'file'

And for templates in a single directory you can use with_fileglob.

Callie answered 16/1, 2017 at 0:44 Comment(2)
this answer is beyond useful, this answer is awesome! i've added my own answer to explain why (but have accepted this)Wuhu
I love it when a plan comes together!Hankering
W
16

This answer provides a working example of the approach laid down by @techraf

with_fileglob expects only files to live within the templates folder - see https://serverfault.com/questions/578544/deploying-a-folder-of-template-files-using-ansible

with_fileglob will only parse files in the templates folder

with_filetree maintains the directory structure when moving the template files to dest. It auto creates those directories for you at dest.

with_filetree will parse all files in the templates folder and nested directories

- name: Approve certs server directories
  file:
    state: directory
    dest: '~/{{ item.path }}'
  with_filetree: '../templates'
  when: item.state == 'directory'

- name: Approve certs server files
  template:
    src: '{{ item.src }}'
    dest: '~/{{ item.path }}'
  with_filetree: '../templates'
  when: item.state == 'file'

Essentially, think of this approach as copying and pasting a directory and all its contents from A to B and whilst doing so, parsing all templates.

Wuhu answered 16/1, 2017 at 1:56 Comment(5)
only issue i had here was with the favicon which i had to copy over manually (it was corrupted when this did it) - you may argue why did i have a favicon in my templates folder ;)Wuhu
Why do you need to pre-create the directories if "It auto creates those directories for you at dest"Lizettelizotte
Question: Does with_filetree also expect files to live within the templates folder?Dimenhydrinate
Update: Just tested this and can confirm that with_filetree WILL WORK with any directory! So, it is not limited to just a templates directory.Dimenhydrinate
does with_filetree overwrite directories if they already exist?Chorion
M
8

I could not manage to do it with the other answers. This is what worked for me:

- name: Template all the templates and place them in the corresponding path
  template:
    src: "{{ item.src }}"
    dest: "{{ destination_path }}/{{ item.path | regex_replace('\\.j2$', '') }}"
    force: yes
  with_filetree: '{{ role_path }}/templates'
  when: item.state == 'file'
Multicellular answered 30/11, 2020 at 16:39 Comment(3)
It seems with_filetree is not available anymore in ansible 2.11Torgerson
@Torgerson just tested with ansible v2.12.1 and it worked perfectlyMulticellular
@Torgerson I see that too, I do not find it in the docs any more. Is there any official alternative?Instinct
E
4

In my case folder contain both files and jinja2 templates.

- name: copy all directories recursively
  file: dest={{templates_dest_path}}/{{ item|replace(templates_src_path+'/', '') }}  state=directory       
  with_items: "{{ lookup('pipe', 'find '+ templates_src_path +'/ -type d').split('\n') }}"

- name: copy all files recursively
  copy: src={{ item }} dest={{templates_dest_path}}/{{ item|replace(templates_src_path+'/', '') }} 
  with_items: "{{ lookup('pipe', 'find '+ templates_src_path +'/  -type f -not -name *.j2 ').split('\n') }}"
  
- name: copy templates files recursively
  template: src={{ item }} dest={{templates_dest_path}}/{{ item|replace(templates_src_path+'/', '')|replace('.j2', '') }}  
  with_items: "{{ lookup('pipe', 'find '+ templates_src_path +'/*.j2 -type f').split('\n') }}"
Edom answered 4/8, 2021 at 19:35 Comment(1)
Simple and working! Also without noisy verbose output like the FileTree Thank you!Socha
H
2

I did it and it worked. \o/

- name: "Create file template"
  template:
    src: "{{ item.src }}"
    dest: "{{ your_dir_remoto }}/{{ item.dest }}"
  loop:
    - { src: '../templates/file1.yaml.j2', dest: 'file1.yaml' }
    - { src: '../templates/file2.yaml.j2', dest: 'file2.yaml' }
Herringbone answered 25/8, 2020 at 13:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.