使用blockinfile:从外部文件使用with_items。当我运行playbook时,我可以看到正在处理的所有项目,但生成的结束文件只更新了最后一项。
道歉,这是一个菜鸟,所以可能会遗漏一些明显的东西。
试过各种排列
我有一个外部yaml配置文件,其中包含以下内容 - 包含在include_vars中:
yaml道具文件:
ds_props:
- prop: dataSource.initialSize=8
- prop: dataSource.maxActive=50
- prop: dataSource.maxIdle=20
- prop: dataSource.minIdle=5
- prop: dataSource.maxWait=1000
Ansible任务:
- name: update DS settings
blockinfile:
path: /app.properties
insertafter: "##### Data Source Properties"
block: |
"{{ item.prop }}"
with_items: "{{ ds_props }}"
预期:
##### Data Source Properties #####
# BEGIN ANSIBLE MANAGED BLOCK
dataSource.initialSize=8
dataSource.maxActive=50
dataSource.maxIdle=20
dataSource.minIdle=5
dataSource.maxWait=1000
# END ANSIBLE MANAGED BLOCK
实际:
##### Data Source Properties #####
# BEGIN ANSIBLE MANAGED BLOCK
dataSource.maxWait=1000
# END ANSIBLE MANAGED BLOCK
blockinfile
的行为与设计完全相同:它向目标文件添加了一个文本块,并在添加修改版本之前删除匹配的块。因此,对于循环的每次迭代,blockinfile
都会删除上一次迭代添加的块并添加一个新块。
鉴于您要向文件中添加单行而不是块,您可能最好使用lineinfile
模块,如:
---
- hosts: localhost
gather_facts: false
vars:
ds_props:
- prop: dataSource.initialSize=8
- prop: dataSource.maxActive=50
- prop: dataSource.maxIdle=20
- prop: dataSource.minIdle=5
- prop: dataSource.maxWait=1000
tasks:
- name: update DS settings using lineinfile
lineinfile:
path: /app.properties-line
line: "{{ item.prop }}"
insertafter: "##### Data Source Properties"
with_items: "{{ ds_props }}"
虽然这有效,但仍然存在问题:如果更改其中一个属性的值,则最终会在文件中包含多个条目。例如,如果我们要将dataSource.maxWait
从1000
改为2000
,我们最终会得到:
dataSource.maxWait=1000
dataSource.maxWait=2000
我们可以使用regexp
模块的lineinfile
选项来防止这种情况,如下所示:
- name: update DS settings using lineinfile
lineinfile:
path: /app.properties-line
line: "{{ item.prop }}"
insertafter: "##### Data Source Properties"
regexp: "{{ item.prop.split('=')[0] }}"
with_items: "{{ ds_props }}"
这将导致模块在添加新属性之前删除特定属性的任何现有行。
顺便提一下,您可能需要考虑稍微重构数据,使用字典而不是“key = value”字符串列表,如下所示:
---
- hosts: localhost
gather_facts: false
vars:
ds_props:
dataSource.initialSize: 8
dataSource.maxActive: 50
dataSource.maxIdle: 20
dataSource.minIdle: 5
dataSource.maxWait: 1000
tasks:
- name: update DS settings using lineinfile
lineinfile:
path: /app.properties-line
line: "{{ item.key }}={{ item.value }}"
insertafter: "##### Data Source Properties"
regexp: "{{ item.key }}"
with_items: "{{ ds_props|dict2items }}"
最后,您可能要考虑使用ansible的lineinfile
模块来创建blockinfile
文件而不是尝试编辑它,而不是使用template
或/app.properties
。
blockinfile
使用marker
来跟踪它在文件中管理的块。默认情况下,此标记为ANSIBLE MANAGED BLOCK
。
在您使用默认标记的情况下会发生的情况是,在第一个项目的“#####数据源属性”行之后创建一个块,然后为下一个项目编辑。
一种解决方案是更改每个项目的标记。另一种是使用@Larsk报告的lineinfile
在这种情况下,我希望立即创建完整块:
- name: update DS settings
blockinfile:
path: /app.properties
insertafter: "##### Data Source Properties"
marker: "Custom ds props - ansible managed"
block: "{{ ds_props | json_query('[].prop') | join('\n') }}"
如果您的意图是使用配置文件执行更复杂的操作,请遵循@Larsk建议并使用模板。