我有一个 Ansible 剧本,我正在使用 with_subelements 模块在 FortiGates 上执行 SNMP 用户操作。我尝试使用循环,但这表现出了一些非常奇怪的行为(在另一个问题here中概述)。由于某种原因,我似乎无法让它正确解析和执行。您可以在控制台错误输出中看到 JSON 信息,其中“meta”是顶级元素。我需要将 JSON 数据转换为其他格式吗?我使用了错误的语法吗?难道我想做的事不会以这种方式进行吗?
它在 RHEL 9.4、Ansible 9.7 和 Python 3.11.7 上运行。
host_pinned
就是策略。
代码非常简单。它首先执行 API 调用来获取所有 SNMP 用户信息。然后,它应该使用 with_subelements 来遍历输出并删除任何不符合条件的 SNMP 用户,即标准用户。
剧本#1:
- 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
- name: Remove non-standard usernames from FortiGate devices
fortinet.fortios.fortios_system_snmp_user:
vdom: "root"
state: "absent"
system_snmp_user:
name: "{{ item.1 }}"
with_subelements:
- "{{ snmp_output | default([]) }}"
- "{{ meta.results.name }}"
when:
- item.1 != "test1"
- item.1 != "test2"
此代码产生以下输出和相应的错误。请注意错误消息如何开始流入之前的任务,这可能是也可能不是控制台奇怪,尽管这种行为是一致的。
***编辑:添加到 snmp_output 的调试中以添加参考
WITH_SUBELEMENTS 错误#1:
TASK [Gather SNMP info] ********************************************************
changed: [firewall1] => changed=true
meta:
build: 1577
http_method: GET
http_status: 200
matched_count: 2
name: user
next_idx: 1
path: system.snmp
results:
- auth-proto: sha
auth-pwd: ENC XXXX
events: cpu-high mem-low log-full intf-ip vpn-tun-up vpn-tun-down ha-switch ha-hb-failure ips-signature ips-anomaly av-virus av-oversize av-pattern av-fragmented fm-if-change bgp-established bgp-backward-transition ha-member-up ha-member-down ent-conf-change av-conserve av-bypass av-oversize-passed av-oversize-blocked ips-pkg-update ips-fail-open temperature-high voltage-alert power-supply-failure faz-disconnect wc-ap-up wc-ap-down fswctl-session-up fswctl-session-down load-balance-real-server-down per-cpu-high dhcp pool-usage ospf-nbr-state-change ospf-virtnbr-state-change
ha-direct: enable
mib-view: ''
name: test1
notify-hosts: XXXX
notify-hosts6: ''
priv-proto: aes
priv-pwd: ENC XXXX
q_origin_key: test1
queries: enable
query-port: 161
security-level: auth-priv
source-ip: 0.0.0.0
source-ipv6: '::'
status: enable
trap-lport: 162
trap-rport: 162
trap-status: disable
vdoms: []
- auth-proto: sha
auth-pwd: ENC XXXX
events: cpu-high mem-low log-full intf-ip vpn-tun-up vpn-tun-down ha-switch ha-hb-failure ips-signature ips-anomaly av-virus av-oversize av-pattern av-fragmented fm-if-change bgp-established bgp-backward-transition ha-member-up ha-member-down ent-conf-change av-conserve av-bypass av-oversize-passed av-oversize-blocked ips-pkg-update ips-fail-open temperature-high voltage-alert power-supply-failure faz-disconnect wc-ap-up wc-ap-down fswctl-session-up fswctl-session-down load-balance-real-server-down per-cpu-high dhcp pool-usage ospf-nbr-state-change ospf-virtnbr-state-change
ha-direct: enable
mib-view: ''
name: test2
notify-hosts: XXXX
notify-hosts6: ''
priv-proto: aes
priv-pwd: ENC XXXX
q_origin_key: test2
queries: enable
query-port: 161
security-level: auth-priv
source-ip: 0.0.0.0
source-ipv6: '::'
status: enable
trap-lport: 162
trap-rport: 162
trap-status: disable
vdoms: []
revision: XXXX
serial: XXXX
size: 2
status: success
vdom: root
version: v7.2.7
The conditional check 'item.1 != "test1"' failed. The error was: error while evaluating conditional (item.1 != "test1"): 'item' is undefined. 'item' is undefined
The error appears to be in '/home/svc-acct/_work/7/s/ansible/import_tasks/FortiOS_snmp_update-task.yml': line 61, column 3, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: Remove non-standard usernames from FortiGate devices
^ here
TASK [Debug snmp_output register] **************************************************
ok: [firewall1] =>
msg: 'Contents of snmp_output: {''changed'': True, ''meta'': {''http_method'': ''GET'', ''size'': 2, ''matched_count'': 2, ''next_idx'': 1, ''revision'': ''XXXX'', ''results'': [{''name'': ''test1'', ''q_origin_key'': ''test1'', ''status'': ''enable'', ''trap-status'': ''disable'', ''trap-lport'': 162, ''trap-rport'': 162, ''queries'': ''enable'', ''query-port'': 161, ''notify-hosts'': ''XXXX'', ''notify-hosts6'': '''', ''source-ip'': ''0.0.0.0'', ''source-ipv6'': ''::'', ''ha-direct'': ''enable'', ''events'': ''cpu-high mem-low log-full intf-ip vpn-tun-up vpn-tun-down ha-switch ha-hb-failure ips-signature ips-anomaly av-virus av-oversize av-pattern av-fragmented fm-if-change bgp-established bgp-backward-transition ha-member-up ha-member-down ent-conf-change av-conserve av-bypass av-oversize-passed av-oversize-blocked ips-pkg-update ips-fail-open temperature-high voltage-alert power-supply-failure faz-disconnect wc-ap-up wc-ap-down fswctl-session-up
fswctl-session-down load-balance-real-server-down per-cpu-high dhcp pool-usage ospf-nbr-state-change ospf-virtnbr-state-change'', ''mib-view'': '''', ''vdoms'': [], ''security-level'': ''auth-priv'', ''auth-proto'': ''sha'', ''auth-pwd'': ''ENC XXXX'', ''priv-proto'': ''aes'', ''priv-pwd'': ''ENC XXXX''}, {''name'': ''test2'', ''q_origin_key'': ''test2'', ''status'': ''enable'', ''trap-status'': ''disable'', ''trap-lport'': 162, ''trap-rport'': 162, ''queries'': ''enable'', ''query-port'': 161, ''notify-hosts'': ''XXXX'', ''notify-hosts6'': '''', ''source-ip'': ''0.0.0.0'', ''source-ipv6'': ''::'', ''ha-direct'': ''enable'', ''events'': ''cpu-high mem-low log-full intf-ip vpn-tun-up vpn-tun-down ha-switch ha-hb-failure ips-signature ips-anomaly av-virus av-oversize av-pattern av-fragmented fm-if-change bgp-established bgp-backward-transition ha-member-up ha-member-down ent-conf-change av-conserve
av-bypass av-oversize-passed av-oversize-blocked ips-pkg-update ips-fail-open temperature-high voltage-alert power-supply-failure faz-disconnect wc-ap-up wc-ap-down fswctl-session-up fswctl-session-down load-balance-real-server-down per-cpu-high dhcp pool-usage ospf-nbr-state-change ospf-virtnbr-state-change'', ''mib-view'': '''', ''vdoms'': [], ''security-level'': ''auth-priv'', ''auth-proto'': ''sha'', ''auth-pwd'': ''ENC XXXX'', ''priv-proto'': ''aes'', ''priv-pwd'': ''ENC XXXX''}], ''vdom'': ''root'', ''path'': ''system.snmp'', ''name'': ''user'', ''status'': ''success'', ''http_status'': 200, ''serial'': ''XXXX'', ''version'': ''v7.2.7'', ''build'': 1577}, ''failed'': False}'
TASK [Remove non-standard usernames from FortiGate devices] ********************
fatal: [firewall1]: FAILED! =>
msg: '''meta'' is undefined. ''meta'' is undefined'
TASK [Log failure and rescue] **************************************************
ok: [firewall1] =>
msg: firewall1 has experienced a failure
TASK [ansible.builtin.lineinfile] **********************************************
changed: [firewall1] => changed=true
backup: ''
msg: line added
PLAY RECAP *********************************************************************
firewall1 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=1 ignored=0
如果我稍微调整 with_subelements 参数,我将得到以下结果(后续示例中省略的收集 SNMP 信息任务输出):
剧本#2:
- 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
- name: Remove non-standard usernames from FortiGate devices
fortinet.fortios.fortios_system_snmp_user:
vdom: "root"
state: "absent"
system_snmp_user:
name: "{{ item.1 }}"
with_subelements:
- "{{ snmp_output.meta.results | default([]) }}"
- name
when:
- item.1 != "test1"
- item.1 != "test2"
WITH_SUBELEMENTS 错误#2:
TASK [Remove non-standard usernames from FortiGate devices] ********************
fatal: [uslb1m01fwl01-01]: FAILED! =>
msg: the key name should point to a list, got 'CPR-CTL-RO'
如果我尝试一点不同,我会得到:
剧本#3:
- 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
- name: Remove non-standard usernames from FortiGate devices
fortinet.fortios.fortios_system_snmp_user:
vdom: "root"
state: "absent"
system_snmp_user:
name: "{{ item.1 }}"
with_subelements:
- "{{ snmp_output.meta | default([]) }}"
- name
when:
- item.1 != "test1"
- item.1 != "test2"
WITH_SUBELEMENTS 错误#3:
TASK [Remove non-standard usernames from FortiGate devices] ********************
fatal: [firewall1]: FAILED! =>
msg: subelements lookup expects a dictionary, got 'test1'
最后一次尝试...
剧本#4:
- 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
- name: Remove non-standard usernames from FortiGate devices
fortinet.fortios.fortios_system_snmp_user:
vdom: "root"
state: "absent"
system_snmp_user:
name: "{{ item.1 }}"
with_subelements:
- "{{ snmp_output.meta | default([]) }}"
- results.name
when:
- item.1 != "test1"
- item.1 != "test2"
WITH_SUBELEMENTS 错误#4:
TASK [Remove non-standard usernames from FortiGate devices] ********************
fatal: [firewall1]: FAILED! =>
msg: subelements lookup expects a dictionary, got 'GET'
库存文件样本:
inventory:
children:
lab:
#
lab:
hosts:
switch1:
ansible_host: 10.1.2.2
ansible_network_os: cisco.ios.ios
ansible_connection: ansible.netcommon.network_cli
#
firewall1:
ansible_host: 10.1.2.3
ansible_network_os: fortinet.fortios.fortios
ansible_connection: ansible.netcommon.httpapi
ansible_httpapi_use_ssl: yes
ansible_httpapi_validate_certs: no
ansible_httpapi_port: 4443
如果需要任何其他信息或有帮助,请告诉我。预先感谢!
除非我完全错过了你的剧本的目标,否则根据你的第一个任务输出和收集到的信息,绝对没有必要在这里使用
subelements
查找:
- name: Remove non-standard usernames from FortiGate devices
fortinet.fortios.fortios_system_snmp_user:
vdom: "root"
state: "absent"
system_snmp_user:
name: "{{ item.name }}"
loop: "{{ snmp_output.meta.results | default([]) }}"
when: item.name not in ["test1", "test2"]