【发布时间】:2015-10-07 13:49:09
【问题描述】:
我需要修改一个 yaml 文件 (schleuder configuration),我想从 ansible playbook 中执行此操作 - 是否有一个模块可以执行此操作?很难用谷歌搜索,所有出现的都是如何编写剧本。
【问题讨论】:
标签: ansible
我需要修改一个 yaml 文件 (schleuder configuration),我想从 ansible playbook 中执行此操作 - 是否有一个模块可以执行此操作?很难用谷歌搜索,所有出现的都是如何编写剧本。
【问题讨论】:
标签: ansible
我还需要配置管理 yaml 文件。我编写了一个 ansible 模块,它在编辑 yaml 文件时尝试幂等。
我称之为 yedit (yaml-edit)。 https://github.com/kwoodson/ansible-role-yedit
如果您觉得有用,请告诉我。当我们的团队遇到需求时,我会根据请求或拉取请求添加功能。
这是一个简单的剧本示例:
roles:
- lib_yaml_editor
tasks:
- name: edit some yaml
yedit:
src: /path/to/yaml/file
key: foo
value: bar
- name: more complex data structure
yedit:
src: /path/to/yaml/file
key: a#b#c#d
value:
e:
f: This is a test
应该产生如下所示的东西:
foo: bar
a:
b:
c:
d:
e:
f: This is a test
编辑:2018 年 5 月 27 日
【讨论】:
实现此目的的一种方法是将文件读入事实,根据需要更新事实,然后稍后将事实写回 yaml 文件。
- name: Read the yaml
slurp:
path: myfile.yaml
register: r_myfile
- name: extract the data
set_fact:
mydata: "{{ r_myfile['content'] | b64decode | from_yaml }}"
然后根据需要更新事实,例如使用ansible.utils.update_fact module。
- name: Write back to a file
copy:
content: '{{ mydata | to_nice_yaml }}'
dest: myfile.yaml
当然,您需要注意,这会使整个更新成为非原子更新。
更新:我最初的建议使用了lookup('file'),但当然是访问本地文件。 slurp 是读取远程文件的正确方法。
【讨论】:
combine 过滤器替换原始字典中的键。
根据 Kevin 和 Bogd 的回答,如果您想合并嵌套键而不是覆盖 YAML 文件的整个分支,则必须在 combine 函数中启用递归:
mydata: "{{ mydata | combine(newdata, recursive=True) }}"
递归 是一个布尔值,默认为 False。组合是否应该递归合并嵌套哈希。注意:它不依赖于 ansible.cfg 中 hash_behaviour 设置的值。
所以完整的解决方案变成:
- name: Open yaml file
slurp:
path: myfile.yaml
register: r_myfile
- name: Read yaml to dictionary
set_fact:
mydata: "{{ r_myfile['content'] | b64decode | from_yaml }}"
- name: Patch yaml dictionary
set_fact:
mydata: "{{ mydata | combine(newdata, recursive=True) }}"
vars:
newdata:
existing_key:
existing_nested_key: new_value
new_nested_key: new_value
- name: Write yaml file
copy:
content: '{{ mydata | to_nice_yaml }}'
dest: myfile.yaml
注意:递归只能添加嵌套键或替换嵌套值。删除特定的嵌套键需要更高级的解决方案。
【讨论】:
这是基于 Kevin Keane 的回答 - 我刚刚添加了事实修改部分。而且由于似乎无法编辑现有答案(编辑队列已满),我只是为其他(像我一样)来这里寻找详细信息的人添加了这个。
从文件中读取 YAML 数据,并创建一个事实来存储该数据:
- name: Read the yaml
slurp:
path: myfile.yaml
register: r_myfile
- name: extract the data
set_fact:
mydata: "{{ r_myfile['content'] | b64decode | from_yaml }}"
我无法找到任何方式来修改 Ansible 中的现有字典。因此,实际修改数据的解决方法是创建一个与现有事实 (mydata) 同名的新字典,并根据需要使用 combine 过滤器更改键:
- name: Create configuration for core - modify params
set_fact:
mydata: "{{ mydata | combine(newdata) }}"
vars:
newdata:
old_key: new_value
new_key: new_value
将修改后的数据写入文件:
- name: Write back to a file
copy:
content: '{{ mydata | to_nice_yaml }}'
dest: myfile.yaml
结果:
原始 myfile.yaml:
---
another_key: another_value # This is a key that we will not touch
old_key: old_value # This is an old key, that we will change
剧本执行后的文件:
another_key: another_value
new_key: new_value
old_key: new_value
请注意(正如您可能预期的那样)所有 cmets 都已消失,因为您只是在读取 YAML 数据并将其写回。
【讨论】:
没有这样的模块。你可以查看https://docs.ansible.com/ansible/list_of_all_modules.html
最好的办法是使用 lineinfile 或 template 或 copy 模块。
【讨论】:
【讨论】:
lineinfile 方法,该方法仅在简单的情况下有用。