nxos_ospf_vrf fix and unittest (#24495)

This commit is contained in:
Trishna Guha 2017-05-19 10:09:46 +05:30 committed by GitHub
parent 1eed6c5b3d
commit 998305a493
3 changed files with 186 additions and 184 deletions

View file

@ -16,10 +16,11 @@
# along with Ansible. If not, see <http://www.gnu.org/licenses/>. # along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# #
ANSIBLE_METADATA = {'metadata_version': '1.0', ANSIBLE_METADATA = {
'status': ['preview'], 'metadata_version': '1.0',
'supported_by': 'community'} 'status': ['preview'],
'supported_by': 'community'
}
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
@ -28,90 +29,90 @@ extends_documentation_fragment: nxos
version_added: "2.2" version_added: "2.2"
short_description: Manages a VRF for an OSPF router. short_description: Manages a VRF for an OSPF router.
description: description:
- Manages a VRF for an OSPF router. - Manages a VRF for an OSPF router.
author: Gabriele Gerbino (@GGabriele) author: Gabriele Gerbino (@GGabriele)
notes: notes:
- Value I(default) restores params default value, if any. - Value I(default) restores params default value, if any.
Otherwise it removes the existing param configuration. Otherwise it removes the existing param configuration.
options: options:
vrf: vrf:
description: description:
- Name of the resource instance. Valid value is a string. - Name of the resource instance. Valid value is a string.
The name 'default' is a valid VRF representing the global OSPF. The name 'default' is a valid VRF representing the global OSPF.
required: false required: false
default: default default: default
ospf: ospf:
description: description:
- Name of the OSPF instance. - Name of the OSPF instance.
required: true required: true
default: null default: null
router_id: router_id:
description: description:
- Router Identifier (ID) of the OSPF router VRF instance. - Router Identifier (ID) of the OSPF router VRF instance.
required: false required: false
default: null default: null
default_metric: default_metric:
description: description:
- Specify the default Metric value. Valid values are an integer - Specify the default Metric value. Valid values are an integer
or the keyword 'default'. or the keyword 'default'.
required: false required: false
default: null default: null
log_adjacency: log_adjacency:
description: description:
- Controls the level of log messages generated whenever a - Controls the level of log messages generated whenever a
neighbor changes state. Valid values are 'log', 'detail', neighbor changes state. Valid values are 'log', 'detail',
and 'default'. and 'default'.
required: false required: false
choices: ['log','detail','default'] choices: ['log','detail','default']
default: null default: null
timer_throttle_lsa_start: timer_throttle_lsa_start:
description: description:
- Specify the start interval for rate-limiting Link-State - Specify the start interval for rate-limiting Link-State
Advertisement (LSA) generation. Valid values are an integer, Advertisement (LSA) generation. Valid values are an integer,
in milliseconds, or the keyword 'default'. in milliseconds, or the keyword 'default'.
required: false required: false
default: null default: null
timer_throttle_lsa_hold: timer_throttle_lsa_hold:
description: description:
- Specify the hold interval for rate-limiting Link-State - Specify the hold interval for rate-limiting Link-State
Advertisement (LSA) generation. Valid values are an integer, Advertisement (LSA) generation. Valid values are an integer,
in milliseconds, or the keyword 'default'. in milliseconds, or the keyword 'default'.
required: false required: false
default: null default: null
timer_throttle_lsa_max: timer_throttle_lsa_max:
description: description:
- Specify the max interval for rate-limiting Link-State - Specify the max interval for rate-limiting Link-State
Advertisement (LSA) generation. Valid values are an integer, Advertisement (LSA) generation. Valid values are an integer,
in milliseconds, or the keyword 'default'. in milliseconds, or the keyword 'default'.
required: false required: false
default: null default: null
timer_throttle_spf_start: timer_throttle_spf_start:
description: description:
- Specify initial Shortest Path First (SPF) schedule delay. - Specify initial Shortest Path First (SPF) schedule delay.
Valid values are an integer, in milliseconds, or Valid values are an integer, in milliseconds, or
the keyword 'default'. the keyword 'default'.
required: false required: false
default: null default: null
timer_throttle_spf_hold: timer_throttle_spf_hold:
description: description:
- Specify minimum hold time between Shortest Path First (SPF) - Specify minimum hold time between Shortest Path First (SPF)
calculations. Valid values are an integer, in milliseconds, calculations. Valid values are an integer, in milliseconds,
or the keyword 'default'. or the keyword 'default'.
required: false required: false
default: null default: null
timer_throttle_spf_max: timer_throttle_spf_max:
description: description:
- Specify the maximum wait time between Shortest Path First (SPF) - Specify the maximum wait time between Shortest Path First (SPF)
calculations. Valid values are an integer, in milliseconds, calculations. Valid values are an integer, in milliseconds,
or the keyword 'default'. or the keyword 'default'.
required: false required: false
default: null default: null
auto_cost: auto_cost:
description: description:
- Specifies the reference bandwidth used to assign OSPF cost. - Specifies the reference bandwidth used to assign OSPF cost.
Valid values are an integer, in Mbps, or the keyword 'default'. Valid values are an integer, in Mbps, or the keyword 'default'.
required: false required: false
default: null default: null
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -125,64 +126,27 @@ EXAMPLES = '''
timer_throttle_lsa_max: 3000 timer_throttle_lsa_max: 3000
vrf: test vrf: test
state: present state: present
username: "{{ un }}"
password: "{{ pwd }}"
host: "{{ inventory_hostname }}"
''' '''
RETURN = ''' RETURN = '''
proposed: commands:
description: k/v pairs of parameters passed into module
returned: verbose mode
type: dict
sample: {"ospf": "1", "timer_throttle_lsa_hold": "1100",
"timer_throttle_lsa_max": "3000", "timer_throttle_lsa_start": "60",
"timer_throttle_spf_hold": "1000",
"timer_throttle_spf_max": "2000", "timer_throttle_spf_start": "50",
"vrf": "test"}
existing:
description: k/v pairs of existing configuration
returned: verbose mode
type: dict
sample: {"auto_cost": "40000", "default_metric": "", "log_adjacency": "",
"ospf": "1", "router_id": "", "timer_throttle_lsa_hold": "5000",
"timer_throttle_lsa_max": "5000", "timer_throttle_lsa_start": "0",
"timer_throttle_spf_hold": "1000",
"timer_throttle_spf_max": "5000",
"timer_throttle_spf_start": "200", "vrf": "test"}
end_state:
description: k/v pairs of configuration after module execution
returned: verbose mode
type: dict
sample: {"auto_cost": "40000", "default_metric": "", "log_adjacency": "",
"ospf": "1", "router_id": "", "timer_throttle_lsa_hold": "1100",
"timer_throttle_lsa_max": "3000", "timer_throttle_lsa_start": "60",
"timer_throttle_spf_hold": "1000",
"timer_throttle_spf_max": "2000", "timer_throttle_spf_start": "50",
"vrf": "test"}
updates:
description: commands sent to the device description: commands sent to the device
returned: always returned: always
type: list type: list
sample: ["router ospf 1", "vrf test", "timers throttle lsa 60 1100 3000", sample: ["router ospf 1", "vrf test", "timers throttle lsa 60 1100 3000",
"timers throttle spf 50 1000 2000"] "ospf 1", "timers throttle spf 50 1000 2000", "vrf test"]
changed:
description: check to see if a change was made on the device
returned: always
type: boolean
sample: true
''' '''
import re import re
from ansible.module_utils.nxos import get_config, load_config, run_commands from ansible.module_utils.nxos import get_config, load_config
from ansible.module_utils.nxos import nxos_argument_spec, check_args from ansible.module_utils.nxos import nxos_argument_spec, check_args
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.netcfg import CustomNetworkConfig from ansible.module_utils.netcfg import CustomNetworkConfig
import re
PARAM_TO_COMMAND_KEYMAP = { PARAM_TO_COMMAND_KEYMAP = {
'vrf': 'vrf',
'ospf': 'ospf',
'router_id': 'router-id', 'router_id': 'router-id',
'default_metric': 'default-metric', 'default_metric': 'default-metric',
'log_adjacency': 'log-adjacency-changes', 'log_adjacency': 'log-adjacency-changes',
@ -205,24 +169,19 @@ PARAM_TO_DEFAULT_KEYMAP = {
} }
def invoke(name, *args, **kwargs):
func = globals().get(name)
if func:
return func(*args, **kwargs)
def get_value(arg, config, module): def get_value(arg, config, module):
REGEX = re.compile(r'(?:{0}\s)(?P<value>.*)$'.format(PARAM_TO_COMMAND_KEYMAP[arg]), re.M) command = PARAM_TO_COMMAND_KEYMAP.get(arg)
command_re = re.compile(r'(?:{0}\s)(?P<value>.*)$'.format(command), re.M)
value = '' value = ''
if PARAM_TO_COMMAND_KEYMAP[arg] in config: if command in config:
if arg == 'log_adjacency': if arg == 'log_adjacency':
if 'log-adjacency-changes detail' in config: if 'log-adjacency-changes detail' in config:
value = 'detail' value = 'detail'
else: else:
value = 'log' value = 'log'
else: else:
value_list = REGEX.search(config).group('value').split() value_list = command_re.search(config).group('value').split()
if 'hold' in arg: if 'hold' in arg:
value = value_list[1] value = value_list[1]
elif 'max' in arg: elif 'max' in arg:
@ -269,14 +228,10 @@ def get_existing(module, args):
def apply_key_map(key_map, table): def apply_key_map(key_map, table):
new_dict = {} new_dict = {}
for key, value in table.items(): for key in table:
new_key = key_map.get(key) new_key = key_map.get(key)
if new_key: if new_key:
value = table.get(key) new_dict[new_key] = table.get(key)
if value:
new_dict[new_key] = value
else:
new_dict[new_key] = value
return new_dict return new_dict
@ -370,8 +325,7 @@ def main():
ospf=dict(required=True, type='str'), ospf=dict(required=True, type='str'),
router_id=dict(required=False, type='str'), router_id=dict(required=False, type='str'),
default_metric=dict(required=False, type='str'), default_metric=dict(required=False, type='str'),
log_adjacency=dict(required=False, type='str', log_adjacency=dict(required=False, type='str', choices=['log', 'detail', 'default']),
choices=['log', 'detail', 'default']),
timer_throttle_lsa_start=dict(required=False, type='str'), timer_throttle_lsa_start=dict(required=False, type='str'),
timer_throttle_lsa_hold=dict(required=False, type='str'), timer_throttle_lsa_hold=dict(required=False, type='str'),
timer_throttle_lsa_max=dict(required=False, type='str'), timer_throttle_lsa_max=dict(required=False, type='str'),
@ -379,8 +333,7 @@ def main():
timer_throttle_spf_hold=dict(required=False, type='str'), timer_throttle_spf_hold=dict(required=False, type='str'),
timer_throttle_spf_max=dict(required=False, type='str'), timer_throttle_spf_max=dict(required=False, type='str'),
auto_cost=dict(required=False, type='str'), auto_cost=dict(required=False, type='str'),
state=dict(choices=['present', 'absent'], default='present', state=dict(choices=['present', 'absent'], default='present', required=False),
required=False),
include_defaults=dict(default=True), include_defaults=dict(default=True),
config=dict(), config=dict(),
save=dict(type='bool', default=False) save=dict(type='bool', default=False)
@ -388,33 +341,17 @@ def main():
argument_spec.update(nxos_argument_spec) argument_spec.update(nxos_argument_spec)
module = AnsibleModule(argument_spec=argument_spec, module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
supports_check_mode=True)
warnings = list() warnings = list()
check_args(module, warnings) check_args(module, warnings)
result = dict(changed=False, warnings=warnings)
state = module.params['state'] state = module.params['state']
args = [ args = PARAM_TO_COMMAND_KEYMAP.keys()
'vrf', existing = get_existing(module, args)
'ospf',
'router_id',
'default_metric',
'log_adjacency',
'timer_throttle_lsa_start',
'timer_throttle_lsa_hold',
'timer_throttle_lsa_max',
'timer_throttle_spf_start',
'timer_throttle_spf_hold',
'timer_throttle_spf_max',
'auto_cost'
]
existing = invoke('get_existing', module, args)
end_state = existing
proposed_args = dict((k, v) for k, v in module.params.items() proposed_args = dict((k, v) for k, v in module.params.items()
if v is not None and k in args) if v is not None and k in args)
proposed = {} proposed = {}
for key, value in proposed_args.items(): for key, value in proposed_args.items():
@ -427,28 +364,25 @@ def main():
value = PARAM_TO_DEFAULT_KEYMAP.get(key) value = PARAM_TO_DEFAULT_KEYMAP.get(key)
if value is None: if value is None:
value = 'default' value = 'default'
if existing.get(key) or (not existing.get(key) and value): if existing.get(key) != value:
proposed[key] = value proposed[key] = value
result = {} candidate = CustomNetworkConfig(indent=3)
if state == 'present' or (state == 'absent' and existing): if state == 'present':
candidate = CustomNetworkConfig(indent=3) state_present(module, existing, proposed, candidate)
invoke('state_%s' % state, module, existing, proposed, candidate) if state == 'absent' and existing:
response = load_config(module, candidate) state_absent(module, existing, proposed, candidate)
result.update(response)
if candidate:
candidate = candidate.items_text()
load_config(module, candidate)
result['changed'] = True
result['commands'] = candidate
else: else:
result['updates'] = [] result['commands'] = []
if module._verbosity > 0:
end_state = invoke('get_existing', module, args)
result['end_state'] = end_state
result['existing'] = existing
result['proposed'] = proposed_args
module.exit_json(**result) module.exit_json(**result)
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View file

@ -484,7 +484,6 @@ lib/ansible/modules/network/nxos/nxos_ntp.py
lib/ansible/modules/network/nxos/nxos_ntp_auth.py lib/ansible/modules/network/nxos/nxos_ntp_auth.py
lib/ansible/modules/network/nxos/nxos_ntp_options.py lib/ansible/modules/network/nxos/nxos_ntp_options.py
lib/ansible/modules/network/nxos/nxos_nxapi.py lib/ansible/modules/network/nxos/nxos_nxapi.py
lib/ansible/modules/network/nxos/nxos_ospf_vrf.py
lib/ansible/modules/network/nxos/nxos_overlay_global.py lib/ansible/modules/network/nxos/nxos_overlay_global.py
lib/ansible/modules/network/nxos/nxos_pim.py lib/ansible/modules/network/nxos/nxos_pim.py
lib/ansible/modules/network/nxos/nxos_pim_interface.py lib/ansible/modules/network/nxos/nxos_pim_interface.py

View file

@ -0,0 +1,69 @@
# (c) 2016 Red Hat Inc.
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import json
from ansible.compat.tests.mock import patch
from ansible.modules.network.nxos import nxos_ospf_vrf
from .nxos_module import TestNxosModule, load_fixture, set_module_args
class TestNxosOspfVrfModule(TestNxosModule):
module = nxos_ospf_vrf
def setUp(self):
self.mock_load_config = patch('ansible.modules.network.nxos.nxos_ospf_vrf.load_config')
self.load_config = self.mock_load_config.start()
self.mock_get_config = patch('ansible.modules.network.nxos.nxos_ospf_vrf.get_config')
self.get_config = self.mock_get_config.start()
def tearDown(self):
self.mock_load_config.stop()
self.mock_get_config.stop()
def load_fixtures(self, commands=None):
self.load_config.return_value = None
def test_nxos_ospf_vrf_present(self):
set_module_args(dict(ospf=1,
vrf='test',
timer_throttle_spf_start=50,
timer_throttle_spf_hold=1000,
timer_throttle_spf_max=2000,
timer_throttle_lsa_start=60,
timer_throttle_lsa_hold=1100,
timer_throttle_lsa_max=3000,
state='present'))
result = self.execute_module(changed=True)
self.assertEqual(sorted(result['commands']),
sorted(['router ospf 1',
'vrf test',
'timers throttle lsa 60 1100 3000',
'ospf 1',
'timers throttle spf 50 1000 2000',
'vrf test']))
def test_nxos_ospf_vrf_absent(self):
set_module_args(dict(ospf=1, vrf='test', state='absent'))
result = self.execute_module(changed=False)
self.assertEqual(result['commands'], [])