我想要实现的目标如下。假设我们有一本剧本相似的更改为以下代码:
---
- 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
上述剧本因???
其中含有以下内容而无效。
现在我的目标是将这个字典映射到 INI 文件内的sections/options/values并获取以下 INI 内容:
[section1]
option1 = value1
option2 = value2
[section2]
option1 = value1
option2 = value2
不幸的是,这似乎失败了,因为我需要为循环添加第二级嵌套不知何故在外循环中循环遍历各个部分,然后在内循环中循环遍历选项/值。
有没有一种更优雅或“ansible”(因为缺少与 pythonic 相对应的 Ansible 术语)的方法来实现这一点,而不是通过在角色中包装一个循环级别并使用迭代部分名称,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
我只是想保持它DRY并避免重复部分名称,当字典显然可以完美地映射到INI文件的“数据模型”时。
答案1
除了使用“扁平化”版本之外,我不知道默认情况下使用 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
此后,您可以在项目中使用新的过滤器,如下所示:
- 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
如果你了解 python,这有时会有所帮助,因为这样你就可以为 ansible 编写自己的插件。
编辑:我将包括一个可读性较差且不推荐的解决方案。由于它loop:
适用于 JSON 格式的字符串,并且在处理字符串之前会将 jinja2 应用于 ansible 中的字符串,因此您可以使用 jinja 逻辑直接在剧本中为您创建“扁平化”布局。与编写自己的过滤器相比,此解决方案更丑陋且可重用性较差,但从技术上讲仍然有效。
- 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 %}
]