Ansible-仅最后一个with_items在文件中更新

时间:2019-04-24 15:58:30

标签: ansible

使用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

2 个答案:

答案 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.maxWait1000更改为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的建议并使用模板。