首页 > 解决方案 > 如何遍历字典列表及其内容列表

问题描述

我有以下变量

---

- hosts: all

  vars:
    new_service:
      name: test
      Unit:
      - option: Description
        value: "Testname"
      Service:
      - option: ExecStart
        value: "/usr/bin/python3 -m http.server 8080"
      - option: WorkingDirectory
        value: /home/test/testservice/html

我希望能够使用ini_file模块来创建服务模板,以便将上面的var转换成下面的ini文件

[Unit]
Description=Testname

[Service]
ExecStart=/usr/bin/python3 -m http.server 8080
WorkingDirectory=/home/test/testservice/html

我不知道如何循环这个。我正在考虑使用 product() 来循环嵌套列表,也许是这样的?

  - name: "Create new unit section of service file"
    ini_file:
      path: "~{{ USERNAME }}/.config/systemd/user/{{ new_service[name] }}"
      section: "{{ item.0 }}"
      option: "{{ item.1.option }}"
      value: "{{ item.1.value }}"
    loop: "{{ ['unit', 'service'] | product({{ new_service[item.0] }})"

但我不相信 item 是在循环定义本身中定义的

(我使用 ini_file 而不是模板的原因是因为我希望服务文件创建能够按需处理任意数量的字段)

标签: ansible

解决方案


您仍然可以使用模板来拥有可变数量的部分和选项。在这里使用loopwithini_file不是有效的 IMO。唯一真正的用例是如果您需要保留文件的原始内容只添加新内容。但是性能会大大低于单个模板,特别是如果你有很多元素。

我看到的唯一困难是name您的 dict 中有一个不是节标题的属性。但很容易排除。

模板.j2

{% for section in new_service %}
{% if section != 'name' %}
[{{ section }}]
{% for option in new_service[section] %}
{{ option.option }}={{ option.value }}
{% endfor %}

{% endif %}
{% endfor %}

回到原来的问题

如果您真的想通过循环路线,它仍然是可能的,但是您的实际数据结构需要相当多的努力(loop/ set_fact/... 最终得到一个可循环的结构)。

如果可能,我会将其更改为以下内容:

new_service:
  name: test
  sections:
    - section: Unit
      options:
        - option: Description
          value: "Testname"
    - section: Service
      options:
        - option: ExecStart
          value: "/usr/bin/python3 -m http.server 8080"
        - option: WorkingDirectory
          value: /home/test/testservice/html

然后,您可以使用subelementslookup直接循环遍历此结构。请注意,"name"(在顶层)不是 var,而是您的服务名称值的字符串标识符,应该按原样使用(在下面的示例中已修复):

  - name: "Create new unit section of service file"
    ini_file:
      path: "~{{ USERNAME }}/.config/systemd/user/{{ new_service.name }}"
      section: "{{ item.0.section }}"
      option: "{{ item.1.option }}"
      value: "{{ item.1.value }}"
    loop: "{{ lookup('subelements', new_service.sections, 'options') }}"

如果需要,您也可以轻松地将我的第一个示例模板调整为这种新的数据结构。


推荐阅读