使用Ansible部署模板文件的文件夹


47

有没有一种简单的方法可以将充满模板.j2文件夹的文件夹部署到linux盒中,使用与模板相同的名称,但不带有.j2扩展名,而不是对每个文件使用模板模块?

现在我有很长的清单:

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

Answers:


67

您可以用来with_fileglob从模板目录中获取文件列表,并使用过滤器像这样剥离j2扩展名。

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

11
请注意,with_fileglob始终使用进行操作files/,您可以使用进入模板../templates/mytemplate/*stackoverflow.com/a/27407566/1695680
ThorSummoner

2
谢谢,这超级有帮助。我发现我必须使用两个反斜杠来避免regex_replace函数中的字面量。也许是因为我的整个dest模板部分都用双引号引起来,所以我可以将YAML格式用于任务定义(我更喜欢单线格式)。
Tony Cesaro

1
这是假定只有文件所在的模板文件夹内,如果你需要支持,你需要with_filetree那么模板文件夹内的两个目录和文件-见stackoverflow.com/questions/41667864/...
danday74

对于文件名中可能存在模式的情况,regex_replace应在行末匹配注释\.j2$
Brett Ryan

20

Michael DeHaan(Ansible的创建者)在CoderWall发表了一篇帖子,谈到了非常相似的问题。您可以根据需要(例如权限和所有权)调整和扩展它。帖子的相关部分在这里:


可以通过使用“ with_items”和单个notify语句来简化此操作。如果任何任务发生更改,则将以与在剧本运行结束时需要重新启动的方式完全相同的方式通知该服务。

 - 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

请注意,由于我们的任务需要多个唯一的参数,因此,我们不仅item在' template:'行中说了“ ” ,还使用with_items了哈希(字典)变量。如果愿意,还可以使用列表将其缩短一些。这是一种风格偏好:

 - 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

当然,我们也可以在另一个文件中定义要遍历的列表,例如groupvars/webservers用于定义webservers组所需的所有变量的“ ”文件,或从varsfiles剧本中的“ ”指令加载的YAML文件。看看我们如何清理。

- name: template everything for fooserv
  template: src={{item.src}} dest={{item.dest}}
  with_items: {{fooserv_template_files}}
  notify: 
      - restart fooserv

5
一个更简单的方法可能是write template: src=templates/{{item}}.j2 dest=/etc/splat/{{item}}.conf,然后使用简单的项目列表:with_items: - foo - bar
Ethan 2015年

现在看来,这实际上是错误的。正确的模板行应为template: src={{item.src}} dest={{item.dest}}(即不是${var},而是{{var}}
Fabiano Francesconi

@FabianoFrancesconi更新。
Mxx

9

罗素的答案确实有效,但需要改进

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

由于regex_replace中的正则表达式是错误的,因此需要除去所有$的冷杉。其次,所有文件应位于文件目录中而不是模板目录中


4
欢迎来到服务器故障!您的答案表明您可以通过先前的答案找到该问题的可行解决方案,因此更适合作为该答案的编辑。请考虑删除您当前的答案,并建议对罗素的答案进行修改。
Paul

7

我编写了一个文件树查找插件,该插件可帮助您对文件树进行操作。

您可以对文件树中的文件进行递归,并根据文件属性执行操作(例如,模板或副本)。由于返回了相对路径,因此您可以轻松地在目标系统上重新创建文件树。

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

它使可读性更高的剧本。


它没有被合并尚未:-(
摩根Christiansson

2
它已被合并。
达格·维耶斯

有没有一种方法可以只过滤* .conf文件?
安德烈(Andrey)

当然,在“ when:”部分中,您可以编写适合您需要的表达式。
Dag Wieers '17

1
该插件并不慢,因为它是单独模板化和复制每个文件的过程,因此速度很慢。但这与插件几乎没有关系,该插件除了模板或复制外还可以用于其他用途。
达格·维耶斯

3

下面的命令对我有用,它可以对模板中的j2文件进行递归查找,并将其移至目标位置。希望它可以帮助寻找模板的递归副本到目标的人。

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

1

可以自动从目录中获取实际文件列表,然后对其进行迭代。

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

请注意有关在换行符上进行分割的标准警告-文件名可能包含换行符。一种更安全的解决方案是使用支持print0(例如)的shell实用程序,find然后拆分\u0000
Dejay Clayton
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.