使用blockinfile:正在使用外部文件中的with_items。当我运行剧本时,我可以看到所有正在处理的主题,但最终文件仅更新了最后一个项目。
道歉,对此有些不了解,因此可能缺少明显的内容。
尝试了各种排列
我有一个外部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
任务:
- 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
答案 0 :(得分:0)
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
。
答案 1 :(得分:0)
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的建议并使用模板。