stable-2.5 nxos bugfix cherry-pick (#38372)

* nxos_vlan purge (#38202)

Signed-off-by: Trishna Guha <trishnaguha17@gmail.com>
(cherry picked from commit 119352b538)

* fix nxos_aaa_server issues (#38117)

(cherry picked from commit 697c301f04)

* fix nxos_aaa_server_host issues (#38188)

(cherry picked from commit 24cc6b80bd)

* fix nxos_static_route issues (#37614)

* fix nxos_static_route issues

* remove nxos_static_route from ignore

(cherry picked from commit 0df5cfd41f)

* fix nxos_acl issues (#38283)

* fix nxos_acl issues

* typo fix

* typo fix in sanity.yaml

* another typo fix in sanity.yaml

(cherry picked from commit 1bf29651af)

* nxos_acl_interface tests addition (#38230)

(cherry picked from commit b8cb382a40)

* update changelog with nxos bugfixes for 2.5

Signed-off-by: Trishna Guha <trishnaguha17@gmail.com>

* revert ignore.txt

Signed-off-by: Trishna Guha <trishnaguha17@gmail.com>
pull/38382/head
Trishna Guha 7 years ago committed by GitHub
parent ff03fc0f67
commit 536dff507d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -9,3 +9,9 @@ bugfixes:
- nxos_vrf_af - Fix nxos_vrf_af issues (https://github.com/ansible/ansible/pull/37211)
- nxos_udld - Fix nxos_udld issues (https://github.com/ansible/ansible/pull/37418)
- nxos_vlan - Fix nxos_vlan issues (https://github.com/ansible/ansible/pull/38008)
- nxos_vlan - nxos_vlan purge (https://github.com/ansible/ansible/pull/38202)
- nxos_aaa_server - Fix nxos_aaa_server (https://github.com/ansible/ansible/pull/38117)
- nxos_aaa_server_host - Fix nxos_aaa_server_host (https://github.com/ansible/ansible/pull/38188)
- nxos_acl - Fix nxos_acl (https://github.com/ansible/ansible/pull/38283)
- nxos_static_route - Fix nxos_static_route (https://github.com/ansible/ansible/pull/37614)
- nxos_acl_interface test - Fix nxos_acl_interface test (https://github.com/ansible/ansible/pull/38230)

@ -39,7 +39,6 @@ notes:
stored as encrypted (type 7).
- Changes to the global AAA server key with encrypt_type=0
are not idempotent.
- If global AAA server key is not found, it's shown as "unknown"
- state=default will set the supplied parameters to their default values.
The parameters that you want to default must also be set to default.
If global_key=default, the global key will be removed.
@ -51,9 +50,7 @@ options:
choices: ['radius', 'tacacs']
global_key:
description:
- Global AAA shared secret.
required: false
default: null
- Global AAA shared secret or keyword 'default'.
encrypt_type:
description:
- The state of encryption applied to the entered global key.
@ -64,18 +61,17 @@ options:
deadtime:
description:
- Duration for which a non-reachable AAA server is skipped,
in minutes. Range is 1-1440. Device default is 0.
in minutes or keyword 'default.
Range is 1-1440. Device default is 0.
required: false
default: null
server_timeout:
description:
- Global AAA server timeout period, in seconds. Range is 1-60.
Device default is 5.
required: false
default: null
- Global AAA server timeout period, in seconds or keyword 'default.
Range is 1-60. Device default is 5.
directed_request:
description:
- Enables direct authentication requests to AAA server.
- Enables direct authentication requests to AAA server or keyword 'default'
Device default is disabled.
required: false
default: null
@ -127,7 +123,14 @@ from ansible.module_utils.network.nxos.nxos import nxos_argument_spec, check_arg
from ansible.module_utils.basic import AnsibleModule
def execute_show_command(command, module, command_type='cli_show'):
PARAM_TO_DEFAULT_KEYMAP = {
'server_timeout': '5',
'deadtime': '0',
'directed_request': 'disabled',
}
def execute_show_command(command, module):
command = {
'command': command,
'output': 'text',
@ -153,8 +156,7 @@ def get_aaa_server_info(server_type, module):
global_key_command = 'show run | sec {0}'.format(server_type)
aaa_regex = r'.*{0}-server\skey\s\d\s+(?P<key>\S+).*'.format(server_type)
server_body = execute_show_command(
server_command, module, command_type='cli_show_ascii')[0]
server_body = execute_show_command(server_command, module)[0]
split_server = server_body.splitlines()
@ -165,30 +167,25 @@ def get_aaa_server_info(server_type, module):
elif line.startswith('deadtime'):
aaa_server_info['deadtime'] = line.split(':')[1]
request_body = execute_show_command(
request_command, module, command_type='cli_show_ascii')[0]
request_body = execute_show_command(request_command, module)[0]
if bool(request_body):
aaa_server_info['directed_request'] = request_body.replace('\n', '')
else:
aaa_server_info['directed_request'] = 'disabled'
key_body = execute_show_command(
global_key_command, module, command_type='cli_show_ascii')[0]
key_body = execute_show_command(global_key_command, module)[0]
try:
match_global_key = re.match(aaa_regex, key_body, re.DOTALL)
group_key = match_global_key.groupdict()
aaa_server_info['global_key'] = group_key["key"].replace('\"', '')
except (AttributeError, TypeError):
aaa_server_info['global_key'] = 'unknown'
aaa_server_info['global_key'] = None
return aaa_server_info
def set_aaa_server_global_key(encrypt_type, key, server_type):
if not encrypt_type:
encrypt_type = ''
return '{0}-server key {1} {2}'.format(
server_type, encrypt_type, key)
def config_aaa_server(params, server_type):
cmds = []
@ -226,13 +223,13 @@ def default_aaa_server(existing, params, server_type):
global_key = params.get('global_key')
existing_key = existing.get('global_key')
if deadtime is not None:
if deadtime is not None and existing.get('deadtime') != PARAM_TO_DEFAULT_KEYMAP['deadtime']:
cmds.append('no {0}-server deadtime 1'.format(server_type))
if server_timeout is not None:
if server_timeout is not None and existing.get('server_timeout') != PARAM_TO_DEFAULT_KEYMAP['server_timeout']:
cmds.append('no {0}-server timeout 1'.format(server_type))
if directed_request is not None:
if directed_request is not None and existing.get('directed_request') != PARAM_TO_DEFAULT_KEYMAP['directed_request']:
cmds.append('no {0}-server directed-request'.format(server_type))
if global_key is not None and existing_key is not None:

@ -33,7 +33,7 @@ description:
author: Jason Edelman (@jedelman8)
notes:
- Tested against NXOSv 7.3.(0)D1(1) on VIRL
- Changes to the AAA server host key (shared secret) are not idempotent.
- Changes to the host key (shared secret) are not idempotent for type 0.
- If C(state=absent) removes the whole host configuration.
options:
server_type:
@ -47,41 +47,29 @@ options:
required: true
key:
description:
- Shared secret for the specified host.
required: false
default: null
- Shared secret for the specified host or keyword 'default'.
encrypt_type:
description:
- The state of encryption applied to the entered key.
O for clear text, 7 for encrypted. Type-6 encryption is
not supported.
required: false
default: null
choices: ['0', '7']
host_timeout:
description:
- Timeout period for specified host, in seconds. Range is 1-60.
required: false
default: null
- Timeout period for specified host, in seconds or keyword 'default.
Range is 1-60.
auth_port:
description:
- Alternate UDP port for RADIUS authentication.
required: false
default: null
- Alternate UDP port for RADIUS authentication or keyword 'default'.
acct_port:
description:
- Alternate UDP port for RADIUS accounting.
required: false
default: null
- Alternate UDP port for RADIUS accounting or keyword 'default'.
tacacs_port:
description:
- Alternate TCP port TACACS Server.
required: false
default: null
- Alternate TCP port TACACS Server or keyword 'default'.
state:
description:
- Manage the state of the resource.
required: false
default: present
choices: ['present','absent']
'''
@ -160,13 +148,11 @@ from ansible.module_utils.network.nxos.nxos import get_capabilities, nxos_argume
from ansible.module_utils.basic import AnsibleModule
def execute_show_command(command, module, command_type='cli_show'):
def execute_show_command(command, module):
device_info = get_capabilities(module)
network_api = device_info.get('network_api', 'nxapi')
if network_api == 'cliconf':
if 'show run' not in command:
command += ' | json'
cmds = [command]
body = run_commands(module, cmds)
elif network_api == 'nxapi':
@ -186,40 +172,36 @@ def flatten_list(command_lists):
return flat_command_list
def _match_dict(match_list, key_map):
no_blanks = []
match_dict = {}
for match_set in match_list:
match_set = tuple(v for v in match_set if v)
no_blanks.append(match_set)
for info in no_blanks:
words = info[0].strip().split()
length = len(words)
alt_key = key_map.get(words[0])
first = alt_key or words[0]
last = words[length - 1]
match_dict[first] = last.replace('\"', '')
return match_dict
def get_aaa_host_info(module, server_type, address):
aaa_host_info = {}
command = 'show run | inc {0}-server.host.{1}'.format(server_type, address)
body = execute_show_command(command, module, command_type='cli_show_ascii')
if body[0]:
body = execute_show_command(command, module)[0]
if body:
try:
pattern = (r'(acct-port \d+)|(timeout \d+)|(auth-port \d+)|'
r'(key 7 "\w+")|( port \d+)')
raw_match = re.findall(pattern, body[0])
aaa_host_info = _match_dict(raw_match, {'acct-port': 'acct_port',
'auth-port': 'auth_port',
'port': 'tacacs_port',
'timeout': 'host_timeout'})
if 'radius' in body:
pattern = (r'\S+ host \S+(?:\s+key 7\s+(\S+))?(?:\s+auth-port (\d+))?'
r'(?:\s+acct-port (\d+))?(?:\s+authentication)?'
r'(?:\s+accounting)?(?:\s+timeout (\d+))?')
match = re.search(pattern, body)
aaa_host_info['key'] = match.group(1)
if aaa_host_info['key']:
aaa_host_info['key'] = aaa_host_info['key'].replace('"', '')
aaa_host_info['encrypt_type'] = '7'
aaa_host_info['auth_port'] = match.group(2)
aaa_host_info['acct_port'] = match.group(3)
aaa_host_info['host_timeout'] = match.group(4)
elif 'tacacs' in body:
pattern = (r'\S+ host \S+(?:\s+key 7\s+(\S+))?(?:\s+port (\d+))?'
r'(?:\s+timeout (\d+))?')
match = re.search(pattern, body)
aaa_host_info['key'] = match.group(1)
if aaa_host_info['key']:
aaa_host_info['key'] = aaa_host_info['key'].replace('"', '')
aaa_host_info['encrypt_type'] = '7'
aaa_host_info['tacacs_port'] = match.group(2)
aaa_host_info['host_timeout'] = match.group(3)
aaa_host_info['server_type'] = server_type
aaa_host_info['address'] = address
except TypeError:
@ -230,35 +212,41 @@ def get_aaa_host_info(module, server_type, address):
return aaa_host_info
def config_aaa_host(server_type, address, params, clear=False):
def config_aaa_host(server_type, address, params, existing):
cmds = []
if clear:
cmds.append('no {0}-server host {1}'.format(server_type, address))
cmd_str = '{0}-server host {1}'.format(server_type, address)
cmd_no_str = 'no ' + cmd_str
key = params.get('key')
enc_type = params.get('encrypt_type', '')
host_timeout = params.get('host_timeout')
auth_port = params.get('auth_port')
acct_port = params.get('acct_port')
port = params.get('tacacs_port')
if auth_port:
cmd_str += ' auth-port {0}'.format(auth_port)
if acct_port:
cmd_str += ' acct-port {0}'.format(acct_port)
if port:
cmd_str += ' port {0}'.format(port)
if host_timeout:
cmd_str += ' timeout {0}'.format(host_timeout)
if key:
cmds.append('{0}-server host {1} key {2} {3}'.format(server_type,
address,
enc_type, key))
defval = False
nondef = False
if key:
if key != 'default':
cmds.append(cmd_str + ' key {0} {1}'.format(enc_type, key))
else:
cmds.append(cmd_no_str + ' key 7 {0}'.format(existing.get('key')))
locdict = {'auth_port': 'auth-port', 'acct_port': 'acct-port',
'tacacs_port': 'port', 'host_timeout': 'timeout'}
# platform CLI needs the keywords in the following order
for key in ['auth_port', 'acct_port', 'tacacs_port', 'host_timeout']:
item = params.get(key)
if item:
if item != 'default':
cmd_str += ' {0} {1}'.format(locdict.get(key), item)
nondef = True
else:
cmd_no_str += ' {0} 1'.format(locdict.get(key))
defval = True
if defval:
cmds.append(cmd_no_str)
if nondef or not existing:
cmds.append(cmd_str)
return cmds
@ -315,22 +303,17 @@ def main():
end_state = existing
commands = []
delta = {}
if state == 'present':
host_timeout = proposed.get('host_timeout')
if host_timeout:
try:
if int(host_timeout) < 1 or int(host_timeout) > 60:
raise ValueError
except ValueError:
module.fail_json(
msg='host_timeout must be an integer between 1 and 60')
delta = dict(
set(proposed.items()).difference(existing.items()))
if delta:
union = existing.copy()
union.update(delta)
command = config_aaa_host(server_type, address, union)
if not existing:
delta = proposed
else:
for key, value in proposed.items():
if value != existing.get(key):
if value != 'default' or existing.get(key):
delta[key] = value
command = config_aaa_host(server_type, address, delta, existing)
if command:
commands.append(command)

@ -252,6 +252,7 @@ def get_acl(module, acl_name, seq_number):
for acl in all_acl_body:
if acl.get('acl_name') == acl_name:
acl_body = acl
break
try:
acl_entries = acl_body['TABLE_seqno']['ROW_seqno']
@ -275,7 +276,7 @@ def get_acl(module, acl_name, seq_number):
temp['action'] = 'remark'
else:
temp['action'] = each.get('permitdeny')
temp['proto'] = each.get('proto', each.get('proto_str', each.get('ip')))
temp['proto'] = str(each.get('proto', each.get('proto_str', each.get('ip'))))
temp['src'] = each.get('src_any', each.get('src_ip_prefix'))
temp['src_port_op'] = each.get('src_port_op')
temp['src_port1'] = each.get('src_port1_num')
@ -507,14 +508,36 @@ def main():
delta_options = {}
if not existing_core.get('remark'):
delta_core = dict(
dcore = dict(
set(proposed_core.items()).difference(
existing_core.items())
)
delta_options = dict(
if not dcore:
# check the diff in the other way just in case
dcore = dict(
set(existing_core.items()).difference(
proposed_core.items())
)
delta_core = dcore
if delta_core:
delta_options = proposed_options
else:
doptions = dict(
set(proposed_options.items()).difference(
existing_options.items())
)
# check the diff in the other way just in case
if not doptions:
doptions = dict(
set(existing_options.items()).difference(
proposed_options.items())
)
delta_options = doptions
else:
delta_core = dict(
set(proposed_core.items()).difference(
existing_core.items())
)
if state == 'present':
if delta_core or delta_options:

@ -49,23 +49,16 @@ options:
vrf:
description:
- VRF for static route.
required: false
default: default
tag:
description:
- Route tag value (numeric).
required: false
default: null
- Route tag value (numeric) or keyword 'default'.
route_name:
description:
- Name of the route. Used with the name parameter on the CLI.
required: false
default: null
- Name of the route or keyword 'default'. Used with the name parameter on the CLI.
pref:
description:
- Preference or administrative difference of route (range 1-255).
required: false
default: null
- Preference or administrative difference of route (range 1-255) or keyword 'default'.
aliases:
- admin_distance
aggregate:
@ -74,8 +67,8 @@ options:
state:
description:
- Manage the state of the resource.
required: true
choices: ['present','absent']
default: 'present'
'''
EXAMPLES = '''
@ -112,11 +105,22 @@ def reconcile_candidate(module, candidate, prefix, w):
parents = []
commands = []
yrc = remove_command.replace('no ', '')
if w['vrf'] == 'default':
config = netcfg.get_section(set_command)
if config and state == 'absent':
netcfg = str(netcfg).split('\n')
ncfg = []
for line in netcfg:
# remove ip route commands of non-default vrfs from
# the running config just in case the same commands
# exist in default and non-default vrfs
if ' ip route' not in line:
ncfg.append(line)
if any(yrc in s for s in ncfg) and state == 'absent':
commands = [remove_command]
elif not config and state == 'present':
elif set_command not in ncfg and state == 'present':
if any(yrc in s for s in ncfg):
commands = [remove_command, set_command]
else:
commands = [set_command]
else:
parents = ['vrf context {0}'.format(w['vrf'])]
@ -124,54 +128,18 @@ def reconcile_candidate(module, candidate, prefix, w):
if not isinstance(config, list):
config = config.split('\n')
config = [line.strip() for line in config]
if set_command in config and state == 'absent':
if any(yrc in s for s in config) and state == 'absent':
commands = [remove_command]
elif set_command not in config and state == 'present':
if any(yrc in s for s in config):
commands = [remove_command, set_command]
else:
commands = [set_command]
if commands:
candidate.add(commands, parents=parents)
def fix_prefix_to_regex(prefix):
prefix = prefix.replace('.', r'\.').replace('/', r'\/')
return prefix
def get_existing(module, prefix, warnings):
key_map = ['tag', 'pref', 'route_name', 'next_hop']
netcfg = CustomNetworkConfig(indent=2, contents=get_config(module))
parents = 'vrf context {0}'.format(module.params['vrf'])
prefix_to_regex = fix_prefix_to_regex(prefix)
route_regex = r'.*ip\sroute\s{0}\s(?P<next_hop>\S+)(\sname\s(?P<route_name>\S+))?(\stag\s(?P<tag>\d+))?(\s(?P<pref>\d+))?.*'.format(prefix_to_regex)
if module.params['vrf'] == 'default':
config = str(netcfg)
else:
config = netcfg.get_section(parents)
if config:
try:
match_route = re.match(route_regex, config, re.DOTALL)
group_route = match_route.groupdict()
for key in key_map:
if key not in group_route:
group_route[key] = ''
group_route['prefix'] = prefix
group_route['vrf'] = module.params['vrf']
except (AttributeError, TypeError):
group_route = {}
else:
group_route = {}
msg = ("VRF {0} didn't exist.".format(module.params['vrf']))
if msg not in warnings:
warnings.append(msg)
return group_route
def remove_route_command(prefix, w):
return 'no ip route {0} {1}'.format(prefix, w['next_hop'])
@ -179,11 +147,12 @@ def remove_route_command(prefix, w):
def set_route_command(prefix, w):
route_cmd = 'ip route {0} {1}'.format(prefix, w['next_hop'])
if w['route_name']:
if w['route_name'] and w['route_name'] != 'default':
route_cmd += ' name {0}'.format(w['route_name'])
if w['tag']:
if w['tag'] != 'default' and w['tag'] != '0':
route_cmd += ' tag {0}'.format(w['tag'])
if w['pref']:
if w['pref'] and w['pref'] != 'default':
route_cmd += ' {0}'.format(w['pref'])
return route_cmd

@ -96,6 +96,8 @@ options:
purge:
description:
- Purge VLANs not defined in the I(aggregate) parameter.
This parameter can be used without aggregate as well.
type: bool
default: no
delay:
description:
@ -143,6 +145,14 @@ EXAMPLES = '''
aggregate:
- { vlan_id: 4000, mode: ce }
- { vlan_id: 4001, name: vlan-4001 }
- name: purge vlans - removes all other vlans except the ones mentioned in aggregate)
nxos_vlan:
aggregate:
- vlan_id: 1
- vlan_id: 4001
purge: yes
'''
RETURN = '''
@ -196,6 +206,7 @@ def is_default_name(obj, vlan_id):
def map_obj_to_commands(updates, module, os_platform):
commands = list()
purge = module.params['purge']
want, have = updates
for w in want:
@ -319,6 +330,12 @@ def map_obj_to_commands(updates, module, os_platform):
commands.append('switchport mode access')
commands.append('no switchport access vlan {0}'.format(vlan_id))
if purge:
for h in have:
obj_in_want = search_obj_in_list(h['vlan_id'], want)
if not obj_in_want:
commands.append('no vlan {0}'.format(h['vlan_id']))
return commands

@ -73,7 +73,7 @@
- assert: *false
- name: "Remove radius server configuration"
nxos_aaa_server:
nxos_aaa_server: &rad_def
server_type: radius
deadtime: default
server_timeout: default
@ -85,6 +85,12 @@
- assert: *true
- name: "Check Idempotence"
nxos_aaa_server: *rad_def
register: result
- assert: *false
rescue:
- debug: msg="connection={{ ansible_connection }} nxos_aaa_server failure detected"
@ -94,4 +100,4 @@
nxos_aaa_server: *remove
register: result
- debug: msg="END connection={{ ansible_connection }} nxos_aaa_server radius.yaml sanity test"
- debug: msg="END connection={{ ansible_connection }} nxos_aaa_server radius.yaml sanity test"

@ -79,11 +79,24 @@
- assert: *false
- name: "Remove tacacs server configuration"
nxos_aaa_server: *remove
nxos_aaa_server: &tac_def
server_type: tacacs
deadtime: default
server_timeout: default
global_key: default
directed_request: default
state: default
provider: "{{ connection }}"
register: result
- assert: *true
- name: "Check Idempotence"
nxos_aaa_server: *tac_def
register: result
- assert: *false
rescue:
- debug: msg="connection={{ ansible_connection }} nxos_aaa_server failure detected"
@ -100,4 +113,4 @@
state: disabled
provider: "{{ connection }}"
- debug: msg="END connection={{ ansible_connection }} nxos_aaa_server tacacs.yaml sanity test"
- debug: msg="END connection={{ ansible_connection }} nxos_aaa_server tacacs.yaml sanity test"

@ -63,18 +63,31 @@
- assert: *false
- name: "Remove radius server configuration"
nxos_aaa_server_host: *remove
- name: "Configure some defaults on radius server"
nxos_aaa_server_host: &configure_some_radius_default
server_type: radius
address: 8.8.8.8
host_timeout: default
auth_port: 1000
acct_port: default
state: present
provider: "{{ connection }}"
register: result
- assert: *true
- name: "Check Idempotence"
nxos_aaa_server_host: *configure_some_radius_default
register: result
- assert: *false
- name: "Configure radius server with clear text pwd"
nxos_aaa_server_host: &configure_radius_clear_text
server_type: radius
address: 8.8.8.8
host_timeout: 25
auth_port: 2083
auth_port: default
acct_port: 2084
encrypt_type: 0
key: hello
@ -115,8 +128,49 @@
nxos_aaa_server_host: *configure_radius_type7
register: result
- assert: *false
- name: "Configure radius server with default key"
nxos_aaa_server_host: &configure_radius_defkey
server_type: radius
address: 8.8.8.8
host_timeout: default
auth_port: 1000
acct_port: default
encrypt_type: 7
key: default
state: present
provider: "{{ connection }}"
register: result
- assert: *true
- name: "Check Idempotence"
nxos_aaa_server_host: *configure_radius_defkey
register: result
- assert: *false
- name: "Configure radius server with all def"
nxos_aaa_server_host: &configure_radius_alldef
server_type: radius
address: 8.8.8.8
host_timeout: default
auth_port: default
acct_port: default
key: default
state: present
provider: "{{ connection }}"
register: result
- assert: *true
- name: "Check Idempotence"
nxos_aaa_server_host: *configure_radius_alldef
register: result
- assert: *false
rescue:
- debug: msg="connection={{ ansible_connection }} nxos_aaa_server_host failure detected"

@ -69,18 +69,30 @@
- assert: *false
- name: "Remove tacacs server configuration"
nxos_aaa_server_host: *remove
- name: "Configure some defaults on tacacs server"
nxos_aaa_server_host: &configure_some_tacacs_default
server_type: tacacs
address: 8.8.8.8
host_timeout: default
tacacs_port: 100
state: present
provider: "{{ connection }}"
register: result
- assert: *true
- name: "Check Idempotence"
nxos_aaa_server_host: *configure_some_tacacs_default
register: result
- assert: *false
- name: "Configure tacacs server with clear text pwd"
nxos_aaa_server_host: &configure_tacacs_clear_text
server_type: tacacs
address: 8.8.8.8
host_timeout: 25
tacacs_port: 89
tacacs_port: default
encrypt_type: 0
key: hello
state: present
@ -119,8 +131,47 @@
nxos_aaa_server_host: *configure_tacacs_type7
register: result
- assert: *false
- name: "Configure tacacs server with default key"
nxos_aaa_server_host: &configure_tacacs_defkey
server_type: tacacs
address: 8.8.8.8
host_timeout: default
tacacs_port: 89
encrypt_type: 7
key: default
state: present
provider: "{{ connection }}"
register: result
- assert: *true
- name: "Check Idempotence"
nxos_aaa_server_host: *configure_tacacs_defkey
register: result
- assert: *false
- name: "Configure tacacs server with all def"
nxos_aaa_server_host: &configure_tacacs_alldef
server_type: tacacs
address: 8.8.8.8
host_timeout: default
tacacs_port: default
key: default
state: present
provider: "{{ connection }}"
register: result
- assert: *true
- name: "Check Idempotence"
nxos_aaa_server_host: *configure_tacacs_alldef
register: result
- assert: *false
rescue:
- debug: msg="connection={{ ansible_connection }} nxos_aaa_server_host failure detected"
@ -131,7 +182,7 @@
nxos_aaa_server_host: *remove
register: result
- name: "Enable feature tacacs+"
- name: "Disable feature tacacs+"
nxos_feature:
feature: tacacs+
state: disabled

@ -10,12 +10,12 @@
nxos_acl: &remove
name: TEST_ACL
seq: 10
state: absent
state: delete_acl
provider: "{{ connection }}"
ignore_errors: yes
- name: "Configure ACL"
nxos_acl: &configure
- name: "Configure ACE10"
nxos_acl: &conf10
name: TEST_ACL
seq: 10
action: permit
@ -27,6 +27,8 @@
ack: 'enable'
dscp: 'af43'
dest: any
dest_port_op: neq
dest_port1: 1899
urg: 'enable'
psh: 'enable'
established: 'enable'
@ -44,13 +46,187 @@
- "result.changed == true"
- name: "Check Idempotence"
nxos_acl: *configure
nxos_acl: *conf10
register: result
- assert: &false
that:
- "result.changed == false"
- name: "Change ACE10"
nxos_acl: &chg10
name: TEST_ACL
seq: 10
action: deny
proto: tcp
src: 1.1.1.1/24
src_port_op: range
src_port1: 1900
src_port2: 1910
ack: 'enable'
dscp: 'af43'
dest: any
dest_port_op: neq
dest_port1: 1899
urg: 'enable'
psh: 'enable'
established: 'enable'
log: 'enable'
fin: 'enable'
rst: 'enable'
syn: 'enable'
time_range: "{{time_range|default(omit)}}"
state: present
provider: "{{ connection }}"
register: result
- assert: *true
- name: "Check Idempotence"
nxos_acl: *chg10
register: result
- assert: *false
- name: "ace remark"
nxos_acl: &remark
name: TEST_ACL
seq: 20
action: remark
remark: test_remark
state: present
provider: "{{ connection }}"
register: result
- assert: *true
- name: "Check Idempotence"
nxos_acl: *remark
register: result
- assert: *false
- name: "change remark"
nxos_acl: &chgremark
name: TEST_ACL
seq: 20
action: remark
remark: changed_remark
state: present
provider: "{{ connection }}"
register: result
- assert: *true
- name: "Check Idempotence"
nxos_acl: *chgremark
register: result
- assert: *false
- name: "ace 30"
nxos_acl: &ace30
name: TEST_ACL
seq: 30
action: deny
proto: 24
src: any
dest: any
fragments: enable
precedence: network
state: present
provider: "{{ connection }}"
register: result
- assert: *true
- name: "Check Idempotence"
nxos_acl: *ace30
register: result
- assert: *false
- name: "change ace 30 options"
nxos_acl: &chgace30opt
name: TEST_ACL
seq: 30
action: deny
proto: 24
src: any
dest: any
precedence: network
state: present
provider: "{{ connection }}"
register: result
- assert: *true
- name: "Check Idempotence"
nxos_acl: *chgace30opt
register: result
- assert: *false
- name: "ace 40"
nxos_acl: &ace40
name: TEST_ACL
seq: 40
action: permit
proto: udp
src: any
src_port_op: neq
src_port1: 1200
dest: any
precedence: network
state: present
provider: "{{ connection }}"
register: result
- assert: *true
- name: "Check Idempotence"
nxos_acl: *ace40
register: result
- assert: *false
- name: "change ace 40"
nxos_acl: &chgace40
name: TEST_ACL
seq: 40
action: permit
proto: udp
src: any
dest: any
precedence: network
state: present
provider: "{{ connection }}"
register: result
- assert: *true
- name: "Check Idempotence"
nxos_acl: *chgace40
register: result
- assert: *false
- name: "remove ace 30"
nxos_acl: &remace30
name: TEST_ACL
seq: 30
state: absent
provider: "{{ connection }}"
register: result
- assert: *true
- name: "Check Idempotence"
nxos_acl: *remace30
register: result
- assert: *false
- name: "Remove ACL"
nxos_acl: *remove
register: result

@ -16,11 +16,21 @@
provider: "{{ connection }}"
ignore_errors: yes
- name: "Setup: Put interface into no switch port mode"
nxos_config:
commands:
- "no switchport"
parents:
- "interface {{ intname }}"
match: none
provider: "{{ connection }}"
ignore_errors: yes
- name: "Setup: Cleanup possibly existing acl"
nxos_acl: &remove
name: ANSIBLE_ACL
seq: 10
state: absent
state: delete_acl
provider: "{{ connection }}"
ignore_errors: yes
@ -112,9 +122,9 @@
nxos_config: *default
ignore_errors: yes
always:
- name: Remove possible configured ACL
nxos_acl: *remove
ignore_errors: yes
always:
- debug: msg="END connection={{ ansible_connection }} nxos_acl_interface sanity test"

@ -1,2 +1,5 @@
---
testcase: "*"
vrfs:
- default
- myvrf

@ -11,8 +11,9 @@
route_name: testing
pref: 100
tag: 5500
vrf: testing
vrf: "{{ item }}"
provider: "{{ connection }}"
with_items: "{{ vrfs }}"
register: result
- assert: &true
@ -21,28 +22,51 @@
- name: "Conf Idempotence"
nxos_static_route: *configure
with_items: "{{ vrfs }}"
register: result
- assert: &false
that:
- "result.changed == false"
- name: change static route
nxos_static_route: &configure1
prefix: "192.168.20.64/24"
next_hop: "3.3.3.3"
route_name: default
pref: 10
tag: default
vrf: "{{ item }}"
provider: "{{ connection }}"
with_items: "{{ vrfs }}"
register: result
- assert: *true
- name: "Conf1 Idempotence"
nxos_static_route: *configure1
with_items: "{{ vrfs }}"
register: result
- assert: *false
- name: remove static route
nxos_static_route: &remove
prefix: "192.168.20.64/24"
next_hop: "3.3.3.3"
route_name: testing
pref: 100
tag: 5500
vrf: testing
vrf: "{{ item }}"
state: absent
provider: "{{ connection }}"
with_items: "{{ vrfs }}"
register: result
- assert: *true
- name: "Remove Idempotence"
nxos_static_route: *remove
with_items: "{{ vrfs }}"
register: result
- assert: *false
@ -96,9 +120,10 @@
route_name: testing
pref: 100
tag: 5500
vrf: testing
vrf: "{{ item }}"
state: absent
provider: "{{ connection }}"
with_items: "{{ vrfs }}"
ignore_errors: yes
- name: remove static route aggregate

@ -63,6 +63,27 @@
that:
- 'result.changed == false'
- name: purge
nxos_vlan: &purge
vlan_id: 1
purge: yes
provider: "{{ connection }}"
register: result
- assert:
that:
- 'result.changed == true'
- '"no vlan 102" in result.commands'
- '"no vlan 103" in result.commands'
- name: purge - Idempotence
nxos_vlan: *purge
register: result
- assert:
that:
- 'result.changed == false'
- name: teardown
nxos_config: *rm
ignore_errors: yes

Loading…
Cancel
Save