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

Ansible中如何直接更新字典内列表项?避免重复创建新字典

优化Ansible字典列表项的更新方式

问题描述

我目前通过创建新字典覆盖原字典的方式更新字典列表中的项,但需要更新多个这类字典,不想每次都创建新字典。另外,命令输出的列表不固定,要为每个项的filelist添加不同内容,求更优实现方式。

原实现代码

tmp.yml

- name: Loop over specific keys in a dictionary
  hosts: localhost
  gather_facts: true
  vars:
    java_keystore_cred_list:
      - { application_name: keystore_certs,
          certs_dir_path: '/etc/keystore',
          command: "ls -1 ./*.yml",
          filelist: []
        }
      - { application_name: app_certs,
          certs_dir_path: '/etc/keystore/app_certs',
          command: "ls -1 ./*.yml",
          filelist: []
        }
    new_cred_list: []

  tasks:

    - debug:
        var: java_keystore_cred_list

    - name: Update credential 
      include_tasks: tmp2.yml
      loop: "{{ java_keystore_cred_list }}"

    - name: Update java_keystore_cred_list
      set_fact:
        java_keystore_cred_list: "{{ new_cred_list }}"

    - debug:
        var: java_keystore_cred_list

tmp2.yml

- name: Get filelist
  shell: "{{ item.command }}"
  register: result

- name: Update filelist in item
  set_fact:
    tmp_item: "{{ item | combine({'filelist': result.stdout_lines | from_yaml}) }}"

- name: Update new_cred_list
  set_fact:
    new_cred_list: "{{ (new_cred_list | default([])) + [ tmp_item ] }}"

优化方案

可以直接利用Ansible的loop注册结果,结合combine过滤器和Jinja2列表推导式生成更新后的列表,无需维护临时列表,代码更简洁高效。

优化后的tmp.yml

- name: 循环更新字典列表中的指定项
  hosts: localhost
  gather_facts: true
  vars:
    java_keystore_cred_list:
      - { application_name: keystore_certs,
          certs_dir_path: '/etc/keystore',
          command: "ls -1 ./*.yml",
          filelist: []
        }
      - { application_name: app_certs,
          certs_dir_path: '/etc/keystore/app_certs',
          command: "ls -1 ./*.yml",
          filelist: []
        }

  tasks:
    - debug:
        var: java_keystore_cred_list

    - name: 获取每个项的文件列表
      shell: "{{ item.command }}"
      register: file_results
      loop: "{{ java_keystore_cred_list }}"

    - name: 生成更新后的字典列表
      set_fact:
        java_keystore_cred_list: >-
          {% set updated_list = [] %}
          {% for idx, item in enumerate(java_keystore_cred_list) %}
            {% set updated_item = item | combine({'filelist': file_results.results[idx].stdout_lines}) %}
            {% do updated_list.append(updated_item) %}
          {% endfor %}
          {{ updated_list }}

    - debug:
        var: java_keystore_cred_list

优化说明

  • 移除了临时列表new_cred_list和外部任务文件,逻辑更集中,减少冗余代码
  • 通过register一次性捕获所有循环的执行结果,避免多次调用set_fact累加数据
  • 若使用Ansible 2.10+版本,也可以用更简洁的map写法替代列表推导:
    - name: 生成更新后的字典列表
      set_fact:
        java_keystore_cred_list: "{{ java_keystore_cred_list | zip(file_results.results) | map(lambda x: x[0] | combine({'filelist': x[1].stdout_lines})) | list }}"
    

优化后执行输出

ansible-playbook tmp.yml                                                                                           ✔  ansible2_13 🐍
[警告]: 提供的主机列表为空,仅localhost可用。注意隐式的localhost不匹配'all'

PLAY [循环更新字典列表中的指定项] *********************************************************************************************************************************

TASK [debug] *******************************************************************************************************************************************************************
ok: [localhost] =>
  java_keystore_cred_list:
  - application_name: keystore_certs
    certs_dir_path: /etc/keystore
    command: ls -1 ./*.yml
    filelist: []
  - application_name: app_certs
    certs_dir_path: /etc/keystore/app_certs
    command: ls -1 ./*.yml
    filelist: []

TASK [获取每个项的文件列表] ************************************************************************************************************************************************************
changed: [localhost] => (item={'application_name': 'keystore_certs', 'certs_dir_path': '/etc/keystore', 'command': 'ls -1 ./*.yml', 'filelist': []})
changed: [localhost] => (item={'application_name': 'app_certs', 'certs_dir_path': '/etc/keystore/app_certs', 'command': 'ls -1 ./*.yml', 'filelist': []})

TASK [生成更新后的字典列表] ******************************************************************************************************************************************
ok: [localhost]

TASK [debug] *******************************************************************************************************************************************************************
ok: [localhost] =>
  java_keystore_cred_list:
  - application_name: keystore_certs
    certs_dir_path: /etc/keystore
    command: ls -1 ./*.yml
    filelist:
    - ./tmp.yml
    - ./tmp2.yml
  - application_name: app_certs
    certs_dir_path: /etc/keystore/app_certs
    command: ls -1 ./*.yml
    filelist:
    - ./tmp.yml
    - ./tmp2.yml

PLAY RECAP *********************************************************************************************************************************************************************
localhost                  : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 01:48:28