模板模块能够处理多个模板/目录吗?

20

我认为Ansible的复制模块可以一次性复制一大堆"文件"。这可以通过递归复制目录来实现。

Ansible的模板模块能否一次性地处理许多"模板"并部署它们?是否有一种方法可以部署一个包含模板的文件夹并递归应用它们?

5个回答

68
template 模块本身在单个文件上执行操作,但您可以使用 with_filetree 对指定路径进行递归循环:
- 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'

对于单个目录中的模板,您可以使用with_fileglob


1
这个答案超级有用,太棒了!我已经添加了自己的答案来解释为什么(但是已经接受了这个答案)。 - danday74
2
我喜欢计划成功的感觉! - Dejay Clayton

15

这篇答案提供了一个按照@techraf的方法进行操作的可行示例。

with_fileglob 只会在 templates 文件夹中寻找文件 - 参见 https://serverfault.com/questions/578544/deploying-a-folder-of-template-files-using-ansible

with_fileglob 只会解析位于 templates 文件夹中的文件

with_filetree 将保留模板文件的目录结构并移动到目标位置。它会自动为您在目标位置创建这些目录。

with_filetree 将解析位于 templates 文件夹和嵌套目录中的所有文件。

- 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'

基本上,将这种方法视为从A复制并粘贴一个目录及其所有内容到B,同时在此过程中解析所有模板。


我在这里遇到的唯一问题是网站图标,我不得不手动复制它(当我这样做时它已经损坏了)。你可能会问为什么我在我的模板文件夹中放置了网站图标 ;) - danday74
3
为什么要预先创建目录,如果“它会在目标位置自动为您创建这些目录”? - blueFast
问题:with_filetree是否也期望文件存储在模板文件夹中? - sudo soul
1
更新:刚刚测试过,可以确认 with_filetree 可以与任何目录一起使用!因此,它不仅限于 templates 目录。 - sudo soul
如果with_filetree中的目录已经存在,它会覆盖吗? - miller the gorilla

8
我无法使用其他答案来解决问题,以下方法对我有效:

我之前尝试了其他方法都无效。以下方法是可行的:

- 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'

似乎 with_filetree 在 Ansible 2.11 中不再可用。 - Cyril
1
@ Cyril 刚刚测试了 ansible v2.12.1,它完美地工作了。 - Samuryte
@Cyril 我也注意到了,我在文档中也找不到了。有官方的替代方案吗? - undefined

3

在我的情况下,文件夹中既包含文件又包含jinja2模板。

- 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') }}"

1
我做到了,而且它起作用了。 \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' }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接