From e4a6d64bc5f84aaf6c2d6bcdd69bedfe979de7ce Mon Sep 17 00:00:00 2001 From: nitish-ks Date: Mon, 18 Nov 2024 21:45:22 -0800 Subject: [PATCH 1/6] Fix for vLan modules --- plugins/module_utils/api.py | 6 +++++- plugins/modules/nios_network.py | 3 ++- plugins/modules/nios_vlan.py | 5 ++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/plugins/module_utils/api.py b/plugins/module_utils/api.py index f78c5cee..f5431d88 100644 --- a/plugins/module_utils/api.py +++ b/plugins/module_utils/api.py @@ -417,6 +417,10 @@ def run(self, ib_obj_type, ib_spec): if 'default_value' in obj: obj['default_value'] = str(obj['default_value']) + if (ib_obj_type == NIOS_VLAN): + if 'parent' in current_object: + current_object['parent'] = current_object['parent']['_ref'] + # checks if the 'text' field has to be updated for the TXT Record if (ib_obj_type == NIOS_TXT_RECORD): text_obj = proposed_object["text"] @@ -696,7 +700,7 @@ def compare_objects(self, current_object, proposed_object): # If the lists are of a different length, the objects cannot be # equal, and False will be returned before comparing the list items # this code part will work for members' assignment - if (key in ('members', 'options', 'delegate_to', 'forwarding_servers', 'stub_members') + if (key in ('members', 'options', 'delegate_to', 'forwarding_servers', 'stub_members', 'vlans') and (len(proposed_item) != len(current_item))): return False diff --git a/plugins/modules/nios_network.py b/plugins/modules/nios_network.py index 532cc8e4..474ae64c 100644 --- a/plugins/modules/nios_network.py +++ b/plugins/modules/nios_network.py @@ -88,6 +88,7 @@ of values (see suboptions). When configuring suboptions at least one of C(name) or C(id) must be specified. type: list + default: [] elements: dict suboptions: name: @@ -430,7 +431,7 @@ def vlans(module): network=dict(required=True, aliases=['name', 'cidr'], ib_req=True), network_view=dict(default='default', ib_req=True), options=dict(type='list', elements='dict', options=option_spec, transform=options, default=[]), - vlans=dict(type='list', elements='dict', options=vlans_spec, transform=vlans), + vlans=dict(type='list', elements='dict', options=vlans_spec, transform=vlans, default=[]), template=dict(type='str'), extattrs=dict(type='dict'), comment=dict(), diff --git a/plugins/modules/nios_vlan.py b/plugins/modules/nios_vlan.py index b769d377..23709949 100644 --- a/plugins/modules/nios_vlan.py +++ b/plugins/modules/nios_vlan.py @@ -11,7 +11,7 @@ module: nios_vlan author: "Christoph Spatt (@edeka-spatt)" short_description: Configure Infoblox NIOS VLANs -version_added: "1.4.3" +version_added: "1.8.0" description: - Adds and/or removes instances of vlan objects from Infoblox NIOS servers. This module manages NIOS C(vlan) objects @@ -39,10 +39,9 @@ description: - Specifies the vlan parent to add or remove from the system. Can be either a C(vlanview) or C(vlanrange) - name. Feteches the required _ref object automatically. + name. Fetches the required _ref object automatically. If not specified defaults to vlan view C(default). type: str - default: default required: true comment: description: From 1b64e6c043f6f9315a38a0c74b28aa27356ab55a Mon Sep 17 00:00:00 2001 From: nitish-ks Date: Tue, 19 Nov 2024 00:37:55 -0800 Subject: [PATCH 2/6] Fixed sanity issues related to vlan parent --- plugins/modules/nios_network.py | 1 + plugins/modules/nios_vlan.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/modules/nios_network.py b/plugins/modules/nios_network.py index 474ae64c..0f16410c 100644 --- a/plugins/modules/nios_network.py +++ b/plugins/modules/nios_network.py @@ -103,6 +103,7 @@ description: - The name of the parent vlanview or vlanrange. type: str + default: default extattrs: description: - Allows for the configuration of Extensible Attributes on the diff --git a/plugins/modules/nios_vlan.py b/plugins/modules/nios_vlan.py index 23709949..25c3d926 100644 --- a/plugins/modules/nios_vlan.py +++ b/plugins/modules/nios_vlan.py @@ -42,7 +42,7 @@ name. Fetches the required _ref object automatically. If not specified defaults to vlan view C(default). type: str - required: true + default: default comment: description: - Configures a text string comment to be associated with the instance From fa931b84af09182661803dd157095bd675a563cd Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 19 Nov 2024 09:32:14 +0000 Subject: [PATCH 3/6] Removed trailing whitespaces --- plugins/modules/nios_network.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/nios_network.py b/plugins/modules/nios_network.py index 0f16410c..2b3752c3 100644 --- a/plugins/modules/nios_network.py +++ b/plugins/modules/nios_network.py @@ -401,7 +401,7 @@ def vlans(module): vlan_filtered['parent'] = obj_vlanrange[0]['_ref'] else: module.fail_json(msg='VLAN View/Range \'%s\' cannot be found.' % vlan_filtered['parent']) - + obj_vlan = wapi.get_object('vlan', vlan_filtered) if obj_vlan: @@ -410,7 +410,7 @@ def vlans(module): module.fail_json(msg='VLAN `%s` cannot be found.' % vlan['name']) return vlans_list - + option_spec = dict( # one of name or num is required; enforced by the function options() name=dict(), From 33d914372693f0e44edd175a7a17c54103f26563 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Wed, 4 Dec 2024 10:33:21 +0000 Subject: [PATCH 4/6] Fixed vLan parent transform --- plugins/modules/nios_vlan.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/modules/nios_vlan.py b/plugins/modules/nios_vlan.py index 25c3d926..d7268c2e 100644 --- a/plugins/modules/nios_vlan.py +++ b/plugins/modules/nios_vlan.py @@ -150,10 +150,10 @@ def parent_transform(module): if module.params['parent']: parent_obj_vlanview = wapi.get_object('vlanview', {'name': module.params['parent']}) parent_obj_vlanrange = wapi.get_object('vlanrange', {'name': module.params['parent']}) - if parent_obj_vlanview and not parent_obj_vlanrange: - parent_ref = parent_obj_vlanview[0]['_ref'] - elif not parent_obj_vlanview and parent_obj_vlanrange: + if parent_obj_vlanrange: parent_ref = parent_obj_vlanrange[0]['_ref'] + elif parent_obj_vlanview: + parent_ref = parent_obj_vlanview[0]['_ref'] else: module.fail_json(msg='VLAN View/Range \'%s\' cannot be found.' % module.params['parent']) return parent_ref From cc2325a3f66db3580f175a2b6a9709f2f63cea84 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Wed, 4 Dec 2024 10:44:31 +0000 Subject: [PATCH 5/6] Fixed vLan transform in network --- plugins/modules/nios_network.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/modules/nios_network.py b/plugins/modules/nios_network.py index 2b3752c3..1f108cc1 100644 --- a/plugins/modules/nios_network.py +++ b/plugins/modules/nios_network.py @@ -395,10 +395,10 @@ def vlans(module): if 'parent' in vlan_filtered: obj_vlanview = wapi.get_object('vlanview', {'name': vlan_filtered['parent']}) obj_vlanrange = wapi.get_object('vlanrange', {'name': vlan_filtered['parent']}) - if obj_vlanview and not obj_vlanrange: - vlan_filtered['parent'] = obj_vlanview[0]['_ref'] - elif not obj_vlanview and obj_vlanrange: + if obj_vlanrange: vlan_filtered['parent'] = obj_vlanrange[0]['_ref'] + elif obj_vlanview: + vlan_filtered['parent'] = obj_vlanview[0]['_ref'] else: module.fail_json(msg='VLAN View/Range \'%s\' cannot be found.' % vlan_filtered['parent']) From f12c22669e1e45c0222094b9a33419b599bee475 Mon Sep 17 00:00:00 2001 From: Nitish KS Date: Thu, 12 Dec 2024 16:59:56 +0530 Subject: [PATCH 6/6] Added unit tests for vLAN --- .../unit/plugins/modules/test_nios_network.py | 90 +++++++++ tests/unit/plugins/modules/test_nios_vlan.py | 180 ++++++++++++++++++ 2 files changed, 270 insertions(+) create mode 100644 tests/unit/plugins/modules/test_nios_vlan.py diff --git a/tests/unit/plugins/modules/test_nios_network.py b/tests/unit/plugins/modules/test_nios_network.py index df9b0464..29f0e8d2 100644 --- a/tests/unit/plugins/modules/test_nios_network.py +++ b/tests/unit/plugins/modules/test_nios_network.py @@ -314,3 +314,93 @@ def test_nios_network_ipv4_update_with_use_logic_filter_rules(self): 'use_logic_filter_rules': True, 'logic_filter_rules': []} ) + + def test_nios_network_ipv4_create_with_vlan(self): + self.module.params = {'provider': None, 'state': 'present', 'network': '192.168.10.0/24', + 'comment': None, 'extattrs': None, 'vlans': [{'name':'ansible_vlan', + 'parent': 'default' ,'id': '10'}]} + + test_object = None + test_spec = { + "network": {"ib_req": True}, + "comment": {}, + "extattrs": {}, + "vlans": {} + } + + wapi = self._get_wapi(test_object) + res = wapi.run('NIOS_IPV4_NETWORK', test_spec) + + self.assertTrue(res['changed']) + wapi.create_object.assert_called_once_with('NIOS_IPV4_NETWORK', {'network': '192.168.10.0/24', + 'vlans': [{'name':'ansible_vlan', + 'parent': 'default' ,'id': '10'}] + } + ) + + def test_nios_network_ipv4_update_vlan(self): + self.module.params = {'provider': None, 'state': 'present', 'network': '192.168.10.0/24', + 'comment': None, 'extattrs': None, 'vlans': [{'name':'ansible_vlan1', + 'parent': 'default' ,'id': '10'}, + {'name':'ansible_vlan2', + 'parent': 'default' ,'id': '20'}]} + ref = "network/ZG5zLm5ldHdvcmtfdmlldyQw:default/true" + + test_object = [ + { + "comment": "test comment", + "_ref": ref, + "network": "192.168.10.0/24", + "vlans": [{'name':'ansible_vlan1', 'parent': 'default' ,'id': '10'}] + } + ] + test_spec = { + "network": {"ib_req": True}, + "comment": {}, + "extattrs": {}, + "vlans": {} + } + + wapi = self._get_wapi(test_object) + res = wapi.run('NIOS_IPV4_NETWORK', test_spec) + + self.assertTrue(res['changed']) + + wapi.update_object.assert_called_once_with(ref, {'network': '192.168.10.0/24', + 'vlans': [{'name':'ansible_vlan1', + 'parent': 'default' ,'id': '10'}, + {'name':'ansible_vlan2', + 'parent': 'default' ,'id': '20'}] + } + ) + + def test_nios_network_ipv4_remove_vlan(self): + self.module.params = {'provider': None, 'state': 'present', 'network': '192.168.10.0/24', + 'comment': None, 'extattrs': None, 'vlans': []} + ref = "network/ZG5zLm5ldHdvcmtfdmlldyQw:default/true" + + test_object = [ + { + "comment": "test comment", + "_ref": ref, + "network": "192.168.10.0/24", + "vlans": [{'name':'ansible_vlan1', 'parent': 'default' ,'id': '10'}, + {'name':'ansible_vlan2', 'parent': 'default' ,'id': '20'} + ] + } + ] + test_spec = { + "network": {"ib_req": True}, + "comment": {}, + "extattrs": {}, + "vlans": {} + } + + wapi = self._get_wapi(test_object) + res = wapi.run('NIOS_IPV4_NETWORK', test_spec) + + self.assertTrue(res['changed']) + wapi.update_object.assert_called_once_with(ref, {'network': '192.168.10.0/24', + 'vlans': [] + } + ) diff --git a/tests/unit/plugins/modules/test_nios_vlan.py b/tests/unit/plugins/modules/test_nios_vlan.py new file mode 100644 index 00000000..8b1c5c98 --- /dev/null +++ b/tests/unit/plugins/modules/test_nios_vlan.py @@ -0,0 +1,180 @@ +# 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 . + +# Make coding more python3-ish + + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +from ansible_collections.infoblox.nios_modules.plugins.modules import nios_vlan +from ansible_collections.infoblox.nios_modules.plugins.module_utils import api +from ansible_collections.infoblox.nios_modules.tests.unit.compat.mock import patch, MagicMock, Mock +from .test_nios_module import TestNiosModule, load_fixture + + +class TestNiosVlanModule(TestNiosModule): + + module = nios_vlan + + def setUp(self): + super(TestNiosVlanModule, self).setUp() + self.module = MagicMock(name='ansible_collections.infoblox.nios_modules.plugins.modules.nios_vlan.WapiModule') + self.module.check_mode = False + self.module.params = {'provider': None} + self.mock_wapi = patch('ansible_collections.infoblox.nios_modules.plugins.modules.nios_vlan.WapiModule') + self.exec_command = self.mock_wapi.start() + self.mock_wapi_run = patch('ansible_collections.infoblox.nios_modules.plugins.modules.nios_vlan.WapiModule.run') + self.mock_wapi_run.start() + self.load_config = self.mock_wapi_run.start() + self.mock_check_type_dict = patch('ansible.module_utils.common.validation.check_type_dict') + self.mock_check_type_dict_obj = self.mock_check_type_dict.start() + + def tearDown(self): + super(TestNiosVlanModule, self).tearDown() + self.mock_wapi.stop() + self.mock_wapi_run.stop() + self.mock_check_type_dict.stop() + + def _get_wapi(self, test_object): + wapi = api.WapiModule(self.module) + wapi.get_object = Mock(name='get_object', return_value=test_object) + wapi.create_object = Mock(name='create_object') + wapi.update_object = Mock(name='update_object') + wapi.delete_object = Mock(name='delete_object') + return wapi + + def load_fixtures(self, commands=None): + self.exec_command.return_value = (0, load_fixture('nios_result.txt').strip(), None) + self.load_config.return_value = dict(diff=None, session='session') + + def test_nios_vlan_create(self): + self.module.params = {'provider': None, 'state': 'present', 'name': 'ansible_vlan', + 'parent': 'default', 'id': '10', 'comment': None, 'extattrs': None} + + test_object = None + + test_spec = { + "name": {"ib_req": True}, + "parent": {"ib_req": True}, + "id": {"ib_req": True}, + "comment": {}, + "extattrs": {} + } + + wapi = self._get_wapi(test_object) + print("WAPI: ", wapi.__dict__) + res = wapi.run('NIOS_VLAN', test_spec) + + self.assertTrue(res['changed']) + wapi.create_object.assert_called_once_with('NIOS_VLAN', {'name': 'ansible_vlan', + 'parent': 'default', 'id': '10'}) + + def test_nios_vlan_update_comment(self): + self.module.params = {'provider': None, 'state': 'present', 'name': 'ansible_vlan', + 'parent': 'default', 'id': '10', 'comment': 'updated comment', + 'contact': 'contact@email.com', 'department': 'IT', 'description': 'test', + 'reserved': True,'extattrs': None} + + ref = "vlan/ZG5zLm5ldHdvcmtfdmlldyQw:ansible_vlan" + test_object = [ + { + "comment": "test comment", + "_ref": ref, + "name": "ansible_vlan", + "parent": "default", + "id": "10", + "extattrs": {} + } + ] + + test_spec = { + "name": {"ib_req": True}, + "parent": {"ib_req": True}, + "id": {"ib_req": True}, + "comment": {}, + "contact": {}, + "department": {}, + "description": {}, + "reserved": {}, + "extattrs": {} + } + + wapi = self._get_wapi(test_object) + res = wapi.run('NIOS_VLAN', test_spec) + self.assertTrue(res['changed']) + wapi.update_object.assert_called_once_with( + ref, {'comment': 'updated comment', 'parent': 'default', 'id': '10', 'name': 'ansible_vlan', + 'contact': 'contact@email.com', 'department': 'IT', 'description': 'test', 'reserved': True} + ) + + def test_nios_vlan_remove(self): + self.module.params = {'provider': None, 'state': 'absent', 'name': 'ansible_vlan', + 'parent': 'default', 'id': '10', 'comment': None, 'extattrs': None} + + ref = "vlan/ZG5zLm5ldHdvcmtfdmlldyQw:ansible_vlan" + + test_object = [{ + "comment": "test comment", + "_ref": ref, + "name": "ansible_vlan", + "parent": "default", + "id": "10", + "extattrs": {'Site': {'value': 'test'}} + }] + + test_spec = { + "name": {"ib_req": True}, + "parent": {"ib_req": True}, + "id": {"ib_req": True}, + "comment": {}, + "extattrs": {} + } + + wapi = self._get_wapi(test_object) + res = wapi.run('NIOS_VLAN', test_spec) + + self.assertTrue(res['changed']) + wapi.delete_object.assert_called_once_with(ref) + + def test_nios_vlan_update_record_name(self): + self.module.params = {'provider': None, 'state': 'present', 'name': {'new_name': 'ansible_new_vlan', 'old_name': 'ansible_vlan'}, + 'parent': 'default', 'id': '10', 'comment': 'comment', 'extattrs': None} + + ref = "vlan/ZG5zLm5ldHdvcmtfdmlldyQw:ansible_new_vlan" + test_object = [ + { + "comment": "test comment", + "_ref": ref, + "name": "ansible_vlan", + "extattrs": {} + } + ] + + test_spec = { + "name": {"ib_req": True}, + "parent": {"ib_req": True}, + "id": {"ib_req": True}, + "comment": {}, + "extattrs": {} + } + + wapi = self._get_wapi(test_object) + res = wapi.run('NIOS_VLAN', test_spec) + + self.assertTrue(res['changed']) + wapi.update_object.assert_called_once_with(ref, {'name': 'ansible_new_vlan', 'parent': 'default', 'id': '10', + 'comment': 'comment'}) \ No newline at end of file