使用Ansible with_subelements操作FortiGate SNMP用户时遇错误求助
解决Ansible处理FortiGate SNMP用户删除的遍历问题
核心问题分析
你误用了with_subelements模块——这个模块用于遍历嵌套的列表结构(比如字典中包含列表类型的子字段),但你的需求只是遍历获取到的SNMP用户列表(每个用户是含name字段的字典),完全不需要嵌套遍历。之前的所有错误都是因为对with_subelements的适用场景理解偏差,以及对注册变量snmp_output的结构解析错误。
正确实现方案
修正后的Playbook
- name: Gather SNMP info fortinet.fortios.fortios_json_generic: vdom: "root" json_generic: method: "GET" path: "/api/v2/cmdb/system.snmp/user" register: snmp_output # 仅在FortiGate主机上执行,避免在其他设备上无效运行 when: ansible_network_os == 'fortinet.fortios.fortios' - name: Remove non-standard usernames from FortiGate devices fortinet.fortios.fortios_system_snmp_user: vdom: "root" state: "absent" system_snmp_user: name: "{{ item.name }}" # 遍历SNMP用户列表,处理空结果的边界情况 loop: "{{ snmp_output.meta.results | default([]) }}" when: - ansible_network_os == 'fortinet.fortios.fortios' - item.name != "test1" - item.name != "test2"
错误原因拆解
针对你之前的4个Playbook错误逐一说明:
Playbook1:
with_subelements的第一个参数{{ snmp_output | default([]) }}是整个注册变量(包含meta、changed等字段的字典),不是可遍历的列表;- 第二个参数
{{ meta.results.name }}语法错误,meta未定义,且无法直接通过results.name提取所有用户的名称。
Playbook2:
with_subelements要求第二个参数对应的字段是列表类型,但name是字符串字段,因此报错“key name应指向列表,却得到'CPR-CTL-RO'”。
Playbook3:
{{ snmp_output.meta | default([]) }}是字典(包含results、method、path等字段),不是可遍历的列表,无法作为with_subelements的第一个参数。
Playbook4:
- 错误地将
snmp_output.meta(字典)作为遍历对象; results.name不是合法的子元素key,meta中没有这个字段,导致解析错误。
- 错误地将
额外优化建议
- 用变量存储允许保留的SNMP用户名,比如
allowed_snmp_users: ["test1", "test2"],然后将条件改为when: item.name not in allowed_snmp_users,提升配置的可维护性; - 确保inventory中的设备分组更清晰,比如单独创建FortiGate组,避免在非目标设备上执行冗余任务。
内容的提问来源于stack exchange,提问作者Jeremy D
相关产品推荐
相关产品推荐

