diff --git a/changelogs/fragments/eos_module_utils_bugfix.yaml b/changelogs/fragments/eos_module_utils_bugfix.yaml new file mode 100644 index 00000000000..d8fa43e9692 --- /dev/null +++ b/changelogs/fragments/eos_module_utils_bugfix.yaml @@ -0,0 +1,2 @@ +bugfixes: + - Fix misuse of self in module_utils/network/eos/eos.py (https://github.com/ansible/ansible/pull/39074) diff --git a/changelogs/fragments/nxos_bugfixes.yaml b/changelogs/fragments/nxos_bugfixes.yaml index b22874bd8d9..4a2393fd44f 100644 --- a/changelogs/fragments/nxos_bugfixes.yaml +++ b/changelogs/fragments/nxos_bugfixes.yaml @@ -20,3 +20,10 @@ bugfixes: - nxos_igmp_snooping - Fix nxos_igmp_snooping (https://github.com/ansible/ansible/pull/38566) - nxos_ntp_auth - Fix nxos_ntp_auth issues (https://github.com/ansible/ansible/pull/38824) - nxos_ntp_options - Fix nxos_ntp_options issues (https://github.com/ansible/ansible/pull/38695) +- nxos_feature - Handle nxos_feature issue where json isn't supported (https://github.com/ansible/ansible/pull/39150) +- nxos_ntp - Fix nxos_ntp issues (https://github.com/ansible/ansible/pull/39178) +- nxos_interface - Fix AttributeError NoneType object has no attribute group (https://github.com/ansible/ansible/pull/38544) +- nxos_snmp_community - Fix nxos_snmp_community issues (https://github.com/ansible/ansible/pull/39258) +- nxos_l2_interface - Add aggregate example in nxos_l2_interface module doc (https://github.com/ansible/ansible/pull/39275) +- nxos_snmp_host - Fix for nxos_snmp_host issues (https://github.com/ansible/ansible/pull/39642) +- nxos_snmp_traps - Fix nxos_snmp_traps issues (https://github.com/ansible/ansible/pull/39444) diff --git a/lib/ansible/module_utils/network/eos/eos.py b/lib/ansible/module_utils/network/eos/eos.py index d254ea71d72..22bf86f6ee1 100644 --- a/lib/ansible/module_utils/network/eos/eos.py +++ b/lib/ansible/module_utils/network/eos/eos.py @@ -232,7 +232,7 @@ class Cli: if not all((bool(use_session), self.supports_sessions)): if commit: - return self.configure(self, commands) + return self.configure(commands) else: self._module.warn("EOS can not check config without config session") result = {'changed': True} @@ -420,7 +420,7 @@ class Eapi: if not all((bool(use_session), self.supports_sessions)): if commit: - return self.configure(self, config) + return self.configure(config) else: self._module.warn("EOS can not check config without config session") result = {'changed': True} diff --git a/lib/ansible/modules/network/nxos/nxos_feature.py b/lib/ansible/modules/network/nxos/nxos_feature.py index e5fc994fc0f..d355e908f7d 100644 --- a/lib/ansible/modules/network/nxos/nxos_feature.py +++ b/lib/ansible/modules/network/nxos/nxos_feature.py @@ -72,6 +72,7 @@ commands: import re from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.connection import ConnectionError from ansible.module_utils.network.nxos.nxos import load_config, run_commands from ansible.module_utils.network.nxos.nxos import get_capabilities, nxos_argument_spec @@ -130,8 +131,13 @@ def validate_feature(module, mode='show'): how they are configured''' feature = module.params['feature'] - info = get_capabilities(module).get('device_info', {}) - os_version = info.get('network_os_version', '') + + try: + info = get_capabilities(module) + device_info = info.get('device_info', {}) + os_version = device_info.get('network_os_version', '') + except ConnectionError: + os_version = '' if '8.1' in os_version: feature_to_be_mapped = { diff --git a/lib/ansible/modules/network/nxos/nxos_interface.py b/lib/ansible/modules/network/nxos/nxos_interface.py index d68d3730a49..1cfdc5b9246 100644 --- a/lib/ansible/modules/network/nxos/nxos_interface.py +++ b/lib/ansible/modules/network/nxos/nxos_interface.py @@ -616,15 +616,17 @@ def map_config_to_obj(want, module): command = 'show run interface {0}'.format(obj['name']) body = execute_show_command(command, module)[0] - if 'speed' in body: - obj['speed'] = re.search(r'speed (\d+)', body).group(1) - else: + speed_match = re.search(r'speed (\d+)', body) + if speed_match is None: obj['speed'] = 'auto' - - if 'duplex' in body: - obj['duplex'] = re.search(r'duplex (\S+)', body).group(1) else: + obj['speed'] = speed_match.group(1) + + duplex_match = re.search(r'duplex (\S+)', body) + if duplex_match is None: obj['duplex'] = 'auto' + else: + obj['duplex'] = duplex_match.group(1) if 'ip forward' in body: obj['ip_forward'] = 'enable' diff --git a/lib/ansible/modules/network/nxos/nxos_l2_interface.py b/lib/ansible/modules/network/nxos/nxos_l2_interface.py index d7a9add776b..bb7ba8892fa 100644 --- a/lib/ansible/modules/network/nxos/nxos_l2_interface.py +++ b/lib/ansible/modules/network/nxos/nxos_l2_interface.py @@ -97,6 +97,13 @@ EXAMPLES = """ mode: trunk trunk_vlans: 51-4094 state: absent + +- name: Aggregate Configure interfaces for access_vlan with aggregate + nxos_l2_interface: + aggregate: + - { name: "Ethernet1/2", access_vlan: 6 } + - { name: "Ethernet1/7", access_vlan: 15 } + mode: access """ RETURN = """ diff --git a/lib/ansible/modules/network/nxos/nxos_ntp.py b/lib/ansible/modules/network/nxos/nxos_ntp.py index 119c48e5393..3ba30576614 100644 --- a/lib/ansible/modules/network/nxos/nxos_ntp.py +++ b/lib/ansible/modules/network/nxos/nxos_ntp.py @@ -25,47 +25,34 @@ options: server: description: - Network address of NTP server. - required: false - default: null peer: description: - Network address of NTP peer. - required: false - default: null key_id: description: - Authentication key identifier to use with - given NTP server or peer. - required: false - default: null + given NTP server or peer or keyword 'default'. prefer: description: - Makes given NTP server or peer the preferred NTP server or peer for the device. - required: false - default: null choices: ['enabled', 'disabled'] vrf_name: description: - Makes the device communicate with the given - NTP server or peer over a specific VRF. - required: false - default: null + NTP server or peer over a specific VRF or + keyword 'default'. source_addr: description: - - Local source address from which NTP messages are sent. - required: false - default: null + - Local source address from which NTP messages are sent + or keyword 'default' source_int: description: - Local source interface from which NTP messages are sent. - Must be fully qualified interface name. - required: false - default: null + Must be fully qualified interface name or keyword 'default' state: description: - Manage the state of the resource. - required: false default: present choices: ['present','absent'] ''' @@ -186,10 +173,12 @@ def get_ntp_peer(module): split_ntp = ntp.splitlines() for peer_line in split_ntp: + if 'access-group' in peer_line: + continue ntp_peer = {} try: peer_address = None - vrf_name = None + vrf_name = 'default' prefer = None key_id = None match_ntp = re.match(ntp_regex, peer_line, re.DOTALL) @@ -261,11 +250,18 @@ def set_ntp_server_peer(peer_type, address, prefer, key_id, vrf_name): def config_ntp(delta, existing): - address = delta.get('address', existing.get('address')) - peer_type = delta.get('peer_type', existing.get('peer_type')) - vrf_name = delta.get('vrf_name', existing.get('vrf_name')) - key_id = delta.get('key_id', existing.get('key_id')) - prefer = delta.get('prefer', existing.get('prefer')) + if (delta.get('address') or delta.get('peer_type') or delta.get('vrf_name') or + delta.get('key_id') or delta.get('prefer')): + address = delta.get('address', existing.get('address')) + peer_type = delta.get('peer_type', existing.get('peer_type')) + key_id = delta.get('key_id', existing.get('key_id')) + prefer = delta.get('prefer', existing.get('prefer')) + vrf_name = delta.get('vrf_name', existing.get('vrf_name')) + if delta.get('key_id') == 'default': + key_id = None + else: + peer_type = None + prefer = None source_type = delta.get('source_type') source = delta.get('source') @@ -281,6 +277,9 @@ def config_ntp(delta, existing): ntp_cmds = [] if peer_type: + if existing.get('peer_type') and existing.get('address'): + ntp_cmds.append('no ntp {0} {1}'.format(existing.get('peer_type'), + existing.get('address'))) ntp_cmds.append(set_ntp_server_peer( peer_type, address, prefer, key_id, vrf_name)) if source: @@ -288,7 +287,11 @@ def config_ntp(delta, existing): existing_source = existing.get('source') if existing_source_type and source_type != existing_source_type: ntp_cmds.append('no ntp {0} {1}'.format(existing_source_type, existing_source)) - ntp_cmds.append('ntp {0} {1}'.format(source_type, source)) + if source == 'default': + if existing_source_type and existing_source: + ntp_cmds.append('no ntp {0} {1}'.format(existing_source_type, existing_source)) + else: + ntp_cmds.append('ntp {0} {1}'.format(source_type, source)) return ntp_cmds @@ -324,6 +327,7 @@ def main(): source_addr = module.params['source_addr'] source_int = module.params['source_int'] state = module.params['state'] + if source_int is not None: source_int = source_int.lower() @@ -365,6 +369,9 @@ def main(): if state == 'present': delta = dict(set(proposed.items()).difference(existing.items())) + if delta.get('key_id') and delta.get('key_id') == 'default': + if not existing.get('key_id'): + delta.pop('key_id') if delta: command = config_ntp(delta, existing) if command: diff --git a/lib/ansible/modules/network/nxos/nxos_snmp_community.py b/lib/ansible/modules/network/nxos/nxos_snmp_community.py index afaba96a549..b0c4a0cfb13 100644 --- a/lib/ansible/modules/network/nxos/nxos_snmp_community.py +++ b/lib/ansible/modules/network/nxos/nxos_snmp_community.py @@ -42,23 +42,16 @@ options: access: description: - Access type for community. - required: false - default: null choices: ['ro','rw'] group: description: - Group to which the community belongs. - required: false - default: null acl: description: - - ACL name to filter snmp requests. - required: false - default: 1 + - ACL name to filter snmp requests or keyword 'default'. state: description: - Manage the state of the resource. - required: true default: present choices: ['present','absent'] ''' @@ -156,7 +149,8 @@ def get_snmp_community(module, name): def config_snmp_community(delta, community): CMDS = { 'group': 'snmp-server community {0} group {group}', - 'acl': 'snmp-server community {0} use-acl {acl}' + 'acl': 'snmp-server community {0} use-acl {acl}', + 'no_acl': 'no snmp-server community {0} use-acl {no_acl}' } commands = [] for k, v in delta.items(): @@ -209,6 +203,10 @@ def main(): args = dict(group=group, acl=acl) proposed = dict((k, v) for k, v in args.items() if v is not None) delta = dict(set(proposed.items()).difference(existing.items())) + if delta.get('acl') == 'default': + delta.pop('acl') + if existing.get('acl'): + delta['no_acl'] = existing.get('acl') commands = [] diff --git a/lib/ansible/modules/network/nxos/nxos_snmp_host.py b/lib/ansible/modules/network/nxos/nxos_snmp_host.py index df2f4bf40f1..acbbd65088b 100644 --- a/lib/ansible/modules/network/nxos/nxos_snmp_host.py +++ b/lib/ansible/modules/network/nxos/nxos_snmp_host.py @@ -42,10 +42,8 @@ options: required: true version: description: - - SNMP version. - required: false - default: v2c - choices: ['v2c', 'v3'] + - SNMP version. If this is not specified, v1 is used. + choices: ['v1', 'v2c', 'v3'] v3: description: - Use this when verion is v3. SNMPv3 Security level. @@ -53,38 +51,36 @@ options: community: description: - Community string or v3 username. - required: false - default: null udp: description: - UDP port number (0-65535). - required: false - default: null + default: 162 snmp_type: description: - - type of message to send to host. - required: false - default: trap + - type of message to send to host. If this is not + specified, trap type is used. choices: ['trap', 'inform'] vrf: description: - VRF to use to source traffic to source. - required: false - default: null + If state = absent, the vrf is removed. vrf_filter: description: - Name of VRF to filter. - required: false - default: null + If state = absent, the vrf is removed from the filter. src_intf: description: - - Source interface. - required: false - default: null + - Source interface. Must be fully qualified interface name. + If state = absent, the interface is removed. state: description: - - Manage the state of the resource. - required: true + - Manage the state of the resource. If state = present, the + host is added to the configuration. If only vrf and/or + vrf_filter and/or src_intf are given, they will be added to + the existing host configuration. If state = absent, the + host is removed if community parameter is given. It is possible + to remove only vrf and/or src_int and/or vrf_filter + by providing only those parameters and no community parameter. default: present choices: ['present','absent'] ''' @@ -144,7 +140,7 @@ def flatten_list(command_lists): return flat_command_list -def get_snmp_host(host, module): +def get_snmp_host(host, udp, module): body = execute_show_command('show snmp host', module) host_map = { @@ -173,7 +169,7 @@ def get_snmp_host(host, module): resource_table = [resource_table] for each in resource_table: - key = str(each['host']) + key = str(each['host']) + '_' + str(each['port']).strip() src = each.get('src_intf') host_resource = apply_key_map(host_map, each) @@ -201,7 +197,7 @@ def get_snmp_host(host, module): resource_table = [resource_table] for each in resource_table: - key = str(each['address']) + key = str(each['address']) + '_' + str(each['port']).strip() src = each.get('src_intf') host_resource = apply_key_map(host_map_5k, each) @@ -210,22 +206,23 @@ def get_snmp_host(host, module): if re.search(r'interface:', src): host_resource['src_intf'] = src.split(':')[1].strip() + vrf = each.get('use_vrf_name') + if vrf: + host_resource['vrf'] = vrf.strip() + vrf_filt = each.get('TABLE_filter_vrf') if vrf_filt: vrf_filter = vrf_filt['ROW_filter_vrf']['filter_vrf_name'].split(',') filters = [vrf.strip() for vrf in vrf_filter] host_resource['vrf_filter'] = filters - vrf = each.get('use_vrf_name') - if vrf: - host_resource['vrf'] = vrf.strip() resource[key] = host_resource except (KeyError, AttributeError, TypeError): return resource except (AttributeError, TypeError): return resource - find = resource.get(host) + find = resource.get(host + '_' + udp) if find: fix_find = {} @@ -239,24 +236,54 @@ def get_snmp_host(host, module): return {} -def remove_snmp_host(host, existing): +def remove_snmp_host(host, udp, existing): commands = [] if existing['version'] == 'v3': existing['version'] = '3' command = 'no snmp-server host {0} {snmp_type} version \ - {version} {v3} {community}'.format(host, **existing) + {version} {v3} {community} udp-port {1}'.format(host, udp, **existing) elif existing['version'] == 'v2c': existing['version'] = '2c' command = 'no snmp-server host {0} {snmp_type} version \ - {version} {community}'.format(host, **existing) + {version} {community} udp-port {1}'.format(host, udp, **existing) + + elif existing['version'] == 'v1': + existing['version'] = '1' + command = 'no snmp-server host {0} {snmp_type} version \ + {version} {community} udp-port {1}'.format(host, udp, **existing) if command: commands.append(command) return commands -def config_snmp_host(delta, proposed, existing, module): +def remove_vrf(host, udp, proposed, existing): + commands = [] + if existing.get('vrf'): + commands.append('no snmp-server host {0} use-vrf \ + {1} udp-port {2}'.format(host, proposed.get('vrf'), udp)) + return commands + + +def remove_filter(host, udp, proposed, existing): + commands = [] + if existing.get('vrf_filter'): + if proposed.get('vrf_filter') in existing.get('vrf_filter'): + commands.append('no snmp-server host {0} filter-vrf \ + {1} udp-port {2}'.format(host, proposed.get('vrf_filter'), udp)) + return commands + + +def remove_src(host, udp, proposed, existing): + commands = [] + if existing.get('src_intf'): + commands.append('no snmp-server host {0} source-interface \ + {1} udp-port {2}'.format(host, proposed.get('src_intf'), udp)) + return commands + + +def config_snmp_host(delta, udp, proposed, existing, module): commands = [] command_builder = [] host = proposed['snmp_host'] @@ -275,7 +302,9 @@ def config_snmp_host(delta, proposed, existing, module): version = version or existing.get('version') if version: - if version == 'v2c': + if version == 'v1': + vn = '1' + elif version == 'v2c': vn = '2c' elif version == 'v3': vn = '3' @@ -291,21 +320,23 @@ def config_snmp_host(delta, proposed, existing, module): community_string = community or existing.get('community') command_builder.append(community_string) + udp_string = ' udp-port {0}'.format(udp) + command_builder.append(udp_string) + cmd = ' '.join(command_builder) commands.append(cmd) CMDS = { - 'vrf_filter': 'snmp-server host {0} filter-vrf {vrf_filter}', - 'vrf': 'snmp-server host {0} use-vrf {vrf}', - 'udp': 'snmp-server host {0} udp-port {udp}', - 'src_intf': 'snmp-server host {0} source-interface {src_intf}' + 'vrf_filter': 'snmp-server host {0} filter-vrf {vrf_filter} udp-port {1}', + 'vrf': 'snmp-server host {0} use-vrf {vrf} udp-port {1}', + 'src_intf': 'snmp-server host {0} source-interface {src_intf} udp-port {1}' } for key in delta: command = CMDS.get(key) if command: - cmd = command.format(host, **delta) + cmd = command.format(host, udp, **delta) commands.append(cmd) return commands @@ -314,13 +345,13 @@ def main(): argument_spec = dict( snmp_host=dict(required=True, type='str'), community=dict(type='str'), - udp=dict(type='str'), - version=dict(choices=['v2c', 'v3'], default='v2c'), + udp=dict(type='str', default='162'), + version=dict(choices=['v1', 'v2c', 'v3']), src_intf=dict(type='str'), v3=dict(choices=['noauth', 'auth', 'priv']), vrf_filter=dict(type='str'), vrf=dict(type='str'), - snmp_type=dict(choices=['trap', 'inform'], default='trap'), + snmp_type=dict(choices=['trap', 'inform']), state=dict(choices=['absent', 'present'], default='present'), ) @@ -343,17 +374,35 @@ def main(): snmp_type = module.params['snmp_type'] state = module.params['state'] - if snmp_type == 'inform' and version != 'v3': - module.fail_json(msg='inform requires snmp v3') + existing = get_snmp_host(snmp_host, udp, module) + + if version is None: + if existing: + version = existing.get('version') + else: + version = 'v1' + + if snmp_type is None: + if existing: + snmp_type = existing.get('snmp_type') + else: + snmp_type = 'trap' - if version == 'v2c' and v3: + if v3 is None: + if version == 'v3' and existing: + v3 = existing.get('v3') + + if snmp_type == 'inform' and version == 'v1': + module.fail_json(msg='inform requires snmp v2c or v3') + + if (version == 'v1' or version == 'v2c') and v3: module.fail_json(msg='param: "v3" should not be used when ' - 'using version v2c') + 'using version v1 or v2c') - if not any([vrf_filter, vrf, udp, src_intf]): - if not all([snmp_type, version, community]): + if not any([vrf_filter, vrf, src_intf]): + if not all([snmp_type, version, community, udp]): module.fail_json(msg='when not configuring options like ' - 'vrf_filter, vrf, udp, and src_intf,' + 'vrf_filter, vrf, and src_intf,' 'the following params are required: ' 'type, version, community') @@ -361,8 +410,6 @@ def main(): module.fail_json(msg='when using version=v3, the param v3 ' '(options: auth, noauth, priv) is also required') - existing = get_snmp_host(snmp_host, module) - # existing returns the list of vrfs configured for a given host # checking to see if the proposed is in the list store = existing.get('vrf_filter') @@ -373,27 +420,34 @@ def main(): existing['vrf_filter'] = vrf_filter commands = [] + args = dict( + community=community, + snmp_host=snmp_host, + udp=udp, + version=version, + src_intf=src_intf, + vrf_filter=vrf_filter, + v3=v3, + vrf=vrf, + snmp_type=snmp_type + ) + proposed = dict((k, v) for k, v in args.items() if v is not None) + if state == 'absent' and existing: - command = remove_snmp_host(snmp_host, existing) - commands.append(command) + if proposed.get('community'): + commands.append(remove_snmp_host(snmp_host, udp, existing)) + else: + if proposed.get('src_intf'): + commands.append(remove_src(snmp_host, udp, proposed, existing)) + if proposed.get('vrf'): + commands.append(remove_vrf(snmp_host, udp, proposed, existing)) + if proposed.get('vrf_filter'): + commands.append(remove_filter(snmp_host, udp, proposed, existing)) elif state == 'present': - args = dict( - community=community, - snmp_host=snmp_host, - udp=udp, - version=version, - src_intf=src_intf, - vrf_filter=vrf_filter, - v3=v3, - vrf=vrf, - snmp_type=snmp_type - ) - proposed = dict((k, v) for k, v in args.items() if v is not None) - delta = dict(set(proposed.items()).difference(existing.items())) if delta: - command = config_snmp_host(delta, proposed, existing, module) + command = config_snmp_host(delta, udp, proposed, existing, module) commands.append(command) cmds = flatten_list(commands) diff --git a/lib/ansible/modules/network/nxos/nxos_snmp_traps.py b/lib/ansible/modules/network/nxos/nxos_snmp_traps.py index 146614be7ec..d42eca87bed 100644 --- a/lib/ansible/modules/network/nxos/nxos_snmp_traps.py +++ b/lib/ansible/modules/network/nxos/nxos_snmp_traps.py @@ -42,9 +42,10 @@ options: description: - Case sensitive group. required: true - choices: ['aaa', 'bridge', 'callhome', 'cfs', 'config', 'entity', - 'feature-control', 'hsrp', 'license', 'link', 'lldp', 'ospf', 'pim', - 'rf', 'rmon', 'snmp', 'storm-control', 'stpx', 'sysmgr', 'system', + choices: ['aaa', 'bfd', 'bgp', 'bridge', 'callhome', 'cfs', 'config', + 'eigrp', 'entity', 'feature-control', 'generic', 'hsrp', 'license', + 'link', 'lldp', 'mmode', 'ospf', 'pim', 'rf', 'rmon', 'snmp', + 'storm-control', 'stpx', 'switchfabric', 'syslog', 'sysmgr', 'system', 'upgrade', 'vtp', 'all'] state: description: @@ -83,25 +84,12 @@ from ansible.module_utils.basic import AnsibleModule def execute_show_command(command, module): command = { 'command': command, - 'output': 'json', + 'output': 'text', } return run_commands(module, command) -def apply_key_map(key_map, table): - new_dict = {} - for key, value in table.items(): - new_key = key_map.get(key) - if new_key: - value = table.get(key) - if value: - new_dict[new_key] = str(value) - else: - new_dict[new_key] = value - return new_dict - - def flatten_list(command_lists): flat_command_list = [] for command in command_lists: @@ -113,61 +101,44 @@ def flatten_list(command_lists): def get_snmp_traps(group, module): - body = execute_show_command('show snmp trap', module) - - trap_key = { - 'description': 'trap', - 'isEnabled': 'enabled' - } - - trap_key_5k = { - 'trap': 'trap', - 'enabled': 'enabled' - } + body = execute_show_command('show run snmp all', module)[0].split('\n') resource = {} - feature_list = ['aaa', 'bridge', 'callhome', 'cfs', 'config', - 'entity', 'feature-control', 'hsrp', 'license', - 'link', 'lldp', 'ospf', 'pim', 'rf', 'rmon', - 'snmp', 'storm-control', 'stpx', 'sysmgr', - 'system', 'upgrade', 'vtp'] - try: - resource_table = body[0]['TABLE_snmp_trap']['ROW_snmp_trap'] - - for each_feature in feature_list: - resource[each_feature] = [] - - for each_resource in resource_table: - key = str(each_resource['trap_type']) - mapped_trap = apply_key_map(trap_key, each_resource) - - if key != 'Generic': - resource[key].append(mapped_trap) - except KeyError: - try: - resource_table = body[0]['TABLE_mib']['ROW_mib'] - - for each_feature in feature_list: - resource[each_feature] = [] - - for each_resource in resource_table: - key = str(each_resource['mib']) - each_resource = each_resource['TABLE_trap']['ROW_trap'] - mapped_trap = apply_key_map(trap_key_5k, each_resource) - - if key != 'Generic': - resource[key].append(mapped_trap) - except (KeyError, AttributeError): - return resource - except AttributeError: - return resource + feature_list = ['aaa', 'bfd', 'bgp', 'bridge', 'callhome', 'cfs', 'config', + 'eigrp', 'entity', 'feature-control', 'generic', 'hsrp', + 'license', 'link', 'lldp', 'mmode', 'ospf', 'pim', + 'rf', 'rmon', 'snmp', 'storm-control', 'stpx', + 'switchfabric', 'syslog', 'sysmgr', 'system', 'upgrade', + 'vtp'] + for each in feature_list: + for line in body: + if each == 'ospf': + # ospf behaves differently when routers are present + if 'snmp-server enable traps ospf' == line: + resource[each] = True + break + else: + if 'enable traps {0}'.format(each) in line: + if 'no ' in line: + resource[each] = False + break + else: + resource[each] = True + + for each in feature_list: + if resource.get(each) is None: + # on some platforms, the 'no' cmd does not + # show up and so check if the feature is enabled + body = execute_show_command('show run | inc feature', module)[0] + if 'feature {0}'.format(each) in body: + resource[each] = False find = resource.get(group, None) if group == 'all'.lower(): return resource - elif find: - trap_resource = {group: resource[group]} + elif find is not None: + trap_resource = {group: find} return trap_resource else: # if 'find' is None, it means that 'group' is a @@ -183,26 +154,22 @@ def get_trap_commands(group, state, existing, module): if group == 'all': if state == 'disabled': for feature in existing: - trap_commands = ['no snmp-server enable traps {0}'.format(feature) for - trap in existing[feature] if trap['enabled'] == 'Yes'] - trap_commands = list(set(trap_commands)) - commands.append(trap_commands) + if existing[feature]: + trap_command = 'no snmp-server enable traps {0}'.format(feature) + commands.append(trap_command) elif state == 'enabled': for feature in existing: - trap_commands = ['snmp-server enable traps {0}'.format(feature) for - trap in existing[feature] if trap['enabled'] == 'No'] - trap_commands = list(set(trap_commands)) - commands.append(trap_commands) + if existing[feature] is False: + trap_command = 'snmp-server enable traps {0}'.format(feature) + commands.append(trap_command) else: if group in existing: - for each_trap in existing[group]: - check = each_trap['enabled'] - if check.lower() == 'yes': - enabled = True - if check.lower() == 'no': - disabled = True + if existing[group]: + enabled = True + else: + disabled = True if state == 'disabled' and enabled: commands.append(['no snmp-server enable traps {0}'.format(group)]) @@ -218,11 +185,12 @@ def get_trap_commands(group, state, existing, module): def main(): argument_spec = dict( state=dict(choices=['enabled', 'disabled'], default='enabled'), - group=dict(choices=['aaa', 'bridge', 'callhome', 'cfs', 'config', - 'entity', 'feature-control', 'hsrp', - 'license', 'link', 'lldp', 'ospf', 'pim', 'rf', - 'rmon', 'snmp', 'storm-control', 'stpx', - 'sysmgr', 'system', 'upgrade', 'vtp', 'all'], + group=dict(choices=['aaa', 'bfd', 'bgp', 'bridge', 'callhome', 'cfs', 'config', + 'eigrp', 'entity', 'feature-control', 'generic', 'hsrp', + 'license', 'link', 'lldp', 'mmode', 'ospf', 'pim', + 'rf', 'rmon', 'snmp', 'storm-control', 'stpx', + 'switchfabric', 'syslog', 'sysmgr', 'system', 'upgrade', + 'vtp', 'all'], required=True), ) diff --git a/test/integration/targets/nxos_ntp/tests/common/sanity.yaml b/test/integration/targets/nxos_ntp/tests/common/sanity.yaml index 0ac117513dd..838359a7c87 100644 --- a/test/integration/targets/nxos_ntp/tests/common/sanity.yaml +++ b/test/integration/targets/nxos_ntp/tests/common/sanity.yaml @@ -39,6 +39,25 @@ that: - "result.changed == false" + - name: Configure ntp with some defaults + nxos_ntp: &config1 + peer: 1.2.3.4 + key_id: default + prefer: enabled + vrf_name: default + source_addr: default + state: present + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_ntp: *config1 + register: result + + - assert: *false + - name: Remove ntp config nxos_ntp: *remove register: result @@ -51,6 +70,50 @@ - assert: *false + - name: Configure ntp again + nxos_ntp: &config2 + source_int: Ethernet1/3 + peer: 1.2.3.4 + prefer: enabled + state: present + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_ntp: *config2 + register: result + + - assert: *false + + - name: Remove source interface + nxos_ntp: &config3 + source_int: default + state: present + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_ntp: *config3 + register: result + + - assert: *false + + - name: Remove ntp + nxos_ntp: *remove + register: result + + - assert: *true + + - name: Remove Idempotence Check + nxos_ntp: *remove + register: result + + - assert: *false + always: - name: Remove ntp config nxos_ntp: *remove diff --git a/test/integration/targets/nxos_snmp_community/tests/common/sanity.yaml b/test/integration/targets/nxos_snmp_community/tests/common/sanity.yaml index 7676ba3fdd4..43be9f619fd 100644 --- a/test/integration/targets/nxos_snmp_community/tests/common/sanity.yaml +++ b/test/integration/targets/nxos_snmp_community/tests/common/sanity.yaml @@ -17,7 +17,6 @@ nxos_snmp_community: &config community: TESTING7 group: network-operator - #access: ro state: present provider: "{{ connection }}" register: result @@ -34,6 +33,22 @@ that: - "result.changed == false" + - name: Change snmp_community group + nxos_snmp_community: &chg + community: TESTING7 + group: network-admin + state: present + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_community: *chg + register: result + + - assert: *false + - name: Remove snmp_community nxos_snmp_community: *remove register: result @@ -91,6 +106,40 @@ - assert: *false + - name: Change acl + nxos_snmp_community: &chgacl + community: TESTING7 + access: rw + acl: new_acl + state: present + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_community: *chgacl + register: result + + - assert: *false + + - name: Remove acl + nxos_snmp_community: &removeacl + community: TESTING7 + access: rw + acl: default + state: present + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_community: *removeacl + register: result + + - assert: *false + always: - name: Cleanup nxos_snmp_community: *remove diff --git a/test/integration/targets/nxos_snmp_contact/defaults/main.yaml b/test/integration/targets/nxos_snmp_contact/defaults/main.yaml new file mode 100644 index 00000000000..5f709c5aac1 --- /dev/null +++ b/test/integration/targets/nxos_snmp_contact/defaults/main.yaml @@ -0,0 +1,2 @@ +--- +testcase: "*" diff --git a/test/integration/targets/nxos_snmp_contact/meta/main.yml b/test/integration/targets/nxos_snmp_contact/meta/main.yml new file mode 100644 index 00000000000..ae741cbdc71 --- /dev/null +++ b/test/integration/targets/nxos_snmp_contact/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - prepare_nxos_tests diff --git a/test/integration/targets/nxos_snmp_contact/tasks/cli.yaml b/test/integration/targets/nxos_snmp_contact/tasks/cli.yaml new file mode 100644 index 00000000000..edbff7dfafb --- /dev/null +++ b/test/integration/targets/nxos_snmp_contact/tasks/cli.yaml @@ -0,0 +1,33 @@ +--- +- name: collect common cli test cases + find: + paths: "{{ role_path }}/tests/common" + patterns: "{{ testcase }}.yaml" + connection: local + register: test_cases + +- name: collect cli test cases + find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + connection: local + register: cli_cases + +- set_fact: + test_cases: + files: "{{ test_cases.files }} + {{ cli_cases.files }}" + +- name: set test_items + set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: run test cases (connection=network_cli) + include: "{{ test_case_to_run }} ansible_connection=network_cli connection={}" + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + +- name: run test case (connection=local) + include: "{{ test_case_to_run }} ansible_connection=local connection={{ cli }}" + with_first_found: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/test/integration/targets/nxos_snmp_contact/tasks/main.yaml b/test/integration/targets/nxos_snmp_contact/tasks/main.yaml new file mode 100644 index 00000000000..4b0f8c64d90 --- /dev/null +++ b/test/integration/targets/nxos_snmp_contact/tasks/main.yaml @@ -0,0 +1,3 @@ +--- +- { include: cli.yaml, tags: ['cli'] } +- { include: nxapi.yaml, tags: ['nxapi'] } diff --git a/test/integration/targets/nxos_snmp_contact/tasks/nxapi.yaml b/test/integration/targets/nxos_snmp_contact/tasks/nxapi.yaml new file mode 100644 index 00000000000..68e96a29420 --- /dev/null +++ b/test/integration/targets/nxos_snmp_contact/tasks/nxapi.yaml @@ -0,0 +1,27 @@ +--- +- name: collect common nxapi test cases + find: + paths: "{{ role_path }}/tests/common" + patterns: "{{ testcase }}.yaml" + connection: local + register: test_cases + +- name: collect nxapi test cases + find: + paths: "{{ role_path }}/tests/nxapi" + patterns: "{{ testcase }}.yaml" + connection: local + register: nxapi_cases + +- set_fact: + test_cases: + files: "{{ test_cases.files }} + {{ nxapi_cases.files }}" + +- name: set test_items + set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: run test cases (connection=local) + include: "{{ test_case_to_run }} ansible_connection=local connection={{ nxapi }}" + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/test/integration/targets/nxos_snmp_contact/tests/common/sanity.yaml b/test/integration/targets/nxos_snmp_contact/tests/common/sanity.yaml new file mode 100644 index 00000000000..b7265f21bd0 --- /dev/null +++ b/test/integration/targets/nxos_snmp_contact/tests/common/sanity.yaml @@ -0,0 +1,64 @@ +--- +- debug: msg="START connection={{ ansible_connection }} nxos_snmp_community sanity test" +- debug: msg="Using provider={{ connection.transport }}" + when: ansible_connection == "local" + +- name: Setup - Remove snmp_contact if configured + nxos_snmp_contact: &remove + contact: Test + state: absent + provider: "{{ connection }}" + +- block: + + - name: Configure snmp contact + nxos_snmp_contact: &config + contact: Testing + state: present + provider: "{{ connection }}" + register: result + + - assert: &true + that: + - "result.changed == true" + + - name: Idempotence Check + nxos_snmp_contact: *config + register: result + + - assert: &false + that: + - "result.changed == false" + + - name: Change snmp contact + nxos_snmp_contact: &config1 + contact: Test + state: present + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_contact: *config1 + register: result + + - assert: *false + + - name: Remove snmp contact + nxos_snmp_contact: *remove + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_contact: *remove + register: result + + - assert: *false + + always: + - name: Cleanup + nxos_snmp_contact: *remove + + - debug: msg="END connection={{ ansible_connection }} nxos_snmp_community sanity test" diff --git a/test/integration/targets/nxos_snmp_host/tests/common/sanity_snmp_v1_trap.yaml b/test/integration/targets/nxos_snmp_host/tests/common/sanity_snmp_v1_trap.yaml new file mode 100644 index 00000000000..e7de1ef55fc --- /dev/null +++ b/test/integration/targets/nxos_snmp_host/tests/common/sanity_snmp_v1_trap.yaml @@ -0,0 +1,129 @@ +--- +- set_fact: snmp_type="trap" +- set_fact: snmp_version="v1" + +- debug: msg="START connection={{ ansible_connection }} nxos_snmp_host {{ snmp_type }} {{ snmp_version }} sanity test" +- debug: msg="Using provider={{ connection.transport }}" + when: ansible_connection == "local" + +# Select interface for test +- set_fact: intname="{{ nxos_int1 }}" + when: not (platform is match("N5K")) + +- name: Setup - Remove snmp_host if configured + nxos_snmp_host: &remove + snmp_host: 3.3.3.3 + community: TESTING + version: "{{ snmp_version }}" + snmp_type: "{{ snmp_type }}" + vrf: management + vrf_filter: management + src_intf: "{{ intname|default(omit) }}" + udp: 222 + state: absent + provider: "{{ connection }}" + ignore_errors: yes + +- block: + + - name: Configure snmp host + nxos_snmp_host: &config + snmp_host: 3.3.3.3 + community: TESTING + version: "{{ snmp_version }}" + snmp_type: "{{ snmp_type }}" + vrf: management + vrf_filter: management + src_intf: "{{ intname|default(omit) }}" + udp: 222 + state: present + provider: "{{ connection }}" + register: result + + - assert: &true + that: + - "result.changed == true" + + - name: Idempotence Check + nxos_snmp_host: *config + register: result + + - assert: &false + that: + - "result.changed == false" + + - block: + - name: Add another vrf to filter + nxos_snmp_host: &config1 + snmp_host: 3.3.3.3 + vrf_filter: default + udp: 222 + state: present + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_host: *config1 + register: result + + - assert: *false + when: not (platform is match('N35|N5K')) + + - name: remove some configuration + nxos_snmp_host: &rem1 + snmp_host: 3.3.3.3 + udp: 222 + src_intf: "{{ intname|default(omit) }}" + vrf: management + vrf_filter: management + state: absent + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_host: *rem1 + register: result + + - assert: *false + + - block: + - name: remove some more configuration + nxos_snmp_host: &rem2 + snmp_host: 3.3.3.3 + udp: 222 + vrf_filter: default + state: absent + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_host: *rem2 + register: result + + - assert: *false + when: not (platform is match('N35|N5K')) + + + - name: Cleanup + nxos_snmp_host: *remove + register: result + + - assert: *true + + - name: Cleanup Idempotence + nxos_snmp_host: *remove + register: result + + - assert: *false + + always: + - name: Cleanup + nxos_snmp_host: *remove + + - debug: msg="END connection={{ ansible_connection }} nxos_snmp_host {{ snmp_type }} {{ snmp_version }} sanity test" diff --git a/test/integration/targets/nxos_snmp_host/tests/common/sanity_snmp_v2_trap.yaml b/test/integration/targets/nxos_snmp_host/tests/common/sanity_snmp_v2_inform.yaml similarity index 51% rename from test/integration/targets/nxos_snmp_host/tests/common/sanity_snmp_v2_trap.yaml rename to test/integration/targets/nxos_snmp_host/tests/common/sanity_snmp_v2_inform.yaml index 16c1843574d..7c7e100077b 100644 --- a/test/integration/targets/nxos_snmp_host/tests/common/sanity_snmp_v2_trap.yaml +++ b/test/integration/targets/nxos_snmp_host/tests/common/sanity_snmp_v2_inform.yaml @@ -1,8 +1,8 @@ --- -- set_fact: snmp_type="trap" +- set_fact: snmp_type="inform" - set_fact: snmp_version="v2c" -- debug: msg="START connection={{ ansible_connection }} nxos_snmp_host {{ snmp_type }} {{ snmp_version }}sanity test" +- debug: msg="START connection={{ ansible_connection }} nxos_snmp_host {{ snmp_type }} {{ snmp_version }} sanity test" - debug: msg="Using provider={{ connection.transport }}" when: ansible_connection == "local" @@ -19,6 +19,7 @@ vrf: management vrf_filter: management src_intf: "{{ intname|default(omit) }}" + udp: 222 state: absent provider: "{{ connection }}" ignore_errors: yes @@ -34,6 +35,7 @@ vrf: management vrf_filter: management src_intf: "{{ intname|default(omit) }}" + udp: 222 state: present provider: "{{ connection }}" register: result @@ -50,7 +52,63 @@ that: - "result.changed == false" - always: + - block: + - name: Add another vrf to filter + nxos_snmp_host: &config1 + snmp_host: 3.3.3.3 + vrf_filter: default + udp: 222 + state: present + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_host: *config1 + register: result + + - assert: *false + when: not (platform is match('N35|N5K')) + + - name: remove some configuration + nxos_snmp_host: &rem1 + snmp_host: 3.3.3.3 + udp: 222 + src_intf: "{{ intname|default(omit) }}" + vrf: management + vrf_filter: management + state: absent + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_host: *rem1 + register: result + + - assert: *false + + - block: + - name: remove some more configuration + nxos_snmp_host: &rem2 + snmp_host: 3.3.3.3 + udp: 222 + vrf_filter: default + state: absent + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_host: *rem2 + register: result + + - assert: *false + when: not (platform is match('N35|N5K')) + - name: Cleanup nxos_snmp_host: *remove register: result @@ -63,4 +121,8 @@ - assert: *false - - debug: msg="END connection={{ ansible_connection }} nxos_snmp_host {{ snmp_type }} {{ snmp_version }}sanity test" + always: + - name: Cleanup + nxos_snmp_host: *remove + + - debug: msg="END connection={{ ansible_connection }} nxos_snmp_host {{ snmp_type }} {{ snmp_version }} sanity test" diff --git a/test/integration/targets/nxos_snmp_host/tests/common/sanity_snmp_v3_inform.yaml b/test/integration/targets/nxos_snmp_host/tests/common/sanity_snmp_v3_inform.yaml index 84b41a2222c..9a481e57701 100644 --- a/test/integration/targets/nxos_snmp_host/tests/common/sanity_snmp_v3_inform.yaml +++ b/test/integration/targets/nxos_snmp_host/tests/common/sanity_snmp_v3_inform.yaml @@ -3,7 +3,7 @@ - set_fact: snmp_version="v3" - set_fact: snmp_auth="noauth" -- debug: msg="START connection={{ ansible_connection }} nxos_snmp_host {{ snmp_type }} {{ snmp_version }}sanity test" +- debug: msg="START connection={{ ansible_connection }} nxos_snmp_host {{ snmp_type }} {{ snmp_version }} sanity test" - debug: msg="Using provider={{ connection.transport }}" when: ansible_connection == "local" @@ -11,13 +11,17 @@ - set_fact: intname="{{ nxos_int1 }}" when: not (platform is match("N5K")) +- set_fact: run="true" +- set_fact: run="false" + when: platform is match('N35') + - name: Setup - Remove snmp_host if configured nxos_snmp_host: &remove snmp_host: 3.3.3.3 community: TESTING - v3: "{{ snmp_auth|default(omit) }}" version: "{{ snmp_version }}" snmp_type: "{{ snmp_type }}" + v3: "{{ snmp_auth }}" vrf: management vrf_filter: management src_intf: "{{ intname|default(omit) }}" @@ -53,9 +57,60 @@ that: - "result.changed == false" - when: not (platform is match('N35')) + - block: + - name: Add another vrf to filter + nxos_snmp_host: &config1 + snmp_host: 3.3.3.3 + vrf_filter: default + state: present + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_host: *config1 + register: result + + - assert: *false + when: not (platform is match('N35|N5K')) + + - name: remove some configuration + nxos_snmp_host: &rem1 + snmp_host: 3.3.3.3 + src_intf: "{{ intname|default(omit) }}" + vrf: management + vrf_filter: management + state: absent + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_host: *rem1 + register: result + + - assert: *false + + - block: + - name: remove some more configuration + nxos_snmp_host: &rem2 + snmp_host: 3.3.3.3 + vrf_filter: default + state: absent + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_host: *rem2 + register: result + + - assert: *false + when: not (platform is match('N35|N5K')) - always: - name: Cleanup nxos_snmp_host: *remove register: result @@ -68,4 +123,11 @@ - assert: *false - - debug: msg="END connection={{ ansible_connection }} nxos_snmp_host {{ snmp_type }} {{ snmp_version }}sanity test" + when: run + + always: + - name: Cleanup + nxos_snmp_host: *remove + register: result + + - debug: msg="END connection={{ ansible_connection }} nxos_snmp_host {{ snmp_type }} {{ snmp_version }} sanity test" diff --git a/test/integration/targets/nxos_snmp_host/tests/common/sanity_snmp_v3_trap.yaml b/test/integration/targets/nxos_snmp_host/tests/common/sanity_snmp_v3_trap.yaml index 0d92d3b94d6..2262a6637f0 100644 --- a/test/integration/targets/nxos_snmp_host/tests/common/sanity_snmp_v3_trap.yaml +++ b/test/integration/targets/nxos_snmp_host/tests/common/sanity_snmp_v3_trap.yaml @@ -1,21 +1,27 @@ --- - set_fact: snmp_type="trap" - set_fact: snmp_version="v3" -- set_fact: snmp_auth="noauth" +- set_fact: snmp_auth="priv" -- debug: msg="START connection={{ ansible_connection }} nxos_snmp_host {{ snmp_type }} {{ snmp_version }}sanity test" +- debug: msg="START connection={{ ansible_connection }} nxos_snmp_host {{ snmp_type }} {{ snmp_version }} sanity test" - debug: msg="Using provider={{ connection.transport }}" when: ansible_connection == "local" +# Select interface for test +- set_fact: intname="{{ nxos_int1 }}" + when: not (platform is match("N5K")) + - name: Setup - Remove snmp_host if configured nxos_snmp_host: &remove snmp_host: 3.3.3.3 community: TESTING + udp: 222 v3: "{{ snmp_auth|default(omit) }}" version: "{{ snmp_version }}" snmp_type: "{{ snmp_type }}" vrf: management vrf_filter: management + src_intf: "{{ intname|default(omit) }}" state: absent provider: "{{ connection }}" ignore_errors: yes @@ -26,11 +32,13 @@ nxos_snmp_host: &config snmp_host: 3.3.3.3 community: TESTING + udp: 222 v3: "{{ snmp_auth|default(omit) }}" version: "{{ snmp_version }}" snmp_type: "{{ snmp_type }}" vrf: management vrf_filter: management + src_intf: "{{ intname|default(omit) }}" state: present provider: "{{ connection }}" register: result @@ -47,7 +55,63 @@ that: - "result.changed == false" - always: + - block: + - name: Add another vrf to filter + nxos_snmp_host: &config1 + snmp_host: 3.3.3.3 + udp: 222 + vrf_filter: default + state: present + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_host: *config1 + register: result + + - assert: *false + when: not (platform is match('N35|N5K')) + + - name: remove some configuration + nxos_snmp_host: &rem1 + snmp_host: 3.3.3.3 + udp: 222 + src_intf: "{{ intname|default(omit) }}" + vrf: management + vrf_filter: management + state: absent + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_host: *rem1 + register: result + + - assert: *false + + - block: + - name: remove some more configuration + nxos_snmp_host: &rem2 + snmp_host: 3.3.3.3 + udp: 222 + vrf_filter: default + state: absent + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_host: *rem2 + register: result + + - assert: *false + when: not (platform is match('N35|N5K')) + - name: Cleanup nxos_snmp_host: *remove register: result @@ -60,4 +124,9 @@ - assert: *false - - debug: msg="END connection={{ ansible_connection }} nxos_snmp_host {{ snmp_type }} {{ snmp_version }}sanity test" + always: + - name: Cleanup + nxos_snmp_host: *remove + register: result + + - debug: msg="END connection={{ ansible_connection }} nxos_snmp_host {{ snmp_type }} {{ snmp_version }} sanity test" diff --git a/test/integration/targets/nxos_snmp_traps/defaults/main.yaml b/test/integration/targets/nxos_snmp_traps/defaults/main.yaml new file mode 100644 index 00000000000..5f709c5aac1 --- /dev/null +++ b/test/integration/targets/nxos_snmp_traps/defaults/main.yaml @@ -0,0 +1,2 @@ +--- +testcase: "*" diff --git a/test/integration/targets/nxos_snmp_traps/meta/main.yml b/test/integration/targets/nxos_snmp_traps/meta/main.yml new file mode 100644 index 00000000000..ae741cbdc71 --- /dev/null +++ b/test/integration/targets/nxos_snmp_traps/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - prepare_nxos_tests diff --git a/test/integration/targets/nxos_snmp_traps/tasks/cli.yaml b/test/integration/targets/nxos_snmp_traps/tasks/cli.yaml new file mode 100644 index 00000000000..edbff7dfafb --- /dev/null +++ b/test/integration/targets/nxos_snmp_traps/tasks/cli.yaml @@ -0,0 +1,33 @@ +--- +- name: collect common cli test cases + find: + paths: "{{ role_path }}/tests/common" + patterns: "{{ testcase }}.yaml" + connection: local + register: test_cases + +- name: collect cli test cases + find: + paths: "{{ role_path }}/tests/cli" + patterns: "{{ testcase }}.yaml" + connection: local + register: cli_cases + +- set_fact: + test_cases: + files: "{{ test_cases.files }} + {{ cli_cases.files }}" + +- name: set test_items + set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: run test cases (connection=network_cli) + include: "{{ test_case_to_run }} ansible_connection=network_cli connection={}" + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run + +- name: run test case (connection=local) + include: "{{ test_case_to_run }} ansible_connection=local connection={{ cli }}" + with_first_found: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/test/integration/targets/nxos_snmp_traps/tasks/main.yaml b/test/integration/targets/nxos_snmp_traps/tasks/main.yaml new file mode 100644 index 00000000000..fea9337c14c --- /dev/null +++ b/test/integration/targets/nxos_snmp_traps/tasks/main.yaml @@ -0,0 +1,7 @@ +--- +# Use block to ensure that both cli and nxapi tests +# will run even if there are failures or errors. +- block: + - { include: cli.yaml, tags: ['cli'] } + always: + - { include: nxapi.yaml, tags: ['nxapi'] } diff --git a/test/integration/targets/nxos_snmp_traps/tasks/nxapi.yaml b/test/integration/targets/nxos_snmp_traps/tasks/nxapi.yaml new file mode 100644 index 00000000000..68e96a29420 --- /dev/null +++ b/test/integration/targets/nxos_snmp_traps/tasks/nxapi.yaml @@ -0,0 +1,27 @@ +--- +- name: collect common nxapi test cases + find: + paths: "{{ role_path }}/tests/common" + patterns: "{{ testcase }}.yaml" + connection: local + register: test_cases + +- name: collect nxapi test cases + find: + paths: "{{ role_path }}/tests/nxapi" + patterns: "{{ testcase }}.yaml" + connection: local + register: nxapi_cases + +- set_fact: + test_cases: + files: "{{ test_cases.files }} + {{ nxapi_cases.files }}" + +- name: set test_items + set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}" + +- name: run test cases (connection=local) + include: "{{ test_case_to_run }} ansible_connection=local connection={{ nxapi }}" + with_items: "{{ test_items }}" + loop_control: + loop_var: test_case_to_run diff --git a/test/integration/targets/nxos_snmp_traps/tests/common/sanity.yaml b/test/integration/targets/nxos_snmp_traps/tests/common/sanity.yaml new file mode 100644 index 00000000000..4286813c866 --- /dev/null +++ b/test/integration/targets/nxos_snmp_traps/tests/common/sanity.yaml @@ -0,0 +1,84 @@ +--- +- debug: msg="START connection={{ ansible_connection }} nxos_snmp_traps sanity test" +- debug: msg="Using provider={{ connection.transport }}" + when: ansible_connection == "local" + +- name: Setup - Remove snmp_traps if configured + nxos_snmp_traps: &remove + group: all + state: disabled + provider: "{{ connection }}" + +- block: + - name: Configure one snmp trap group + nxos_snmp_traps: &config + group: bridge + state: enabled + provider: "{{ connection }}" + register: result + + - assert: &true + that: + - "result.changed == true" + + - name: Idempotence Check + nxos_snmp_traps: *config + register: result + + - assert: &false + that: + - "result.changed == false" + + - name: Remove snmp trap group + nxos_snmp_traps: &rem1 + group: bridge + state: disabled + provider: "{{ connection }}" + register: result + + - assert: *true + + - name: Idempotence Check + nxos_snmp_traps: *rem1 + register: result + + - assert: *false + + - name: Configure all snmp trap groups + nxos_snmp_traps: &config1 + group: all + state: enabled + provider: "{{ connection }}" + register: result + + - assert: *true + + - block: + # On I2, link command does not work properly + # On D1, callhome command does not work properly + # skip for these older platforms + - name: Idempotence Check + nxos_snmp_traps: *config1 + register: result + when: imagetag is not search("I2|D1") + + - assert: *false + when: imagetag is not search("I2|D1") + + - name: Cleanup + nxos_snmp_traps: *remove + register: result + + - assert: *true + + - name: Cleanup Idempotence + nxos_snmp_traps: *remove + register: result + + - assert: *false + + always: + - name: Cleanup + nxos_snmp_traps: *remove + + - debug: msg="END connection={{ ansible_connection }} nxos_snmp_traps sanity test" diff --git a/test/sanity/validate-modules/ignore.txt b/test/sanity/validate-modules/ignore.txt index a9995f37a09..c331edf3378 100644 --- a/test/sanity/validate-modules/ignore.txt +++ b/test/sanity/validate-modules/ignore.txt @@ -1748,7 +1748,6 @@ lib/ansible/modules/network/nxos/nxos_reboot.py E325 lib/ansible/modules/network/nxos/nxos_smu.py E324 lib/ansible/modules/network/nxos/nxos_snapshot.py E325 lib/ansible/modules/network/nxos/nxos_snapshot.py E326 -lib/ansible/modules/network/nxos/nxos_snmp_community.py E324 lib/ansible/modules/network/nxos/nxos_snmp_user.py E325 lib/ansible/modules/network/nxos/nxos_snmp_user.py E326 lib/ansible/modules/network/nxos/nxos_system.py E325