0xC*_*22L 5 configuration-management ansible
我想要实现的是以下内容。假设我们有一个类似于以下的剧本:
---
- hosts: local
tasks:
- ini_file:
path: test.ini
create: yes
section: "{{???}}"
option: "{{???}}"
value: "{{???}}"
loop: "{{inidict ...???}}"
vars:
inidict:
section1:
option1: value1
option2: value2
section2:
option1: value1
option2: value2
Run Code Online (Sandbox Code Playgroud)
上面的剧本是无效的,因为其中有几行???
。
现在我的目标是将此字典映射到 INI 文件中的部分/选项/值,并获得以下 INI 内容:
[section1]
option1 = value1
option2 = value2
[section2]
option1 = value1
option2 = value2
Run Code Online (Sandbox Code Playgroud)
不幸的是,这似乎失败了,因为我需要为循环添加二级嵌套,以某种方式循环遍历外部循环中的部分,然后遍历内部循环中的选项/值。
有没有比在角色中包装一个循环级别并include_role
在传递节名称和列表选项/值作为变量?
我想一种替代方法可能是以某种方式“展平”字典,从而产生相当于(YAML)的东西:
vars:
inicontents:
- section: section1
key: option1
value: value1
- section: section1
key: option2
value: value2
- section: section2
key: option1
value: value1
- section: section2
key: option2
value: value2
Run Code Online (Sandbox Code Playgroud)
我只想保持 DRY 并避免部分名称的重复,因为 dict 显然可以完美地映射到 INI 文件的“数据模型”上。
小智 5
除了使用您的“扁平”版本之外,我不知道默认情况下使用 ansible 执行此操作的方法。幸运的是,您可以两全其美,并编写自己的过滤器插件来为您扁平化字典。只需将如下内容添加到filter_plugins
项目目录或中的目录中~/.ansible/plugins/filter_plugins
,并将其命名为filters.py
:
class FilterModule(object):
def filters(self):
return { 'ini_dict_flatten': self.ini_dict_flatten }
def ini_dict_flatten(self, arg):
ret = []
for section, subdict in arg.items():
for key, value in subdict.items():
ret.append(dict(section=section,
key=key,
value=value))
return ret
Run Code Online (Sandbox Code Playgroud)
之后,您可以在项目中使用新的过滤器,如下所示:
- hosts: localhost
tasks:
- ini_file:
path: /tmp/test.ini
create: yes
section: "{{ item.section }}"
option: "{{ item.key }}"
value: "{{ item.value }}"
loop: "{{ inidict | ini_dict_flatten }}"
vars:
inidict:
section1:
option1: value1
option2: value2
section2:
option1: value1
option2: value2
Run Code Online (Sandbox Code Playgroud)
如果您了解 python,有时会有所帮助,因为这样您就可以为 ansible 编写自己的插件。
编辑:我还将包括一个可读性较差且不推荐的解决方案。由于loop:
使用 json 格式的字符串,并且 jinja2 在处理字符串之前应用于 ansible 中的字符串,因此您可以使用 jinja 逻辑直接在 playbook 中为您创建“扁平”布局。这个解决方案比编写自己的过滤器更丑陋且可重用性较差,但在技术上仍然有效。
- hosts: localhost
vars:
inidict:
section1:
option1: value1
option2: value2
section2:
option1: value1
option2: value2
tasks:
- ini_file:
path: /tmp/test.ini
create: yes
section: "{{ item.section }}"
option: "{{ item.key }}"
value: "{{ item.value }}"
loop: >-
[
{% for section, subdict in inidict.items() %}
{% for key, value in subdict.items() %}
{'section': '{{ section }}',
'key': '{{ key }}',
'value': '{{ value }}'}
{% if not loop.last %}
,
{% endif %}
{% endfor %}
{% if not loop.last %}
,
{% endif %}
{% endfor %}
]
Run Code Online (Sandbox Code Playgroud)