Ansible - 仅在文件中更新with_items

问题描述 投票:1回答:2

使用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
ansible
2个回答
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


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建议并使用模板。

© www.soinside.com 2019 - 2024. All rights reserved.