diff --git a/lib/ansible/modules/network/nxos/nxos_l3_interface.py b/lib/ansible/modules/network/nxos/nxos_l3_interface.py index 8d1d1cb1f40..715c96dd69b 100644 --- a/lib/ansible/modules/network/nxos/nxos_l3_interface.py +++ b/lib/ansible/modules/network/nxos/nxos_l3_interface.py @@ -99,7 +99,7 @@ def search_obj_in_list(name, lst): return o -def map_obj_to_commands(updates, module): +def map_obj_to_commands(updates, module, warnings): commands = list() want, have = updates @@ -112,24 +112,26 @@ def map_obj_to_commands(updates, module): obj_in_have = search_obj_in_list(name, have) - if state == 'absent' and obj_in_have: + if not obj_in_have: + warnings.append('Unknown interface {0}'.format(name)) + elif state == 'absent': command = [] if obj_in_have['name'] == name: - if ipv4 and obj_in_have['ipv4']: + if ipv4 and ipv4 == obj_in_have['ipv4']: command.append('no ip address {0}'.format(ipv4)) - if ipv6 and obj_in_have['ipv6']: + if ipv6 and ipv6 in obj_in_have['ipv6']: command.append('no ipv6 address {0}'.format(ipv6)) if command: command.append('exit') command.insert(0, 'interface {0}'.format(name)) commands.extend(command) - elif state == 'present' and obj_in_have: + elif state == 'present': command = [] if obj_in_have['name'] == name: if ipv4 and ipv4 != obj_in_have['ipv4']: command.append('ip address {0}'.format(ipv4)) - if ipv6 and ipv6 != obj_in_have['ipv6']: + if ipv6 and ipv6 not in obj_in_have['ipv6']: command.append('ipv6 address {0}'.format(ipv6)) if command: command.append('exit') @@ -174,7 +176,7 @@ def map_config_to_obj(want, module): for w in want: parents = ['interface {0}'.format(w['name'])] config = netcfg.get_section(parents) - obj = dict(name=None, ipv4=None, ipv6=None) + obj = dict(name=None, ipv4=None, ipv6=[]) if config: match_name = re.findall(r'interface (\S+)', config, re.M) @@ -187,9 +189,9 @@ def map_config_to_obj(want, module): match_ipv6 = re.findall(r'ipv6 address (\S+)', config, re.M) if match_ipv6: - obj['ipv6'] = match_ipv6[0] + obj['ipv6'] = match_ipv6 - objs.append(obj) + objs.append(obj) return objs @@ -224,15 +226,15 @@ def main(): warnings = list() result = {'changed': False} - if warnings: - result['warnings'] = warnings want = map_params_to_obj(module) have = map_config_to_obj(want, module) - commands = map_obj_to_commands((want, have), module) + commands = map_obj_to_commands((want, have), module, warnings) result['commands'] = commands + if warnings: + result['warnings'] = warnings if commands: if not module.check_mode: load_config(module, commands) diff --git a/test/units/modules/network/nxos/fixtures/nxos_l3_interface/ethernet_noshut b/test/units/modules/network/nxos/fixtures/nxos_l3_interface/ethernet_noshut new file mode 100644 index 00000000000..b0407edc491 --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_l3_interface/ethernet_noshut @@ -0,0 +1,3 @@ +interface Ethernet1/1 + description Configured by Ansible + no shutdown diff --git a/test/units/modules/network/nxos/fixtures/nxos_l3_interface/ethernet_noshut_ipv4_ipv6 b/test/units/modules/network/nxos/fixtures/nxos_l3_interface/ethernet_noshut_ipv4_ipv6 new file mode 100644 index 00000000000..3e4f197876f --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_l3_interface/ethernet_noshut_ipv4_ipv6 @@ -0,0 +1,5 @@ +interface Ethernet1/1 + description Configured by Ansible + ip address 192.168.0.1/24 + ipv6 address 2001:db8::1/124 + no shutdown diff --git a/test/units/modules/network/nxos/fixtures/nxos_l3_interface/ethernet_noshut_multiple_ipv6 b/test/units/modules/network/nxos/fixtures/nxos_l3_interface/ethernet_noshut_multiple_ipv6 new file mode 100644 index 00000000000..9013b1348e1 --- /dev/null +++ b/test/units/modules/network/nxos/fixtures/nxos_l3_interface/ethernet_noshut_multiple_ipv6 @@ -0,0 +1,7 @@ +interface Ethernet1/1 + description Configured by Ansible + ip address 192.168.0.1/24 + ipv6 address 2001:db8:1::1/124 + ipv6 address 2001:db8:2::1/124 + ipv6 address 2001:db8::1/124 + no shutdown diff --git a/test/units/modules/network/nxos/test_nxos_l3_interface.py b/test/units/modules/network/nxos/test_nxos_l3_interface.py new file mode 100644 index 00000000000..0257793768c --- /dev/null +++ b/test/units/modules/network/nxos/test_nxos_l3_interface.py @@ -0,0 +1,226 @@ +# Copyright: (c) 2019, Olivier Blin +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from units.compat.mock import patch +from ansible.modules.network.nxos import nxos_l3_interface +from .nxos_module import TestNxosModule, load_fixture, set_module_args + + +class TestNxosL3InterfaceModule(TestNxosModule): + + module = nxos_l3_interface + + def setUp(self): + super(TestNxosL3InterfaceModule, self).setUp() + + self.mock_load_config = patch('ansible.modules.network.nxos.nxos_l3_interface.load_config') + self.load_config = self.mock_load_config.start() + + self.mock_get_config = patch('ansible.modules.network.nxos.nxos_l3_interface.get_config') + self.get_config = self.mock_get_config.start() + + def tearDown(self): + super(TestNxosL3InterfaceModule, self).tearDown() + self.mock_load_config.stop() + self.mock_get_config.stop() + + def load_fixtures(self, commands=None, device=''): + self.load_config.return_value = None + self.get_config.return_value = load_fixture('nxos_l3_interface', self.mode) + + def test_nxos_l3_interface_unknonw_ethernet(self): + self.mode = 'ethernet_noshut' + set_module_args(dict(name='Ethernet1/2', ipv4='192.168.0.1/24')) + result = self.execute_module(changed=False) + + # Add when missing + def test_nxos_l3_interface_add_missing_ipv4(self): + self.mode = 'ethernet_noshut' + set_module_args(dict(name='Ethernet1/1', ipv4='192.168.0.1/24')) + result = self.execute_module(changed=True) + self.assertEqual(result['commands'], ['interface Ethernet1/1', 'ip address 192.168.0.1/24', 'exit']) + + def test_nxos_l3_interface_add_missing_ipv4_on_e11(self): + self.mode = 'ethernet_noshut' + set_module_args(dict(name='et1/1', ipv4='192.168.0.1/24')) + result = self.execute_module(changed=True) + self.assertEqual(result['commands'], ['interface Ethernet1/1', 'ip address 192.168.0.1/24', 'exit']) + + def test_nxos_l3_interface_add_missing_ipv6(self): + self.mode = 'ethernet_noshut' + set_module_args(dict(name='Ethernet1/1', ipv6='2001:db8::1/124')) + result = self.execute_module(changed=True) + self.assertEqual(result['commands'], ['interface Ethernet1/1', 'ipv6 address 2001:db8::1/124', 'exit']) + + def test_nxos_l3_interface_add_missing_ipv4_and_ipv6(self): + self.mode = 'ethernet_noshut' + set_module_args(dict(name='Ethernet1/1', ipv4='192.168.0.1/24', ipv6='2001:db8::1/124')) + result = self.execute_module(changed=True) + self.assertEqual(result['commands'], ['interface Ethernet1/1', 'ip address 192.168.0.1/24', 'ipv6 address 2001:db8::1/124', 'exit']) + + # Add when existing + def test_nxos_l3_interface_add_existing_ipv4(self): + self.mode = 'ethernet_noshut_ipv4_ipv6' + set_module_args(dict(name='Ethernet1/1', ipv4='192.168.0.1/24')) + result = self.execute_module() + + def test_nxos_l3_interface_add_existing_ipv4_on_e11(self): + self.mode = 'ethernet_noshut_ipv4_ipv6' + set_module_args(dict(name='et1/1', ipv4='192.168.0.1/24')) + result = self.execute_module() + + def test_nxos_l3_interface_add_existing_ipv6(self): + self.mode = 'ethernet_noshut_ipv4_ipv6' + set_module_args(dict(name='Ethernet1/1', ipv6='2001:db8::1/124')) + result = self.execute_module() + + def test_nxos_l3_interface_add_existing_ipv4_and_ipv6(self): + self.mode = 'ethernet_noshut_ipv4_ipv6' + set_module_args(dict(name='Ethernet1/1', ipv4='192.168.0.1/24', ipv6='2001:db8::1/124')) + result = self.execute_module() + + def test_nxos_l3_interface_new_ipv4_and_ipv6(self): + self.mode = 'ethernet_noshut_ipv4_ipv6' + set_module_args(dict(name='Ethernet1/1', ipv4='192.168.0.2/24', ipv6='2001:db8::2/124')) + result = self.execute_module(changed=True) + self.assertEqual(result['commands'], ['interface Ethernet1/1', 'ip address 192.168.0.2/24', 'ipv6 address 2001:db8::2/124', 'exit']) + + # Add when existing with multiple IPv6 + def test_nxos_l3_interface_multiple_ipv6_add_first(self): + self.mode = 'ethernet_noshut_multiple_ipv6' + set_module_args(dict(name='Ethernet1/1', ipv6='2001:db8::1/124')) + result = self.execute_module() + + def test_nxos_l3_interface_multiple_ipv6_add_last(self): + self.mode = 'ethernet_noshut_multiple_ipv6' + set_module_args(dict(name='Ethernet1/1', ipv6='2001:db8:2::1/124')) + result = self.execute_module() + + # Add aggregate + def test_nxos_l3_interface_add_missing_with_empty_aggregate(self): + self.mode = 'ethernet_noshut' + set_module_args(dict(aggregate=[])) + result = self.execute_module() + + def test_nxos_l3_interface_add_missing_with_aggregate(self): + self.mode = 'ethernet_noshut' + set_module_args(dict(aggregate=[ + dict(name='Ethernet1/1', ipv4='192.168.0.2/24', ipv6='2001:db8::2/124'), + dict(name='Ethernet1/1', ipv6='2001:db8:1::2/124'), + dict(name='Ethernet1/1', ipv6='2001:db8:2::2/124')])) + result = self.execute_module(changed=True) + self.assertEqual(result['commands'], [ + 'interface Ethernet1/1', 'ip address 192.168.0.2/24', 'ipv6 address 2001:db8::2/124', 'exit', + 'interface Ethernet1/1', 'ipv6 address 2001:db8:1::2/124', 'exit', + 'interface Ethernet1/1', 'ipv6 address 2001:db8:2::2/124', 'exit']) + + # Rem when missing + def test_nxos_l3_interface_rem_missing_ipv4(self): + self.mode = 'ethernet_noshut' + set_module_args(dict(name='Ethernet1/1', ipv4='192.168.0.1/24', state='absent')) + result = self.execute_module() + + def test_nxos_l3_interface_rem_missing_ipv4_on_e11(self): + self.mode = 'ethernet_noshut' + set_module_args(dict(name='et1/1', ipv4='192.168.0.1/24', state='absent')) + result = self.execute_module() + + def test_nxos_l3_interface_rem_missing_ipv6(self): + self.mode = 'ethernet_noshut' + set_module_args(dict(name='Ethernet1/1', ipv6='2001:db8::1/124', state='absent')) + result = self.execute_module() + + def test_nxos_l3_interface_rem_missing_ipv4_and_ipv6(self): + self.mode = 'ethernet_noshut' + set_module_args(dict(name='Ethernet1/1', ipv4='192.168.0.1/24', ipv6='2001:db8::1/124', state='absent')) + result = self.execute_module() + + # Rem when existing + def test_nxos_l3_interface_rem_existing_ipv4(self): + self.mode = 'ethernet_noshut_ipv4_ipv6' + set_module_args(dict(name='Ethernet1/1', ipv4='192.168.0.1/24', state='absent')) + result = self.execute_module(changed=True) + self.assertEqual(result['commands'], ['interface Ethernet1/1', 'no ip address 192.168.0.1/24', 'exit']) + + def test_nxos_l3_interface_rem_existing_ipv4_on_e11(self): + self.mode = 'ethernet_noshut_ipv4_ipv6' + set_module_args(dict(name='et1/1', ipv4='192.168.0.1/24', state='absent')) + result = self.execute_module(changed=True) + self.assertEqual(result['commands'], ['interface Ethernet1/1', 'no ip address 192.168.0.1/24', 'exit']) + + def test_nxos_l3_interface_rem_existing_ipv6(self): + self.mode = 'ethernet_noshut_ipv4_ipv6' + set_module_args(dict(name='Ethernet1/1', ipv6='2001:db8::1/124', state='absent')) + result = self.execute_module(changed=True) + self.assertEqual(result['commands'], ['interface Ethernet1/1', 'no ipv6 address 2001:db8::1/124', 'exit']) + + def test_nxos_l3_interface_rem_existing_ipv4_and_ipv6(self): + self.mode = 'ethernet_noshut_ipv4_ipv6' + set_module_args(dict(name='Ethernet1/1', ipv4='192.168.0.1/24', ipv6='2001:db8::1/124', state='absent')) + result = self.execute_module(changed=True) + self.assertEqual(result['commands'], ['interface Ethernet1/1', 'no ip address 192.168.0.1/24', 'no ipv6 address 2001:db8::1/124', 'exit']) + + # Rem when existing with multiple IPv6 + def test_nxos_l3_interface_multiple_ipv6_rem_first(self): + self.mode = 'ethernet_noshut_multiple_ipv6' + set_module_args(dict(name='Ethernet1/1', ipv6='2001:db8::1/124', state='absent')) + result = self.execute_module(changed=True) + self.assertEqual(result['commands'], ['interface Ethernet1/1', 'no ipv6 address 2001:db8::1/124', 'exit']) + + def test_nxos_l3_interface_multiple_ipv6_rem_last(self): + self.mode = 'ethernet_noshut_multiple_ipv6' + set_module_args(dict(name='Ethernet1/1', ipv6='2001:db8:2::1/124', state='absent')) + result = self.execute_module(changed=True) + self.assertEqual(result['commands'], ['interface Ethernet1/1', 'no ipv6 address 2001:db8:2::1/124', 'exit']) + + # Rem when missing with aggregate + def test_nxos_l3_interface_rem_with_empty_aggregate(self): + self.mode = 'ethernet_noshut_multiple_ipv6' + set_module_args(dict(aggregate=[], state='absent')) + result = self.execute_module() + + def test_nxos_l3_interface_rem_missing_with_aggregate(self): + self.mode = 'ethernet_noshut_multiple_ipv6' + set_module_args(dict(state='absent', aggregate=[ + dict(name='Ethernet1/1', ipv4='192.168.0.2/24', ipv6='2001:db8::2/124'), + dict(name='Ethernet1/1', ipv6='2001:db8:1::2/124'), + dict(name='Ethernet1/1', ipv6='2001:db8:2::2/124')])) + result = self.execute_module() + + # Rem when existing with aggregate + def test_nxos_l3_interface_rem_existing_with_aggregate(self): + self.mode = 'ethernet_noshut_multiple_ipv6' + set_module_args(dict(state='absent', aggregate=[ + dict(name='Ethernet1/1', ipv4='192.168.0.1/24', ipv6='2001:db8::1/124'), + dict(name='Ethernet1/1', ipv6='2001:db8:1::1/124'), + dict(name='Ethernet1/1', ipv6='2001:db8:2::1/124')])) + result = self.execute_module(changed=True) + self.assertEqual(result['commands'], [ + 'interface Ethernet1/1', 'no ip address 192.168.0.1/24', 'no ipv6 address 2001:db8::1/124', 'exit', + 'interface Ethernet1/1', 'no ipv6 address 2001:db8:1::1/124', 'exit', + 'interface Ethernet1/1', 'no ipv6 address 2001:db8:2::1/124', 'exit']) + + # Add itf only + def test_nxos_l3_interface_add_on_itf_only(self): + self.mode = 'ethernet_noshut' + set_module_args(dict(name='Ethernet1/1')) + result = self.execute_module(changed=True) + self.assertEqual(result['commands'], ['interface Ethernet1/1']) + + # Add unknown interface + def test_nxos_l3_interface_add_on_unknown_itf(self): + self.mode = 'ethernet_noshut' + set_module_args(dict(name='Ethernet1/2', ipv4='192.168.0.1/24')) + result = self.execute_module() + self.assertEqual(result['warnings'], ['Unknown interface Ethernet1/2']) + + # Rem unknown interface + def test_nxos_l3_interface_rem_on_unknown_itf(self): + self.mode = 'ethernet_noshut' + set_module_args(dict(name='Ethernet1/2', ipv4='192.168.0.1/24', state='absent')) + result = self.execute_module() + self.assertEqual(result['warnings'], ['Unknown interface Ethernet1/2'])