ansible-collections / cisco.ios

Ansible Network Collection for Cisco IOS
GNU General Public License v3.0
283 stars 169 forks source link

ios_snmp_server readonly community idempotency #971

Closed exeral closed 4 days ago

exeral commented 10 months ago
SUMMARY

when creating a read-only community, the task is always status changed despite there is no change to do

ISSUE TYPE
COMPONENT NAME

cisco.ios.ios_snmp_server

ANSIBLE VERSION
ansible [core 2.11.12]
  config file = /home/ansible/ansible-cisco/ansible.cfg
  configured module search path = ['/home/ansible/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/ansible/.local/lib/python3.7/site-packages/ansible
  ansible collection location = /home/ansible/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/ansible/.local/bin/ansible
  python version = 3.7.12 (default, Nov 16 2021, 18:14:49) [GCC 6.3.0 20170516]
  jinja version = 3.1.2
  libyaml = True
COLLECTION VERSION
# /home/ansible/.local/lib/python3.7/site-packages/ansible_collections
Collection Version
---------- -------
cisco.ios  2.6.0

# /home/ansible/.ansible/collections/ansible_collections
Collection Version
---------- -------
cisco.ios  3.2.0
CONFIGURATION
CACHE_PLUGIN(/home/ansible/ansible-cisco/ansible.cfg) = jsonfile
CACHE_PLUGIN_CONNECTION(/home/ansible/ansible-cisco/ansible.cfg) = /tmp/ansible.cache
CACHE_PLUGIN_TIMEOUT(/home/ansible/ansible-cisco/ansible.cfg) = 86400
DEFAULT_HOST_LIST(/home/ansible/ansible-cisco/ansible.cfg) = ['/home/ansible/ansible-cisco/inventory/production']
DEFAULT_INVENTORY_PLUGIN_PATH(/home/ansible/ansible-cisco/ansible.cfg) = ['/home/ansible/ansible-cisco/inventory/plugins']
HOST_KEY_CHECKING(/home/ansible/ansible-cisco/ansible.cfg) = False
INVENTORY_CACHE_ENABLED(/home/ansible/ansible-cisco/ansible.cfg) = True
INVENTORY_CACHE_PLUGIN_CONNECTION(/home/ansible/ansible-cisco/ansible.cfg) = /tmp/ansible.cache
OS / ENVIRONMENT

debian 9

Cisco IOS Software, C2960 Software (C2960-LANBASEK9-M), Version 15.0(2)SE10a, RELEASE SOFTWARE (fc3) WS-C2960G-48TC-L

STEPS TO REPRODUCE
- name: snmp settings
  cisco.ios.ios_snmp_server:
    config:
      location: "in the racks"
      contact: john@doe.org
      packet_size: 500
      communities:
        - acl_v4: ADMIN-SUP
          name: community_name
          rw: false
          ro: true
EXPECTED RESULTS

after two consecutive runs, task should not have the status "changed"

ACTUAL RESULTS

task status is always "changed"

TASK [dv-cisco : snmp settings] *************************************************************************************************************************************************************************************************************
changed: [switch] => {"after": {"communities": [{"acl_v4": "ADMIN-SUP", "name": "community_name", "ro": true}], "contact": "john@doe.org", "location": "in the racks", "packet_size": 500}, "before": {"communities": [{"acl_v4": "ADMIN-SUP", "name": "community_name", "ro": true}], "contact": "john@doe.org", "location": "in the racks", "packet_size": 500}, "changed": true, "commands": ["snmp-server community community_name ro ADMIN-SUP"]}

I think the issue is that: on Cisco running config it's: snmp-server community community_name RO ADMIN-SUP while ansible try to match this commands ?: snmp-server community community_name ro ADMIN-SUP

Cisco config wants the readonly parameter UPPERCASE

TheRealBecks commented 9 months ago

I found out that 'Legacy IOS' uses RO and RW, but IOS XE uses ro and rw instead. I tested it with my legacy IOS devices and it's working idempotentely as expected.

@exeral Can you please check again with a newer version of cisco.ios? Your newest version is 3.2.0, but the current one in 6.0.0, so it could be that it's already been fixed.

exeral commented 9 months ago

I tested with cisco.ios 6.0.0

➜  ansible-cisco git:(main) ✗ ansible --version
ansible [core 2.14.5]
  config file = /home/avittecoq/ansible-cisco/ansible.cfg
  configured module search path = ['/home/avittecoq/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/avittecoq/.local/lib/python3.10/site-packages/ansible
  ansible collection location = /home/avittecoq/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/avittecoq/.local/bin/ansible
  python version = 3.10.12 (main, Jun 11 2023, 05:26:28) [GCC 11.4.0] (/usr/bin/python3)
  jinja version = 3.1.2
  libyaml = True
➜  ansible-cisco git:(main) ✗ cat /etc/debian_version
bookworm/sid
➜  ansible-cisco git:(main) ✗ ansible-galaxy collection list cisco.ios

# /home/avittecoq/.ansible/collections/ansible_collections
Collection Version
---------- -------
cisco.ios  6.0.0

but it's the same, here is the debug output:

TASK [dv-cisco : snmp settings] *************************************************************************************************************************************************************************************************************
task path: /home/avittecoq/ansible-cisco/roles/dv-cisco/tasks/ios.yaml:25
redirecting (type: connection) ansible.builtin.network_cli to ansible.netcommon.network_cli
redirecting (type: terminal) ansible.builtin.ios to cisco.ios.ios
redirecting (type: cliconf) ansible.builtin.ios to cisco.ios.ios
redirecting (type: become) ansible.builtin.enable to ansible.netcommon.enable
redirecting (type: action) cisco.ios.ios_snmp_server to cisco.ios.ios
redirecting (type: action) cisco.ios.ios_snmp_server to cisco.ios.ios
changed: [cisco-device] => {
    "after": {
        "communities": [
            {
                "acl_v4": "community_name",
                "name": "RO",
                "ro": true
            },
            {
                "acl_v4": "ADMIN-SUP",
                "name": "community_name",
                "ro": true
            }
        ],
        "contact": "john@doe.org",
        "location": "in the racks",
        "packet_size": 500
    },
    "before": {
        "communities": [
            {
                "acl_v4": "community_name",
                "name": "RO",
                "ro": true
            },
            {
                "acl_v4": "ADMIN-SUP",
                "name": "community_name",
                "ro": true
            }
        ],
        "contact": "john@doe.org",
        "location": "in the racks",
        "packet_size": 500
    },
    "changed": true,
    "commands": [
        "snmp-server community community_name ro ADMIN-SUP"
    ],
    "invocation": {
        "module_args": {
            "config": {
                "accounting": null,
                "cache": null,
                "chassis_id": null,
                "communities": [
                    {
                        "acl_v4": "ADMIN-SUP",
                        "acl_v6": null,
                        "name": "community_name",
                        "ro": true,
                        "rw": false,
                        "view": null
                    }
                ],
                "contact": "john@doe.org",
                "context": null,
                "drop": null,
                "engine_id": null,
                "file_transfer": null,
                "groups": null,
                "hosts": null,
                "if_index": null,
                "inform": null,
                "ip": null,
                "location": "in the racks",
                "manager": null,
                "packet_size": 500,
                "password_policy": null,
                "queue_length": null,
                "source_interface": null,
                "system_shutdown": null,
                "trap_source": null,
                "trap_timeout": null,
                "traps": null,
                "users": null,
                "views": null
            },
            "running_config": null,
            "state": "merged"
        }
    }
}

the before/after are identical but the "commands" show it tries in lowercase nayway

I'm also surprised ansible ends creating two communities where one have the community name in the acl field. but that's maybe another story

TheRealBecks commented 9 months ago

@exeral That looks indeed weird^^ Can you also show use the task configuration and YAML values?

exeral commented 8 months ago

Yes it's weird. it's not very critical but a bit annoying, so I'm curious what is the cause

The task is:

- name: snmp settings
  cisco.ios.ios_snmp_server:
    config:
      location: "{{ snmp_location_datacenter }}"
      contact: john@doe.org
      packet_size: 500
      communities:
        - acl_v4: ADMIN-SUP
          name: community_name
          rw: false
          ro: true

snmp_location_datacenter is pulled from inventory and has value "in the racks" community value is hardcoded in the task (as you can see)

shepherdjay commented 6 months ago

I found out that 'Legacy IOS' uses RO and RW, but IOS XE uses ro and rw instead. I tested it with my legacy IOS devices and it's working idempotentely as expected.

On my IOS-XE devices they also show in the config as RO though the command help when configuring shows it in lowercase ro

I'm also running into this. Actually hit -vvvv and wound up with two scenarios that both reporting needing changes but different commands for each.

In the first case is as @exeral reported with rw: true and rw: false it then tries to send the command set of

    "changed": true,
    "commands": [
        "no snmp-server community community ro",
        "snmp-server community community ro"

However if you have the boolean of rw: false only leaving ro: null which is what the documentation shows it doesn't send the ro in the configlet. Cisco defaults at least on the platform I'm testing to read only but I don't know if this would also cause more idempotency issues

    "changed": true,
    "commands": [
        "no snmp-server community community ro",
        "snmp-server community community"
shepherdjay commented 6 months ago

For reference our pip is locked to

ansible-core==2.16.3
ansible==9.2.0

and collection is set to

collections:
- name: cisco.ios
  version: 6.1.2
  type: galaxy