You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Ansible中基于用户配置向字典列表追加字典

问题:通过Ansible动态生成systemd服务配置列表

场景说明

需要通过Ansible部署一个支持可配置节点数量的应用,每个应用节点以systemd服务运行。使用systemd服务管理角色维护这些服务,该角色要求提供服务名称、优先级等配置信息。

用户在playbook中定义的节点变量如下:

application_nodes:
  - name: "node1"
    api_port: 3900
  - name: "node2"
    api_port: 3910

尝试的方法及错误

方法1:字符串拼接生成服务列表

尝试用模板循环拼接字符串生成服务配置,代码如下:

service_list: "{% for node in application_nodes %}{'name': 'application_{{ node.name }}.service', 'priority': 1000}{% endfor %}"
devture_systemd_service_manager_services_list_auto: |
  {{
    ([{{ service_list }}])
  }}

执行后报错:

FAILED! => {"msg": "An unhandled exception occurred while templating '{{\n  ([{{ service_list }}])\n}}\n'. Error was a <class 'ansible.errors.AnsibleError'>, original message: template error while templating string: expected token ':', got '}'. String: {{\n  ([{{ service_list }}])\n}}\n. expected token ':', got '}'"}

方法2:循环追加列表到变量

尝试用set_fact循环追加服务配置,代码如下:

- name: Append services list by nodes
  set_fact:
    devture_systemd_service_manager_services_list_auto: "{{ devture_systemd_service_manager_services_list_auto + [{'name': 'application_{{ item.name }}.service', 'priority': 1000, 'groups': ['applicationname']}] }}"
  loop: "{{ application_nodes }}"

- name: "Print services"
  debug:
    msg: "services {{ devture_systemd_service_manager_services_list_auto }}"

执行后报错:

TASK [custom/base : Print services B] ********************************************************************************************************************************************************************************************************************
fatal: [mydomain]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: [{'name': 'application_node2.service', 'priority': 1000, 'groups': ['applicationname']}, {'name': 'application_{{ item.name }}.service', 'priority': 1000, 'groups': ['applicationname']}]: 'item' is undefined. 'item' is undefined. [{'name': 'application_node2.service', 'priority': 1000, 'groups': ['applicationname']}, {'name': 'application_{{ item.name }}.service', 'priority': 1000, 'groups': ['applicationname']}]: 'item' is undefined. 'item' is undefined\n\nThe error appears to be in '/.../roles/custom/base/tasks/add_services.yml': line 11, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: \"Print services B\"\n  ^ here\n"}

期望的最终效果

希望自动生成适配所有节点的服务列表,效果如下:

devture_systemd_service_manager_services_list_auto: |
  {{
    ([{'name': 'application_node1.service', 'priority': 1000}])
    +
    ([{'name': 'application_node2.service', 'priority': 1000}])
  }}

解决方案

方案1:使用列表推导式直接生成

Ansible支持Jinja2列表推导式,可直接生成所需服务列表,无需字符串拼接或循环追加:

devture_systemd_service_manager_services_list_auto: "{{ application_nodes | map('combine', {'name': 'application_' ~ item.name ~ '.service', 'priority': 1000, 'groups': ['applicationname']}) | list }}"

或者更简洁的写法:

devture_systemd_service_manager_services_list_auto: >-
  {{
    application_nodes | map('extract', {}, ['name'])
    | map('regex_replace', '^(.*)$', 'application_\\1.service')
    | map('community.general.dict_kv', 'name')
    | map('combine', {'priority': 1000, 'groups': ['applicationname']})
    | list
  }}

方案2:修复set_fact循环写法

如果坚持用循环追加,需注意变量嵌套语法,避免在双引号中嵌套{{ }},改用Jinja2字符串拼接:

- name: Initialize services list if not exists
  set_fact:
    devture_systemd_service_manager_services_list_auto: []

- name: Append services list by nodes
  set_fact:
    devture_systemd_service_manager_services_list_auto: "{{ devture_systemd_service_manager_services_list_auto + [{'name': 'application_' ~ item.name ~ '.service', 'priority': 1000, 'groups': ['applicationname']}] }}"
  loop: "{{ application_nodes }}"

- name: "Print services"
  debug:
    msg: "services {{ devture_systemd_service_manager_services_list_auto }}"

注意:必须先初始化列表为空,避免变量未定义问题;同时用~进行字符串拼接,而非嵌套{{ }}。

内容的提问来源于stack exchange,提问作者Moanos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 09:30:57