diff options
Diffstat (limited to 'test/units')
59 files changed, 0 insertions, 15336 deletions
diff --git a/test/units/module_utils/test_netapp.py b/test/units/module_utils/test_netapp.py deleted file mode 100644 index 828eaf96b4..0000000000 --- a/test/units/module_utils/test_netapp.py +++ /dev/null @@ -1,163 +0,0 @@ -# (c) 2018, NetApp Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -import pytest - -from ansible.module_utils.ansible_release import __version__ as ansible_version - -import ansible.module_utils.netapp as netapp_utils - -try: - from unittest.mock import patch, mock_open -except ImportError: - from mock import patch, mock_open - -from ansible.module_utils.six.moves.urllib.error import URLError -from ansible.module_utils.netapp import NetAppESeriesModule, create_multipart_formdata -from units.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase, set_module_args - - -class StubNetAppESeriesModule(NetAppESeriesModule): - def __init__(self): - super(StubNetAppESeriesModule, self).__init__(ansible_options={}) - - -class NetappTest(ModuleTestCase): - REQUIRED_PARAMS = {"api_username": "rw", - "api_password": "password", - "api_url": "http://localhost", - "ssid": "1"} - REQ_FUNC = "ansible.module_utils.netapp.request" - - def _set_args(self, args=None): - module_args = self.REQUIRED_PARAMS.copy() - if args is not None: - module_args.update(args) - set_module_args(module_args) - - def test_is_embedded_embedded_pass(self): - """Verify is_embedded successfully returns True when an embedded web service's rest api is inquired.""" - self._set_args() - with patch(self.REQ_FUNC, side_effect=[(200, {"version": "03.10.9000.0009"}), - (200, {"runningAsProxy": False})]): - base = StubNetAppESeriesModule() - self.assertTrue(base.is_embedded()) - with patch(self.REQ_FUNC, side_effect=[(200, {"version": "03.10.9000.0009"}), - (200, {"runningAsProxy": True})]): - base = StubNetAppESeriesModule() - self.assertFalse(base.is_embedded()) - - def test_is_embedded_fail(self): - """Verify exception is thrown when a web service's rest api fails to return about information.""" - self._set_args() - with patch(self.REQ_FUNC, side_effect=[(200, {"version": "03.10.9000.0009"}), Exception()]): - with self.assertRaisesRegexp(AnsibleFailJson, r"Failed to retrieve the webservices about information!"): - base = StubNetAppESeriesModule() - base.is_embedded() - with patch(self.REQ_FUNC, side_effect=[(200, {"version": "03.10.9000.0009"}), URLError(""), Exception()]): - with self.assertRaisesRegexp(AnsibleFailJson, r"Failed to retrieve the webservices about information!"): - base = StubNetAppESeriesModule() - base.is_embedded() - - def test_check_web_services_version_fail(self): - """Verify that an unacceptable rest api version fails.""" - minimum_required = "02.10.9000.0010" - test_set = ["02.10.9000.0009", "02.09.9000.0010", "01.10.9000.0010"] - - self._set_args() - base = StubNetAppESeriesModule() - base.web_services_version = minimum_required - base.is_embedded = lambda: True - for current_version in test_set: - with patch(self.REQ_FUNC, return_value=(200, {"version": current_version})): - with self.assertRaisesRegexp(AnsibleFailJson, r"version does not meet minimum version required."): - base._check_web_services_version() - - def test_check_web_services_version_pass(self): - """Verify that an unacceptable rest api version fails.""" - minimum_required = "02.10.9000.0010" - test_set = ["02.10.9000.0009", "02.09.9000.0010", "01.10.9000.0010"] - - self._set_args() - base = StubNetAppESeriesModule() - base.web_services_version = minimum_required - base.is_embedded = lambda: True - for current_version in test_set: - with patch(self.REQ_FUNC, return_value=(200, {"version": current_version})): - with self.assertRaisesRegexp(AnsibleFailJson, r"version does not meet minimum version required."): - base._check_web_services_version() - - def test_check_check_web_services_version_fail(self): - """Verify exception is thrown when api url is invalid.""" - invalid_url_forms = ["localhost:8080/devmgr/v2", - "http:///devmgr/v2"] - - invalid_url_protocols = ["ssh://localhost:8080/devmgr/v2"] - - for url in invalid_url_forms: - self._set_args({"api_url": url}) - with patch(self.REQ_FUNC, return_value=(200, {"runningAsProxy": True})): - with self.assertRaisesRegexp(AnsibleFailJson, r"Failed to provide valid API URL."): - base = StubNetAppESeriesModule() - base._check_web_services_version() - - for url in invalid_url_protocols: - self._set_args({"api_url": url}) - with patch(self.REQ_FUNC, return_value=(200, {"runningAsProxy": True})): - with self.assertRaisesRegexp(AnsibleFailJson, r"Protocol must be http or https."): - base = StubNetAppESeriesModule() - base._check_web_services_version() - - -class MockONTAPConnection(object): - ''' mock a server connection to ONTAP host ''' - - def __init__(self, kind=None, parm1=None): - ''' save arguments ''' - self.type = kind - self.parm1 = parm1 - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'vserver': - xml = self.build_vserver_info(self.parm1) - self.xml_out = xml - return xml - - @staticmethod - def build_vserver_info(vserver): - ''' build xml data for vserser-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = netapp_utils.zapi.NaElement('attributes-list') - attributes.add_node_with_children('vserver-info', - **{'vserver-name': vserver}) - xml.add_child_elem(attributes) - return xml - - -@pytest.mark.skipif(not netapp_utils.has_netapp_lib(), reason="skipping as missing required netapp_lib") -def test_ems_log_event_version(): - ''' validate Ansible version is correctly read ''' - source = 'unittest' - server = MockONTAPConnection() - netapp_utils.ems_log_event(source, server) - xml = server.xml_in - version = xml.get_child_content('app-version') - assert version == ansible_version - print("Ansible version: %s" % ansible_version) - - -@pytest.mark.skipif(not netapp_utils.has_netapp_lib(), reason="skipping as missing required netapp_lib") -def test_get_cserver(): - ''' validate cluster vserser name is correctly retrieved ''' - svm_name = 'svm1' - server = MockONTAPConnection('vserver', svm_name) - cserver = netapp_utils.get_cserver(server) - assert cserver == svm_name diff --git a/test/units/modules/storage/netapp/test_na_ontap_aggregate.py b/test/units/modules/storage/netapp/test_na_ontap_aggregate.py deleted file mode 100644 index e9766af468..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_aggregate.py +++ /dev/null @@ -1,217 +0,0 @@ -# (c) 2018-2019, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -""" unit tests for Ansible module: na_ontap_aggregate """ - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_aggregate \ - import NetAppOntapAggregate as my_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, parm1=None, parm2=None): - ''' save arguments ''' - self.type = kind - self.parm1 = parm1 - self.parm2 = parm2 - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'aggregate': - xml = self.build_aggregate_info(self.parm1, self.parm2) - elif self.type == 'aggregate_fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - @staticmethod - def build_aggregate_info(vserver, aggregate): - ''' build xml data for aggregatte and vserser-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 2, - 'attributes-list': - {'aggr-attributes': - {'aggregate-name': aggregate, - 'aggr-raid-attributes': - {'state': 'offline' - } - }, - }, - 'vserver-info': - {'vserver-name': vserver - } - } - xml.translate_struct(data) - print(xml.to_string()) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection('aggregate', '12', 'name') - # whether to use a mock or a simulator - self.onbox = False - - def set_default_args(self): - if self.onbox: - hostname = '10.193.74.78' - username = 'admin' - password = 'netapp1!' - name = 'name' - else: - hostname = 'hostname' - username = 'username' - password = 'password' - name = 'name' - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'name': name - }) - - def call_command(self, module_args): - ''' utility function to call apply ''' - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - # mock the connection - my_obj.server = MockONTAPConnection('aggregate', '12', 'test_name') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - return exc.value.args[0]['changed'] - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_is_mirrored(self): - module_args = { - 'disk_count': '2', - 'is_mirrored': 'true', - } - changed = self.call_command(module_args) - assert not changed - - def test_disks_list(self): - module_args = { - 'disk_count': '2', - 'disks': ['1', '2'], - } - changed = self.call_command(module_args) - assert not changed - - def test_mirror_disks(self): - module_args = { - 'disk_count': '2', - 'disks': ['1', '2'], - 'mirror_disks': ['3', '4'] - } - changed = self.call_command(module_args) - assert not changed - - def test_spare_pool(self): - module_args = { - 'disk_count': '2', - 'spare_pool': 'Pool1' - } - changed = self.call_command(module_args) - assert not changed - - def test_rename(self): - module_args = { - 'from_name': 'test_name2' - } - changed = self.call_command(module_args) - assert not changed - - def test_if_all_methods_catch_exception(self): - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'service_state': 'online'}) - module_args.update({'unmount_volumes': 'True'}) - module_args.update({'from_name': 'test_name2'}) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('aggregate_fail') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.aggr_get_iter(module_args.get('name')) - assert '' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.aggregate_online() - assert 'Error changing the state of aggregate' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.aggregate_offline() - assert 'Error changing the state of aggregate' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.create_aggr() - assert 'Error provisioning aggregate' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.delete_aggr() - assert 'Error removing aggregate' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.rename_aggregate() - assert 'Error renaming aggregate' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.asup_log_for_cserver = Mock(return_value=None) - my_obj.apply() - assert 'Error renaming: aggregate test_name2 does not exist' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_autosupport.py b/test/units/modules/storage/netapp/test_na_ontap_autosupport.py deleted file mode 100644 index 6f10f78f80..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_autosupport.py +++ /dev/null @@ -1,244 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_autosupport \ - import NetAppONTAPasup as asup_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'asup': - xml = self.build_asup_config_info(self.params) - self.xml_out = xml - return xml - - @staticmethod - def build_asup_config_info(asup_data): - ''' build xml data for asup-config ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = {'attributes': {'autosupport-config-info': { - 'node-name': asup_data['node_name'], - 'is-enabled': asup_data['is_enabled'], - 'is-support-enabled': asup_data['support'], - 'proxy-url': asup_data['proxy_url'], - 'post-url': asup_data['post_url'], - 'transport': asup_data['transport'], - 'is-node-in-subject': 'false', - 'from': 'test', - 'mail-hosts': [{'string': '1.2.3.4'}, {'string': '4.5.6.8'}], - 'noteto': [{'mail-address': 'abc@test.com'}, - {'mail-address': 'def@test.com'}], - }}} - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.mock_asup = { - 'node_name': 'test-vsim1', - 'transport': 'https', - 'support': 'false', - 'post_url': 'testbed.netapp.com/asupprod/post/1.0/postAsup', - 'proxy_url': 'something.com', - } - - def mock_args(self): - return { - 'node_name': self.mock_asup['node_name'], - 'transport': self.mock_asup['transport'], - 'support': self.mock_asup['support'], - 'post_url': self.mock_asup['post_url'], - 'proxy_url': self.mock_asup['proxy_url'], - 'hostname': 'host', - 'username': 'admin', - 'password': 'password', - } - - def get_asup_mock_object(self, kind=None, enabled='false'): - """ - Helper method to return an na_ontap_volume object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_volume object - """ - asup_obj = asup_module() - asup_obj.autosupport_log = Mock(return_value=None) - if kind is None: - asup_obj.server = MockONTAPConnection() - else: - data = self.mock_asup - data['is_enabled'] = enabled - asup_obj.server = MockONTAPConnection(kind='asup', data=data) - return asup_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - asup_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_enable_asup(self): - ''' a more interesting test ''' - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_asup_mock_object('asup').apply() - assert exc.value.args[0]['changed'] - - def test_disable_asup(self): - ''' a more interesting test ''' - # enable asup - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_asup_mock_object(kind='asup', enabled='true').apply() - assert exc.value.args[0]['changed'] - - def test_result_from_get(self): - ''' Check boolean and service_state conversion from get ''' - data = self.mock_args() - set_module_args(data) - obj = self.get_asup_mock_object(kind='asup', enabled='true') - # constructed based on valued passed in self.mock_asup and build_asup_config_info() - expected_dict = { - 'node_name': 'test-vsim1', - 'service_state': 'started', - 'support': False, - 'hostname_in_subject': False, - 'transport': self.mock_asup['transport'], - 'post_url': self.mock_asup['post_url'], - 'proxy_url': self.mock_asup['proxy_url'], - 'from_address': 'test', - 'mail_hosts': ['1.2.3.4', '4.5.6.8'], - 'partner_addresses': [], - 'to_addresses': [], - 'noteto': ['abc@test.com', 'def@test.com'] - } - result = obj.get_autosupport_config() - assert result == expected_dict - - def test_modify_config(self): - ''' Check boolean and service_state conversion from get ''' - data = self.mock_args() - data['transport'] = 'http' - data['post_url'] = 'somethingelse.com' - data['proxy_url'] = 'somethingelse.com' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_asup_mock_object('asup').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_autosupport.NetAppONTAPasup.get_autosupport_config') - def test_get_called(self, get_asup): - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_asup_mock_object('asup').apply() - get_asup.assert_called_with() - - @patch('ansible.modules.storage.netapp.na_ontap_autosupport.NetAppONTAPasup.modify_autosupport_config') - def test_modify_called(self, modify_asup): - data = self.mock_args() - data['transport'] = 'http' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_asup_mock_object('asup').apply() - modify_asup.assert_called_with({'transport': 'http', 'service_state': 'started'}) - - @patch('ansible.modules.storage.netapp.na_ontap_autosupport.NetAppONTAPasup.modify_autosupport_config') - @patch('ansible.modules.storage.netapp.na_ontap_autosupport.NetAppONTAPasup.get_autosupport_config') - def test_modify_not_called(self, get_asup, modify_asup): - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_asup_mock_object('asup').apply() - get_asup.assert_called_with() - modify_asup.assert_not_called() - - def test_modify_packet(self): - '''check XML construction for nested attributes like mail-hosts, noteto, partner-address, and to''' - data = self.mock_args() - set_module_args(data) - obj = self.get_asup_mock_object(kind='asup', enabled='true') - modify_dict = { - 'noteto': ['one@test.com'], - 'partner_addresses': ['firstpartner@test.com'], - 'mail_hosts': ['1.1.1.1'], - 'to_addresses': ['first@test.com'] - } - obj.modify_autosupport_config(modify_dict) - xml = obj.server.xml_in - for key in ['noteto', 'to', 'partner-address']: - assert xml[key] is not None - assert xml[key]['mail-address'] is not None - assert xml['noteto']['mail-address'] == modify_dict['noteto'][0] - assert xml['to']['mail-address'] == modify_dict['to_addresses'][0] - assert xml['partner-address']['mail-address'] == modify_dict['partner_addresses'][0] - assert xml['mail-hosts'] is not None - assert xml['mail-hosts']['string'] is not None - assert xml['mail-hosts']['string'] == modify_dict['mail_hosts'][0] diff --git a/test/units/modules/storage/netapp/test_na_ontap_broadcast_domain.py b/test/units/modules/storage/netapp/test_na_ontap_broadcast_domain.py deleted file mode 100644 index 98c13bea65..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_broadcast_domain.py +++ /dev/null @@ -1,308 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_broadcast_domain \ - import NetAppOntapBroadcastDomain as broadcast_domain_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.type = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'broadcast_domain': - xml = self.build_broadcast_domain_info(self.params) - self.xml_out = xml - return xml - - @staticmethod - def build_broadcast_domain_info(broadcast_domain_details): - ''' build xml data for broadcast_domain info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'net-port-broadcast-domain-info': { - 'broadcast-domain': broadcast_domain_details['name'], - 'ipspace': broadcast_domain_details['ipspace'], - 'mtu': broadcast_domain_details['mtu'], - 'ports': { - 'port-info': { - 'port': 'test_port_1' - } - } - } - - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.mock_broadcast_domain = { - 'name': 'test_broadcast_domain', - 'mtu': '1000', - 'ipspace': 'Default', - 'ports': 'test_port_1' - } - - def mock_args(self): - return { - 'name': self.mock_broadcast_domain['name'], - 'ipspace': self.mock_broadcast_domain['ipspace'], - 'mtu': self.mock_broadcast_domain['mtu'], - 'ports': self.mock_broadcast_domain['ports'], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - - def get_broadcast_domain_mock_object(self, kind=None, data=None): - """ - Helper method to return an na_ontap_volume object - :param kind: passes this param to MockONTAPConnection() - :param data: passes this param to MockONTAPConnection() - :return: na_ontap_volume object - """ - broadcast_domain_obj = broadcast_domain_module() - broadcast_domain_obj.asup_log_for_cserver = Mock(return_value=None) - broadcast_domain_obj.cluster = Mock() - broadcast_domain_obj.cluster.invoke_successfully = Mock() - if kind is None: - broadcast_domain_obj.server = MockONTAPConnection() - else: - if data is None: - broadcast_domain_obj.server = MockONTAPConnection(kind='broadcast_domain', data=self.mock_broadcast_domain) - else: - broadcast_domain_obj.server = MockONTAPConnection(kind='broadcast_domain', data=data) - return broadcast_domain_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - broadcast_domain_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_nonexistent_net_route(self): - ''' Test if get_broadcast_domain returns None for non-existent broadcast_domain ''' - set_module_args(self.mock_args()) - result = self.get_broadcast_domain_mock_object().get_broadcast_domain() - assert result is None - - def test_create_error_missing_broadcast_domain(self): - ''' Test if create throws an error if broadcast_domain is not specified''' - data = self.mock_args() - del data['name'] - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_broadcast_domain_mock_object('broadcast_domain').create_broadcast_domain() - msg = 'missing required arguments: name' - assert exc.value.args[0]['msg'] == msg - - @patch('ansible.modules.storage.netapp.na_ontap_broadcast_domain.NetAppOntapBroadcastDomain.create_broadcast_domain') - def test_successful_create(self, create_broadcast_domain): - ''' Test successful create ''' - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_broadcast_domain_mock_object().apply() - assert exc.value.args[0]['changed'] - create_broadcast_domain.assert_called_with() - - def test_create_idempotency(self): - ''' Test create idempotency ''' - set_module_args(self.mock_args()) - obj = self.get_broadcast_domain_mock_object('broadcast_domain') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert not exc.value.args[0]['changed'] - - def test_modify_mtu(self): - ''' Test successful modify mtu ''' - data = self.mock_args() - data['mtu'] = '1200' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_broadcast_domain_mock_object('broadcast_domain').apply() - assert exc.value.args[0]['changed'] - - def test_modify_ipspace_idempotency(self): - ''' Test modify ipsapce idempotency''' - data = self.mock_args() - data['ipspace'] = 'Cluster' - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_broadcast_domain_mock_object('broadcast_domain').apply() - msg = 'A domain ipspace can not be modified after the domain has been created.' - assert exc.value.args[0]['msg'] == msg - - @patch('ansible.modules.storage.netapp.na_ontap_broadcast_domain.NetAppOntapBroadcastDomain.add_broadcast_domain_ports') - def test_add_ports(self, add_broadcast_domain_ports): - ''' Test successful modify ports ''' - data = self.mock_args() - data['ports'] = 'test_port_1,test_port_2' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_broadcast_domain_mock_object('broadcast_domain').apply() - assert exc.value.args[0]['changed'] - add_broadcast_domain_ports.assert_called_with(['test_port_2']) - - @patch('ansible.modules.storage.netapp.na_ontap_broadcast_domain.NetAppOntapBroadcastDomain.delete_broadcast_domain_ports') - def test_delete_ports(self, delete_broadcast_domain_ports): - ''' Test successful modify ports ''' - data = self.mock_args() - data['ports'] = '' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_broadcast_domain_mock_object('broadcast_domain').apply() - assert exc.value.args[0]['changed'] - delete_broadcast_domain_ports.assert_called_with(['test_port_1']) - - @patch('ansible.modules.storage.netapp.na_ontap_broadcast_domain.NetAppOntapBroadcastDomain.modify_broadcast_domain') - @patch('ansible.modules.storage.netapp.na_ontap_broadcast_domain.NetAppOntapBroadcastDomain.split_broadcast_domain') - @patch('ansible.modules.storage.netapp.na_ontap_broadcast_domain.NetAppOntapBroadcastDomain.get_broadcast_domain') - def test_split_broadcast_domain(self, get_broadcast_domain, split_broadcast_domain, modify_broadcast_domain): - ''' Test successful split broadcast domain ''' - data = self.mock_args() - data['from_name'] = 'test_broadcast_domain' - data['name'] = 'test_broadcast_domain_2' - data['ports'] = 'test_port_2' - set_module_args(data) - current = { - 'name': 'test_broadcast_domain', - 'mtu': '1000', - 'ipspace': 'Default', - 'ports': ['test_port_1,test_port2'] - } - get_broadcast_domain.side_effect = [ - None, - current, - current - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_broadcast_domain_mock_object().apply() - assert exc.value.args[0]['changed'] - modify_broadcast_domain.assert_not_called() - split_broadcast_domain.assert_called_with() - - @patch('ansible.modules.storage.netapp.na_ontap_broadcast_domain.NetAppOntapBroadcastDomain.delete_broadcast_domain') - @patch('ansible.modules.storage.netapp.na_ontap_broadcast_domain.NetAppOntapBroadcastDomain.modify_broadcast_domain') - @patch('ansible.modules.storage.netapp.na_ontap_broadcast_domain.NetAppOntapBroadcastDomain.get_broadcast_domain') - def test_split_broadcast_domain_modify_delete(self, get_broadcast_domain, modify_broadcast_domain, delete_broadcast_domain): - ''' Test successful split broadcast domain ''' - data = self.mock_args() - data['from_name'] = 'test_broadcast_domain' - data['name'] = 'test_broadcast_domain_2' - data['ports'] = 'test_port_1,test_port_2' - data['mtu'] = '1200' - set_module_args(data) - - current = { - 'name': 'test_broadcast_domain', - 'mtu': '1000', - 'ipspace': 'Default', - 'ports': ['test_port_1,test_port2'] - } - get_broadcast_domain.side_effect = [ - None, - current, - current - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_broadcast_domain_mock_object().apply() - assert exc.value.args[0]['changed'] - delete_broadcast_domain.assert_called_with('test_broadcast_domain') - modify_broadcast_domain.assert_called_with() - - @patch('ansible.modules.storage.netapp.na_ontap_broadcast_domain.NetAppOntapBroadcastDomain.get_broadcast_domain') - def test_split_broadcast_domain_not_exist(self, get_broadcast_domain): - ''' Test successful split broadcast domain ''' - data = self.mock_args() - data['from_name'] = 'test_broadcast_domain' - data['name'] = 'test_broadcast_domain_2' - data['ports'] = 'test_port_2' - set_module_args(data) - - get_broadcast_domain.side_effect = [ - None, - None, - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_broadcast_domain_mock_object().apply() - msg = 'A domain can not be split if it does not exist.' - assert exc.value.args[0]['msg'], msg - - @patch('ansible.modules.storage.netapp.na_ontap_broadcast_domain.NetAppOntapBroadcastDomain.split_broadcast_domain') - def test_split_broadcast_domain_idempotency(self, split_broadcast_domain): - ''' Test successful split broadcast domain ''' - data = self.mock_args() - data['from_name'] = 'test_broadcast_domain' - data['ports'] = 'test_port_1' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_broadcast_domain_mock_object('broadcast_domain').apply() - assert exc.value.args[0]['changed'] is False - split_broadcast_domain.assert_not_called() diff --git a/test/units/modules/storage/netapp/test_na_ontap_cifs.py b/test/units/modules/storage/netapp/test_na_ontap_cifs.py deleted file mode 100644 index 95d56a6635..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_cifs.py +++ /dev/null @@ -1,227 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests ONTAP Ansible module: na_ontap_cifs ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_cifs \ - import NetAppONTAPCifsShare as my_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None): - ''' save arguments ''' - self.type = kind - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'cifs': - xml = self.build_cifs_info() - elif self.type == 'cifs_fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - @staticmethod - def build_cifs_info(): - ''' build xml data for cifs-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 1, 'attributes-list': {'cifs-share': { - 'share-name': 'test', - 'path': '/test', - 'vscan-fileop-profile': 'standard', - 'share-properties': [{'cifs-share-properties': 'browsable'}, - {'cifs-share-properties': 'oplocks'}], - 'symlink-properties': [{'cifs-share-symlink-properties': 'enable'}, - {'cifs-share-symlink-properties': 'read_only'}], - }}} - xml.translate_struct(data) - print(xml.to_string()) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.onbox = False - - def set_default_args(self): - if self.onbox: - hostname = '10.193.77.37' - username = 'admin' - password = 'netapp1!' - share_name = 'test' - path = '/test' - share_properties = 'browsable,oplocks' - symlink_properties = 'disable' - vscan_fileop_profile = 'standard' - vserver = 'abc' - else: - hostname = '10.193.77.37' - username = 'admin' - password = 'netapp1!' - share_name = 'test' - path = '/test' - share_properties = 'show_previous_versions' - symlink_properties = 'disable' - vscan_fileop_profile = 'no_scan' - vserver = 'abc' - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'share_name': share_name, - 'path': path, - 'share_properties': share_properties, - 'symlink_properties': symlink_properties, - 'vscan_fileop_profile': vscan_fileop_profile, - 'vserver': vserver - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_cifs_get_called(self): - ''' fetching details of cifs ''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - cifs_get = my_obj.get_cifs_share() - print('Info: test_cifs_share_get: %s' % repr(cifs_get)) - assert not bool(cifs_get) - - def test_ensure_apply_for_cifs_called(self): - ''' creating cifs share and checking idempotency ''' - module_args = {} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_cifs_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - if not self.onbox: - my_obj.server = MockONTAPConnection('cifs') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_cifs_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_cifs.NetAppONTAPCifsShare.create_cifs_share') - def test_cifs_create_called(self, create_cifs_share): - ''' creating cifs''' - module_args = {} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection() - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_cifs_apply: %s' % repr(exc.value)) - create_cifs_share.assert_called_with() - - @patch('ansible.modules.storage.netapp.na_ontap_cifs.NetAppONTAPCifsShare.delete_cifs_share') - def test_cifs_delete_called(self, delete_cifs_share): - ''' deleting cifs''' - module_args = {} - module_args.update(self.set_default_args()) - module_args['state'] = 'absent' - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('cifs') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_cifs_apply: %s' % repr(exc.value)) - delete_cifs_share.assert_called_with() - - @patch('ansible.modules.storage.netapp.na_ontap_cifs.NetAppONTAPCifsShare.modify_cifs_share') - def test_cifs_modify_called(self, modify_cifs_share): - ''' modifying cifs''' - module_args = {} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('cifs') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_cifs_apply: %s' % repr(exc.value)) - modify_cifs_share.assert_called_with() - - def test_if_all_methods_catch_exception(self): - module_args = {} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('cifs_fail') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.create_cifs_share() - assert 'Error creating cifs-share' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.delete_cifs_share() - assert 'Error deleting cifs-share' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.modify_cifs_share() - assert 'Error modifying cifs-share' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_cifs_server.py b/test/units/modules/storage/netapp/test_na_ontap_cifs_server.py deleted file mode 100644 index 92173c33d3..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_cifs_server.py +++ /dev/null @@ -1,221 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests ONTAP Ansible module: na_ontap_cifs_server ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_cifs_server \ - import NetAppOntapcifsServer as my_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, parm1=None, parm2=None): - ''' save arguments ''' - self.type = kind - self.parm1 = parm1 - self.parm2 = parm2 - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'cifs_server': - xml = self.build_vserver_info(self.parm1, self.parm2) - self.xml_out = xml - return xml - - @staticmethod - def build_vserver_info(cifs_server, admin_status): - ''' build xml data for cifs-server-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 1, - 'attributes-list': {'cifs-server-config': {'cifs-server': cifs_server, - 'administrative-status': admin_status}}} - xml.translate_struct(data) - print(xml.to_string()) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.use_vsim = False - - def set_default_args(self): - if self.use_vsim: - hostname = '10.193.77.154' - username = 'admin' - password = 'netapp1!' - cifs_server = 'test' - vserver = 'ansible_test' - else: - hostname = 'hostname' - username = 'username' - password = 'password' - cifs_server = 'name' - vserver = 'vserver' - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'cifs_server_name': cifs_server, - 'vserver': vserver - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_cifs_server_get_called(self): - ''' a more interesting test ''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - cifs_server = my_obj.get_cifs_server() - print('Info: test_cifs_server_get: %s' % repr(cifs_server)) - assert cifs_server is None - - def test_ensure_cifs_server_apply_for_create_called(self): - ''' creating cifs server and checking idempotency ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'cifs_server_name': 'create'}) - set_module_args(module_args) - my_obj = my_module() - if not self.use_vsim: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_cifs_server_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - if not self.use_vsim: - my_obj.server = MockONTAPConnection('cifs_server', 'create', 'up') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_cifs_server_apply_for_create: %s' % repr(exc.value)) - assert not exc.value.args[0]['changed'] - - def test_ensure_cifs_server_apply_for_delete_called(self): - ''' deleting cifs server and checking idempotency ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'cifs_server_name': 'delete'}) - set_module_args(module_args) - my_obj = my_module() - if not self.use_vsim: - my_obj.server = MockONTAPConnection('cifs_server', 'delete', 'up') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_cifs_server_apply: %s' % repr(exc.value)) - assert not exc.value.args[0]['changed'] - module_args.update({'state': 'absent'}) - set_module_args(module_args) - my_obj = my_module() - if not self.use_vsim: - my_obj.server = MockONTAPConnection('cifs_server', 'delete', 'up') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_cifs_server_delete: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - - def test_ensure_start_cifs_server_called(self): - ''' starting cifs server and checking idempotency ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'cifs_server_name': 'delete'}) - module_args.update({'service_state': 'started'}) - set_module_args(module_args) - my_obj = my_module() - if not self.use_vsim: - my_obj.server = MockONTAPConnection('cifs_server', 'test', 'up') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_ensure_start_cifs_server: %s' % repr(exc.value)) - assert not exc.value.args[0]['changed'] - module_args.update({'service_state': 'stopped'}) - set_module_args(module_args) - my_obj = my_module() - if not self.use_vsim: - my_obj.server = MockONTAPConnection('cifs_server', 'test', 'up') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_ensure_start_cifs_server: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - - def test_ensure_stop_cifs_server_called(self): - ''' stopping cifs server and checking idempotency ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'cifs_server_name': 'delete'}) - module_args.update({'service_state': 'stopped'}) - set_module_args(module_args) - my_obj = my_module() - if not self.use_vsim: - my_obj.server = MockONTAPConnection('cifs_server', 'test', 'down') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_ensure_stop_cifs_server: %s' % repr(exc.value)) - assert not exc.value.args[0]['changed'] - module_args.update({'service_state': 'started'}) - set_module_args(module_args) - my_obj = my_module() - if not self.use_vsim: - my_obj.server = MockONTAPConnection('cifs_server', 'test', 'down') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_ensure_stop_cifs_server: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_cluster.py b/test/units/modules/storage/netapp/test_na_ontap_cluster.py deleted file mode 100644 index 913344f101..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_cluster.py +++ /dev/null @@ -1,198 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests ONTAP Ansible module: na_ontap_cluster ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_cluster \ - import NetAppONTAPCluster as my_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None): - ''' save arguments ''' - self.type = kind - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'cluster': - xml = self.build_cluster_info() - elif self.type == 'cluster_fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - def autosupport_log(self): - ''' mock autosupport log''' - return None - - @staticmethod - def build_cluster_info(): - ''' build xml data for cluster-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'license-v2-status': {'package': 'cifs', 'method': 'site'}} - xml.translate_struct(data) - print(xml.to_string()) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.use_vsim = False - - def set_default_args(self): - if self.use_vsim: - hostname = '10.193.77.37' - username = 'admin' - password = 'netapp1!' - license_package = 'CIFS' - node_serial_number = '123' - license_code = 'AAA' - cluster_name = 'abc' - else: - hostname = '10.193.77.37' - username = 'admin' - password = 'netapp1!' - license_package = 'CIFS' - node_serial_number = '123' - cluster_ip_address = '0.0.0.0' - license_code = 'AAA' - cluster_name = 'abc' - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'license_package': license_package, - 'node_serial_number': node_serial_number, - 'license_code': license_code, - 'cluster_name': cluster_name, - 'cluster_ip_address': cluster_ip_address - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_license_get_called(self): - ''' fetching details of license ''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - license_get = my_obj.get_licensing_status() - print('Info: test_license_get: %s' % repr(license_get)) - assert not bool(license_get) - - def test_ensure_apply_for_cluster_called(self): - ''' creating license and checking idempotency ''' - module_args = {} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - my_obj.autosupport_log = Mock(return_value=None) - if not self.use_vsim: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_cluster_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - if not self.use_vsim: - my_obj.server = MockONTAPConnection('cluster') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_cluster_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_cluster.NetAppONTAPCluster.create_cluster') - def test_cluster_create_called(self, cluster_create): - ''' creating cluster''' - module_args = {} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - my_obj.autosupport_log = Mock(return_value=None) - if not self.use_vsim: - my_obj.server = MockONTAPConnection('cluster') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_cluster_apply: %s' % repr(exc.value)) - cluster_create.assert_called_with() - - def test_if_all_methods_catch_exception(self): - module_args = {} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.use_vsim: - my_obj.server = MockONTAPConnection('cluster_fail') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.get_licensing_status() - assert 'Error checking license status' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.create_cluster() - assert 'Error creating cluster' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.cluster_join() - assert 'Error adding node to cluster' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.license_v2_add() - assert 'Error adding license' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.license_v2_delete() - assert 'Error deleting license' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_cluster_peer.py b/test/units/modules/storage/netapp/test_na_ontap_cluster_peer.py deleted file mode 100644 index 7c38b30ac8..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_cluster_peer.py +++ /dev/null @@ -1,211 +0,0 @@ -''' unit tests ONTAP Ansible module: na_ontap_cluster_peer ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_cluster_peer \ - import NetAppONTAPClusterPeer as my_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, parm1=None): - ''' save arguments ''' - self.type = kind - self.data = parm1 - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'cluster_peer': - xml = self.build_cluster_peer_info(self.data) - self.xml_out = xml - return xml - - @staticmethod - def build_cluster_peer_info(parm1): - ''' build xml data for vserser-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'cluster-peer-info': { - 'cluster-name': parm1['dest_cluster_name'], - 'peer-addresses': parm1['dest_intercluster_lifs'] - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.mock_cluster_peer = { - 'source_intercluster_lifs': '1.2.3.4,1.2.3.5', - 'dest_intercluster_lifs': '1.2.3.6,1.2.3.7', - 'passphrase': 'netapp123', - 'dest_hostname': '10.20.30.40', - 'dest_cluster_name': 'cluster2', - 'hostname': 'hostname', - 'username': 'username', - 'password': 'password', - - } - - def mock_args(self): - return { - 'source_intercluster_lifs': self.mock_cluster_peer['source_intercluster_lifs'], - 'dest_intercluster_lifs': self.mock_cluster_peer['dest_intercluster_lifs'], - 'passphrase': self.mock_cluster_peer['passphrase'], - 'dest_hostname': self.mock_cluster_peer['dest_hostname'], - 'dest_cluster_name': 'cluster2', - 'hostname': 'hostname', - 'username': 'username', - 'password': 'password', - } - - def get_cluster_peer_mock_object(self, kind=None): - """ - Helper method to return an na_ontap_cluster_peer object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_cluster_peer object - """ - cluster_peer_obj = my_module() - cluster_peer_obj.asup_log_for_cserver = Mock(return_value=None) - cluster_peer_obj.cluster = Mock() - cluster_peer_obj.cluster.invoke_successfully = Mock() - if kind is None: - cluster_peer_obj.server = MockONTAPConnection() - cluster_peer_obj.dest_server = MockONTAPConnection() - else: - cluster_peer_obj.server = MockONTAPConnection(kind=kind, parm1=self.mock_cluster_peer) - cluster_peer_obj.dest_server = MockONTAPConnection(kind=kind, parm1=self.mock_cluster_peer) - return cluster_peer_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - @patch('ansible.modules.storage.netapp.na_ontap_cluster_peer.NetAppONTAPClusterPeer.cluster_peer_get') - def test_successful_create(self, cluster_peer_get): - ''' Test successful create ''' - set_module_args(self.mock_args()) - cluster_peer_get.side_effect = [ - None, - None - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_cluster_peer_mock_object().apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_cluster_peer.NetAppONTAPClusterPeer.cluster_peer_get') - def test_create_idempotency(self, cluster_peer_get): - ''' Test create idempotency ''' - set_module_args(self.mock_args()) - current1 = { - 'cluster_name': 'cluster1', - 'peer-addresses': '1.2.3.6,1.2.3.7' - } - current2 = { - 'cluster_name': 'cluster2', - 'peer-addresses': '1.2.3.4,1.2.3.5' - } - cluster_peer_get.side_effect = [ - current1, - current2 - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_cluster_peer_mock_object('cluster_peer').apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_cluster_peer.NetAppONTAPClusterPeer.cluster_peer_get') - def test_successful_delete(self, cluster_peer_get): - ''' Test delete existing interface ''' - data = self.mock_args() - data['state'] = 'absent' - data['source_cluster_name'] = 'cluster1' - set_module_args(data) - current1 = { - 'cluster_name': 'cluster1', - 'peer-addresses': '1.2.3.6,1.2.3.7' - } - current2 = { - 'cluster_name': 'cluster2', - 'peer-addresses': '1.2.3.4,1.2.3.5' - } - cluster_peer_get.side_effect = [ - current1, - current2 - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_cluster_peer_mock_object('cluster_peer').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_cluster_peer.NetAppONTAPClusterPeer.cluster_peer_get') - def test_delete_idempotency(self, cluster_peer_get): - ''' Test delete idempotency ''' - data = self.mock_args() - data['state'] = 'absent' - data['source_cluster_name'] = 'cluster2' - set_module_args(data) - cluster_peer_get.side_effect = [ - None, - None - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_cluster_peer_mock_object().apply() - assert not exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_command.py b/test/units/modules/storage/netapp/test_na_ontap_command.py deleted file mode 100644 index 4b5af4abdc..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_command.py +++ /dev/null @@ -1,169 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test for ONTAP Command Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_command \ - import NetAppONTAPCommand as my_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, parm1=None): - ''' save arguments ''' - self.type = kind - self.parm1 = parm1 - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - # print(xml.to_string()) - - if self.type == 'version': - priv = xml.get_child_content('priv') - xml = self.build_version(priv) - self.xml_out = xml - return xml - - @staticmethod - def build_version(priv): - ''' build xml data for version ''' - prefix = 'NetApp Release' - if priv == 'advanced': - prefix = '\n' + prefix - xml = netapp_utils.zapi.NaElement('results') - xml.add_new_child('cli-output', prefix) - # print(xml.to_string()) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection(kind='version') - # whether to use a mock or a simulator - self.use_vsim = False - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - @staticmethod - def set_default_args(vsim=False): - ''' populate hostname/username/password ''' - if vsim: - hostname = '10.10.10.10' - username = 'admin' - password = 'admin' - else: - hostname = 'hostname' - username = 'username' - password = 'password' - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'https': True, - 'validate_certs': False - }) - - def call_command(self, module_args, vsim=False): - ''' utility function to call apply ''' - module_args.update(self.set_default_args(vsim=vsim)) - set_module_args(module_args) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not vsim: - # mock the connection - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - msg = exc.value.args[0]['msg'] - return msg - - def test_default_priv(self): - ''' make sure privilege is not required ''' - module_args = { - 'command': 'version', - } - msg = self.call_command(module_args, vsim=self.use_vsim) - needle = b'<cli-output>NetApp Release' - assert needle in msg - print('Version (raw): %s' % msg) - - def test_admin_priv(self): - ''' make sure admin is accepted ''' - module_args = { - 'command': 'version', - 'privilege': 'admin', - } - msg = self.call_command(module_args, vsim=self.use_vsim) - needle = b'<cli-output>NetApp Release' - assert needle in msg - print('Version (raw): %s' % msg) - - def test_advanced_priv(self): - ''' make sure advanced is not required ''' - module_args = { - 'command': 'version', - 'privilege': 'advanced', - } - msg = self.call_command(module_args, vsim=self.use_vsim) - # Interestingly, the ZAPI returns a slightly different response - needle = b'<cli-output>\nNetApp Release' - assert needle in msg - print('Version (raw): %s' % msg) diff --git a/test/units/modules/storage/netapp/test_na_ontap_dns.py b/test/units/modules/storage/netapp/test_na_ontap_dns.py deleted file mode 100644 index 1efa98a81f..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_dns.py +++ /dev/null @@ -1,276 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests for Ansible module: na_ontap_dns''' - -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_dns \ - import NetAppOntapDns as dns_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') -HAS_NETAPP_ZAPI_MSG = "pip install netapp_lib is required" - - -# REST API canned responses when mocking send_request -SRR = { - # common responses - 'is_rest': (200, None), - 'is_zapi': (400, "Unreachable"), - 'empty_good': ({}, None), - 'end_of_sequence': (None, "Unexpected call to send_request"), - 'generic_error': (None, "Expected error"), - 'dns_record': ({"records": [{"domains": ['0.0.0.0'], - "servers": ['0.0.0.0'], - "svm": {"name": "svm1", "uuid": "02c9e252-41be-11e9-81d5-00a0986138f7"}}]}, None)} - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - request = xml.to_string().decode('utf-8') - if request.startswith("<ems-autosupport-log>"): - xml = None # or something that may the logger happy, and you don't need @patch anymore - # or - # xml = build_ems_log_response() - elif request == "<net-dns-get/>": - if self.kind == 'create': - raise netapp_utils.zapi.NaApiError(code="15661") - else: - xml = self.build_dns_status_info() - elif request.startswith("<net-dns-create>"): - xml = self.build_dns_status_info() - if self.kind == 'enable': - xml = self.build_dns_status_info() - self.xml_out = xml - return xml - - @staticmethod - def build_dns_status_info(): - xml = netapp_utils.zapi.NaElement('xml') - nameservers = [{'ip-address': '0.0.0.0'}] - domains = [{'string': '0.0.0.0'}] - attributes = {'num-records': 1, - 'attributes': {'net-dns-info': {'name-servers': nameservers, - 'domains': domains, - 'skip-config-validation': 'false'}}} - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' Unit tests for na_ontap_job_schedule ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - - def mock_args(self): - return { - 'state': 'present', - 'vserver': 'vserver', - 'nameservers': ['0.0.0.0'], - 'domains': ['0.0.0.0'], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - - def get_dns_mock_object(self, type='zapi', kind=None, status=None): - dns_obj = dns_module() - if type == 'zapi': - if kind is None: - dns_obj.server = MockONTAPConnection() - else: - dns_obj.server = MockONTAPConnection(kind=kind, data=status) - return dns_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - dns_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_idempotent_modify_dns(self): - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_dns_mock_object('zapi', 'enable', 'false').apply() - assert not exc.value.args[0]['changed'] - - def test_successfully_modify_dns(self): - data = self.mock_args() - data['domains'] = ['1.1.1.1'] - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_dns_mock_object('zapi', 'enable', 'false').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.ems_log_event') - def test_idempotent_create_dns(self, mock_ems_log_event): - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_dns_mock_object('zapi').apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.ems_log_event') - def test_successfully_create_dns(self, mock_ems_log_event): - data = self.mock_args() - print("create dns") - data['domains'] = ['1.1.1.1'] - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_dns_mock_object('zapi', 'create').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.OntapRestAPI.send_request') - def test_rest_error(self, mock_request): - data = self.mock_args() - set_module_args(data) - mock_request.side_effect = [ - SRR['is_rest'], - SRR['generic_error'], - SRR['end_of_sequence'] - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_dns_mock_object(type='rest').apply() - assert exc.value.args[0]['msg'] == SRR['generic_error'][1] - - @patch('ansible.module_utils.netapp.OntapRestAPI.send_request') - def test_rest_successfully_create(self, mock_request): - data = self.mock_args() - set_module_args(data) - mock_request.side_effect = [ - SRR['is_rest'], - SRR['empty_good'], # get - SRR['empty_good'], # post - SRR['end_of_sequence'] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_dns_mock_object(type='rest').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.OntapRestAPI.send_request') - def test_rest_idempotent_create_dns(self, mock_request): - data = self.mock_args() - set_module_args(data) - mock_request.side_effect = [ - SRR['is_rest'], - SRR['dns_record'], # get - SRR['end_of_sequence'] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_dns_mock_object(type='rest').apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.OntapRestAPI.send_request') - def test_rest_successfully_destroy(self, mock_request): - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - mock_request.side_effect = [ - SRR['is_rest'], - SRR['dns_record'], # get - SRR['empty_good'], # delete - SRR['end_of_sequence'] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_dns_mock_object(type='rest').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.OntapRestAPI.send_request') - def test_rest_idempotently_destroy(self, mock_request): - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - mock_request.side_effect = [ - SRR['is_rest'], - SRR['empty_good'], # get - SRR['end_of_sequence'] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_dns_mock_object(type='rest').apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.OntapRestAPI.send_request') - def test_rest_successfully_modify(self, mock_request): - data = self.mock_args() - data['state'] = 'present' - set_module_args(data) - mock_request.side_effect = [ - SRR['is_rest'], - SRR['empty_good'], # get - SRR['empty_good'], # patch - SRR['end_of_sequence'] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_dns_mock_object(type='rest').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.OntapRestAPI.send_request') - def test_rest_idempotently_modify(self, mock_request): - data = self.mock_args() - data['state'] = 'present' - set_module_args(data) - mock_request.side_effect = [ - SRR['is_rest'], - SRR['dns_record'], # get - SRR['end_of_sequence'] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_dns_mock_object(type='rest').apply() - assert not exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_export_policy_rule.py b/test/units/modules/storage/netapp/test_na_ontap_export_policy_rule.py deleted file mode 100644 index 5874603c97..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_export_policy_rule.py +++ /dev/null @@ -1,264 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_export_policy_rule \ - import NetAppontapExportRule as policy_rule # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.data = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'rule': - xml = self.build_policy_rule(self.data) - if self.kind == 'rules': - xml = self.build_policy_rule(self.data, multiple=True) - if self.kind == 'policy': - xml = self.build_policy() - self.xml_out = xml - return xml - - @staticmethod - def build_policy_rule(policy, multiple=False): - ''' build xml data for vserser-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = {'attributes-list': { - 'export-rule-info': { - 'policy-name': policy['name'], - 'client-match': policy['client_match'], - 'ro-rule': { - 'security-flavor': 'any' - }, - 'rw-rule': { - 'security-flavor': 'any' - }, - 'protocol': { - 'access-protocol': policy['protocol'] - }, - 'super-user-security': { - 'security-flavor': 'any' - }, - 'is-allow-set-uid-enabled': 'false', - 'rule-index': policy['rule_index'] - } - }, 'num-records': 2 if multiple is True else 1} - xml.translate_struct(attributes) - return xml - - @staticmethod - def build_policy(): - ''' build xml data for export-policy-get-iter ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.mock_rule = { - 'name': 'test', - 'protocol': 'nfs', - 'client_match': '1.1.1.0', - 'rule_index': 10 - } - - def mock_rule_args(self): - return { - 'name': self.mock_rule['name'], - 'client_match': self.mock_rule['client_match'], - 'vserver': 'test', - 'protocol': self.mock_rule['protocol'], - 'rule_index': self.mock_rule['rule_index'], - 'ro_rule': 'any', - 'rw_rule': 'any', - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - - def get_mock_object(self, kind=None): - """ - Helper method to return an na_ontap_firewall_policy object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_firewall_policy object - """ - obj = policy_rule() - obj.autosupport_log = Mock(return_value=None) - if kind is None: - obj.server = MockONTAPConnection() - else: - obj.server = MockONTAPConnection(kind=kind, data=self.mock_rule_args()) - return obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - policy_rule() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_nonexistent_rule(self): - ''' Test if get_export_policy_rule returns None for non-existent policy ''' - set_module_args(self.mock_rule_args()) - result = self.get_mock_object().get_export_policy_rule() - assert result is None - - def test_get_nonexistent_policy(self): - ''' Test if get_export_policy returns None for non-existent policy ''' - set_module_args(self.mock_rule_args()) - result = self.get_mock_object().get_export_policy() - assert result is None - - def test_get_existing_rule(self): - ''' Test if get_export_policy_rule returns rule details for existing policy ''' - data = self.mock_rule_args() - set_module_args(data) - result = self.get_mock_object('rule').get_export_policy_rule() - assert result['name'] == data['name'] - assert result['client_match'] == data['client_match'] - assert result['ro_rule'] == ['any'] # from build_rule() - - def test_get_existing_policy(self): - ''' Test if get_export_policy returns policy details for existing policy ''' - data = self.mock_rule_args() - set_module_args(data) - result = self.get_mock_object('policy').get_export_policy() - assert result is not None - - def test_create_missing_param_error(self): - ''' Test validation error from create ''' - data = self.mock_rule_args() - del data['ro_rule'] - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_mock_object().apply() - msg = 'Error: Missing required param for creating export policy rule ro_rule' - assert exc.value.args[0]['msg'] == msg - - def test_successful_create(self): - ''' Test successful create ''' - set_module_args(self.mock_rule_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_mock_object().apply() - assert exc.value.args[0]['changed'] - - def test_create_idempotency(self): - ''' Test create idempotency ''' - set_module_args(self.mock_rule_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_mock_object('rule').apply() - assert not exc.value.args[0]['changed'] - - def test_successful_delete_without_rule_index(self): - ''' Test delete existing job ''' - data = self.mock_rule_args() - data['state'] = 'absent' - del data['rule_index'] - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_mock_object('rule').apply() - assert exc.value.args[0]['changed'] - - def test_delete_idempotency(self): - ''' Test delete idempotency ''' - data = self.mock_rule_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_mock_object().apply() - assert not exc.value.args[0]['changed'] - - def test_successful_modify(self): - ''' Test successful modify protocol ''' - data = self.mock_rule_args() - data['protocol'] = ['cifs'] - data['allow_suid'] = 'true' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_mock_object('rule').apply() - assert exc.value.args[0]['changed'] - - def test_error_on_ambiguous_delete(self): - ''' Test error if multiple entries match for a delete ''' - data = self.mock_rule_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_mock_object('rules').apply() - msg = "Multiple export policy rules exist.Please specify a rule_index to delete" - assert exc.value.args[0]['msg'] == msg - - def test_helper_query_parameters(self): - ''' Test helper method set_query_parameters() ''' - data = self.mock_rule_args() - set_module_args(data) - result = self.get_mock_object('rule').set_query_parameters() - print(str(result)) - assert 'query' in result - assert 'export-rule-info' in result['query'] - assert result['query']['export-rule-info']['rule-index'] == data['rule_index'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_firewall_policy.py b/test/units/modules/storage/netapp/test_na_ontap_firewall_policy.py deleted file mode 100644 index e8d48fe0db..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_firewall_policy.py +++ /dev/null @@ -1,286 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_firewall_policy \ - import NetAppONTAPFirewallPolicy as fp_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.data = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'policy': - xml = self.build_policy_info(self.data) - if self.kind == 'config': - xml = self.build_firewall_config_info(self.data) - self.xml_out = xml - return xml - - @staticmethod - def build_policy_info(data): - ''' build xml data for net-firewall-policy-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'net-firewall-policy-info': { - 'policy': data['policy'], - 'service': data['service'], - 'allow-list': [ - {'ip-and-mask': '1.2.3.0/24'} - ] - } - } - } - - xml.translate_struct(attributes) - return xml - - @staticmethod - def build_firewall_config_info(data): - ''' build xml data for net-firewall-config-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'attributes': { - 'net-firewall-config-info': { - 'is-enabled': 'true', - 'is-logging': 'false' - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.mock_policy = { - 'policy': 'test', - 'service': 'http', - 'vserver': 'my_vserver', - 'allow_list': '1.2.3.0/24' - } - self.mock_config = { - 'node': 'test', - 'enable': 'enable', - 'logging': 'enable' - } - - def mock_policy_args(self): - return { - 'policy': self.mock_policy['policy'], - 'service': self.mock_policy['service'], - 'vserver': self.mock_policy['vserver'], - 'allow_list': [self.mock_policy['allow_list']], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - - def mock_config_args(self): - return { - 'node': self.mock_config['node'], - 'enable': self.mock_config['enable'], - 'logging': self.mock_config['logging'], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - - def get_mock_object(self, kind=None): - """ - Helper method to return an na_ontap_firewall_policy object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_firewall_policy object - """ - obj = fp_module() - obj.autosupport_log = Mock(return_value=None) - if kind is None: - obj.server = MockONTAPConnection() - else: - mock_data = self.mock_config if kind == 'config' else self.mock_policy - obj.server = MockONTAPConnection(kind=kind, data=mock_data) - return obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - fp_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_helper_firewall_policy_attributes(self): - ''' helper returns dictionary with vserver, service and policy details ''' - data = self.mock_policy - set_module_args(self.mock_policy_args()) - result = self.get_mock_object('policy').firewall_policy_attributes() - del data['allow_list'] - assert data == result - - def test_helper_validate_ip_addresses_positive(self): - ''' test if helper validates if IP is a network address ''' - data = self.mock_policy_args() - data['allow_list'] = ['1.2.0.0/16', '1.2.3.0/24'] - set_module_args(data) - result = self.get_mock_object().validate_ip_addresses() - assert result is None - - def test_helper_validate_ip_addresses_negative(self): - ''' test if helper validates if IP is a network address ''' - data = self.mock_policy_args() - data['allow_list'] = ['1.2.0.10/16', '1.2.3.0/24'] - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_mock_object().validate_ip_addresses() - msg = 'Error: Invalid IP address value for allow_list parameter.' \ - 'Please specify a network address without host bits set: ' \ - '1.2.0.10/16 has host bits set' - assert exc.value.args[0]['msg'] == msg - - def test_get_nonexistent_policy(self): - ''' Test if get_firewall_policy returns None for non-existent policy ''' - set_module_args(self.mock_policy_args()) - result = self.get_mock_object().get_firewall_policy() - assert result is None - - def test_get_existing_policy(self): - ''' Test if get_firewall_policy returns policy details for existing policy ''' - data = self.mock_policy_args() - set_module_args(data) - result = self.get_mock_object('policy').get_firewall_policy() - assert result['service'] == data['service'] - assert result['allow_list'] == ['1.2.3.0/24'] # from build_policy_info() - - def test_successful_create(self): - ''' Test successful create ''' - set_module_args(self.mock_policy_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_mock_object().apply() - assert exc.value.args[0]['changed'] - - def test_create_idempotency(self): - ''' Test create idempotency ''' - set_module_args(self.mock_policy_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_mock_object('policy').apply() - assert not exc.value.args[0]['changed'] - - def test_successful_delete(self): - ''' Test delete existing job ''' - data = self.mock_policy_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_mock_object('policy').apply() - assert exc.value.args[0]['changed'] - - def test_delete_idempotency(self): - ''' Test delete idempotency ''' - data = self.mock_policy_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_mock_object().apply() - assert not exc.value.args[0]['changed'] - - def test_successful_modify(self): - ''' Test successful modify allow_list ''' - data = self.mock_policy_args() - data['allow_list'] = ['1.2.0.0/16'] - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_mock_object('policy').apply() - assert exc.value.args[0]['changed'] - - def test_successful_modify_multiple_ips(self): - ''' Test successful modify allow_list ''' - data = self.mock_policy_args() - data['allow_list'] = ['1.2.0.0/16', '1.0.0.0/8'] - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_mock_object('policy').apply() - assert exc.value.args[0]['changed'] - - def test_get_nonexistent_config(self): - ''' Test if get_firewall_config returns None for non-existent node ''' - set_module_args(self.mock_config_args()) - result = self.get_mock_object().get_firewall_config_for_node() - assert result is None - - def test_get_existing_config(self): - ''' Test if get_firewall_config returns policy details for existing node ''' - data = self.mock_config_args() - set_module_args(data) - result = self.get_mock_object('config').get_firewall_config_for_node() - assert result['enable'] == 'enable' # from build_config_info() - assert result['logging'] == 'disable' # from build_config_info() - - def test_successful_modify_config(self): - ''' Test successful modify allow_list ''' - data = self.mock_config_args() - data['enable'] = 'disable' - data['logging'] = 'enable' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_mock_object('config').apply() - assert exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_firmware_upgrade.py b/test/units/modules/storage/netapp/test_na_ontap_firmware_upgrade.py deleted file mode 100644 index 5c2399f0dd..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_firmware_upgrade.py +++ /dev/null @@ -1,291 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests ONTAP Ansible module: na_ontap_firmware_upgrade ''' - -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_firmware_upgrade\ - import NetAppONTAPFirmwareUpgrade as my_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, parm1=None, parm2=None, parm3=None): - ''' save arguments ''' - self.type = kind - self.parm1 = parm1 - self.parm2 = parm2 - # self.parm3 = parm3 - self.xml_in = None - self.xml_out = None - self.firmware_type = 'None' - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'firmware_upgrade': - xml = self.build_firmware_upgrade_info(self.parm1, self.parm2) - if self.type == 'acp': - xml = self.build_acp_firmware_info(self.firmware_type) - self.xml_out = xml - return xml - - def autosupport_log(self): - ''' mock autosupport log''' - return None - - @staticmethod - def build_firmware_upgrade_info(version, node): - ''' build xml data for service-processor firmware info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = { - 'num-records': 1, - 'attributes-list': {'service-processor-info': {'firmware-version': '3.4'}} - } - xml.translate_struct(data) - print(xml.to_string()) - return xml - - @staticmethod - def build_acp_firmware_info(firmware_type): - ''' build xml data for acp firmware info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = { - # 'num-records': 1, - 'attributes-list': {'storage-shelf-acp-module': {'state': 'firmware_update_required'}} - } - xml.translate_struct(data) - print(xml.to_string()) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.use_vsim = False - - def set_default_args(self): - if self.use_vsim: - hostname = '10.10.10.10' - username = 'admin' - password = 'admin' - node = 'vsim1' - clear_logs = True - package = 'test1.zip' - install_baseline_image = False - update_type = 'serial_full' - else: - hostname = 'hostname' - username = 'username' - password = 'password' - node = 'abc' - package = 'test1.zip' - clear_logs = True - install_baseline_image = False - update_type = 'serial_full' - - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'node': node, - 'package': package, - 'clear_logs': clear_logs, - 'install_baseline_image': install_baseline_image, - 'update_type': update_type, - 'https': 'true' - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_missing_parameters(self): - ''' fail if firmware_type is missing ''' - module_args = {} - module_args.update(self.set_default_args()) - set_module_args(module_args) - with pytest.raises(AnsibleFailJson) as exc: - set_module_args(module_args) - my_module() - msg = 'missing required arguments: firmware_type' - print('Info: %s' % exc.value.args[0]['msg']) - assert exc.value.args[0]['msg'] == msg - - def test_invalid_firmware_type_parameters(self): - ''' fail if firmware_type is missing ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'firmware_type': 'service_test'}) - set_module_args(module_args) - with pytest.raises(AnsibleFailJson) as exc: - set_module_args(module_args) - my_module() - msg = 'value of firmware_type must be one of: service-processor, shelf, acp, disk, got: %s' % module_args['firmware_type'] - print('Info: %s' % exc.value.args[0]['msg']) - assert exc.value.args[0]['msg'] == msg - - def test_ensure_sp_firmware_get_called(self): - ''' a more interesting test ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'firmware_type': 'service-processor'}) - set_module_args(module_args) - my_obj = my_module() - my_obj.server = self.server - firmware_image_get = my_obj.firmware_image_get('node') - print('Info: test_firmware_upgrade_get: %s' % repr(firmware_image_get)) - assert firmware_image_get is None - - def test_ensure_firmware_get_with_package_baseline_called(self): - ''' a more interesting test ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'firmware_type': 'service-processor'}) - module_args.update({'package': 'test1.zip'}) - module_args.update({'install_baseline_image': True}) - with pytest.raises(AnsibleFailJson) as exc: - set_module_args(module_args) - my_module() - msg = 'Do not specify both package and install_baseline_image: true' - print('info: ' + exc.value.args[0]['msg']) - assert exc.value.args[0]['msg'] == msg - - def test_ensure_acp_firmware_required_get_called(self): - ''' a test tp verify acp firmware upgrade is required or not ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'firmware_type': 'acp'}) - set_module_args(module_args) - my_obj = my_module() - # my_obj.server = self.server - my_obj.server = MockONTAPConnection(kind='acp') - acp_firmware_required_get = my_obj.acp_firmware_required_get() - print('Info: test_acp_firmware_upgrade_required_get: %s' % repr(acp_firmware_required_get)) - assert acp_firmware_required_get is True - - @patch('ansible.modules.storage.netapp.na_ontap_firmware_upgrade.NetAppONTAPFirmwareUpgrade.sp_firmware_image_update') - @patch('ansible.modules.storage.netapp.na_ontap_firmware_upgrade.NetAppONTAPFirmwareUpgrade.sp_firmware_image_update_progress_get') - def test_ensure_apply_for_firmware_upgrade_called(self, get_mock, update_mock): - ''' updgrading firmware and checking idempotency ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'package': 'test1.zip'}) - module_args.update({'firmware_type': 'service-processor'}) - set_module_args(module_args) - my_obj = my_module() - my_obj.autosupport_log = Mock(return_value=None) - if not self.use_vsim: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_firmware_upgrade_apply: %s' % repr(exc.value)) - assert not exc.value.args[0]['changed'] - if not self.use_vsim: - my_obj.server = MockONTAPConnection('firmware_upgrade', '3.5', 'true') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_firmware_upgrade_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - update_mock.assert_called_with() - - def test_shelf_firmware_upgrade(self): - ''' Test shelf firmware upgrade ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'firmware_type': 'shelf'}) - set_module_args(module_args) - my_obj = my_module() - my_obj.autosupport_log = Mock(return_value=None) - if not self.use_vsim: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_firmware_upgrade_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_firmware_upgrade.NetAppONTAPFirmwareUpgrade.acp_firmware_upgrade') - @patch('ansible.modules.storage.netapp.na_ontap_firmware_upgrade.NetAppONTAPFirmwareUpgrade.acp_firmware_required_get') - def test_acp_firmware_upgrade(self, get_mock, update_mock): - ''' Test ACP firmware upgrade ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'firmware_type': 'acp'}) - set_module_args(module_args) - my_obj = my_module() - my_obj.autosupport_log = Mock(return_value=None) - if not self.use_vsim: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_firmware_upgrade_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_firmware_upgrade.NetAppONTAPFirmwareUpgrade.disk_firmware_upgrade') - def test_disk_firmware_upgrade(self, get_mock): - ''' Test disk firmware upgrade ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'firmware_type': 'disk'}) - set_module_args(module_args) - my_obj = my_module() - my_obj.autosupport_log = Mock(return_value=None) - if not self.use_vsim: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_firmware_upgrade_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_flexcache.py b/test/units/modules/storage/netapp/test_na_ontap_flexcache.py deleted file mode 100644 index e7c5fb941c..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_flexcache.py +++ /dev/null @@ -1,529 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test for ONTAP FlexCache Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_flexcache \ - import NetAppONTAPFlexCache as my_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, parm1=None, api_error=None, job_error=None): - ''' save arguments ''' - self.type = kind - self.parm1 = parm1 - self.api_error = api_error - self.job_error = job_error - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - tag = xml.get_name() - if tag == 'flexcache-get-iter' and self.type == 'vserver': - xml = self.build_flexcache_info(self.parm1) - elif tag == 'flexcache-create-async': - xml = self.build_flexcache_create_destroy_rsp() - elif tag == 'flexcache-destroy-async': - if self.api_error: - code, message = self.api_error.split(':', 2) - raise netapp_utils.zapi.NaApiError(code, message) - xml = self.build_flexcache_create_destroy_rsp() - elif tag == 'job-get': - xml = self.build_job_info(self.job_error) - self.xml_out = xml - return xml - - @staticmethod - def build_flexcache_info(vserver): - ''' build xml data for vserser-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = netapp_utils.zapi.NaElement('attributes-list') - count = 2 if vserver == 'repeats' else 1 - for dummy in range(count): - attributes.add_node_with_children('flexcache-info', **{ - 'vserver': vserver, - 'origin-vserver': 'ovserver', - 'origin-volume': 'ovolume', - 'origin-cluster': 'ocluster', - 'volume': 'volume', - }) - xml.add_child_elem(attributes) - xml.add_new_child('num-records', str(count)) - return xml - - @staticmethod - def build_flexcache_create_destroy_rsp(): - ''' build xml data for a create or destroy response ''' - xml = netapp_utils.zapi.NaElement('xml') - xml.add_new_child('result-status', 'in_progress') - xml.add_new_child('result-jobid', '1234') - return xml - - @staticmethod - def build_job_info(error): - ''' build xml data for a job ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = netapp_utils.zapi.NaElement('attributes') - if error is None: - state = 'success' - elif error == 'time_out': - state = 'running' - else: - state = 'failure' - attributes.add_node_with_children('job-info', **{ - 'job-state': state, - 'job-progress': 'dummy', - 'job-completion': error, - }) - xml.add_child_elem(attributes) - xml.add_new_child('result-status', 'in_progress') - xml.add_new_child('result-jobid', '1234') - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - # make sure to change this to False before submitting - self.onbox = False - self.dummy_args = dict() - for arg in ('hostname', 'username', 'password'): - self.dummy_args[arg] = arg - if self.onbox: - self.args = { - 'hostname': '10.193.78.219', - 'username': 'admin', - 'password': 'netapp1!', - } - else: - self.args = self.dummy_args - self.server = MockONTAPConnection() - - def create_flexcache(self, vserver, volume, junction_path): - ''' create flexcache ''' - if not self.onbox: - return - args = { - 'state': 'present', - 'volume': volume, - 'size': '90', # 80MB minimum - 'size_unit': 'mb', # 80MB minimum - 'vserver': vserver, - 'aggr_list': 'aggr1', - 'origin_volume': 'fc_vol_origin', - 'origin_vserver': 'ansibleSVM', - 'junction_path': junction_path, - } - args.update(self.args) - set_module_args(args) - my_obj = my_module() - try: - my_obj.apply() - except AnsibleExitJson as exc: - print('Create util: ' + repr(exc)) - except AnsibleFailJson as exc: - print('Create util: ' + repr(exc)) - - def delete_flexcache(self, vserver, volume): - ''' delete flexcache ''' - if not self.onbox: - return - args = {'volume': volume, 'vserver': vserver, 'state': 'absent', 'force_offline': 'true'} - args.update(self.args) - set_module_args(args) - my_obj = my_module() - try: - my_obj.apply() - except AnsibleExitJson as exc: - print('Delete util: ' + repr(exc)) - except AnsibleFailJson as exc: - print('Delete util: ' + repr(exc)) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_missing_parameters(self): - ''' fail if origin volume and origin verser are missing ''' - args = { - 'vserver': 'vserver', - 'volume': 'volume' - } - args.update(self.dummy_args) - set_module_args(args) - my_obj = my_module() - my_obj.server = self.server - with pytest.raises(AnsibleFailJson) as exc: - # It may not be a good idea to start with apply - # More atomic methods can be easier to mock - # Hint: start with get methods, as they are called first - my_obj.apply() - msg = 'Missing parameters: origin_volume, origin_vserver' - assert exc.value.args[0]['msg'] == msg - - def test_missing_parameter(self): - ''' fail if origin verser parameter is missing ''' - args = { - 'vserver': 'vserver', - 'origin_volume': 'origin_volume', - 'volume': 'volume' - } - args.update(self.dummy_args) - set_module_args(args) - my_obj = my_module() - my_obj.server = self.server - with pytest.raises(AnsibleFailJson) as exc: - my_obj.apply() - msg = 'Missing parameter: origin_vserver' - assert exc.value.args[0]['msg'] == msg - - def test_get_flexcache(self): - ''' get flexcache info ''' - args = { - 'vserver': 'ansibleSVM', - 'origin_volume': 'origin_volume', - 'volume': 'volume' - } - args.update(self.args) - set_module_args(args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('vserver') - info = my_obj.flexcache_get() - print('info: ' + repr(info)) - - def test_get_flexcache_double(self): - ''' get flexcache info returns 2 entries! ''' - args = { - 'vserver': 'ansibleSVM', - 'origin_volume': 'origin_volume', - 'volume': 'volume' - } - args.update(self.dummy_args) - set_module_args(args) - my_obj = my_module() - my_obj.server = MockONTAPConnection('vserver', 'repeats') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.flexcache_get() - msg = 'Error fetching FlexCache info: Multiple records found for %s:' % args['volume'] - assert exc.value.args[0]['msg'] == msg - - def test_create_flexcache(self): - ''' create flexcache ''' - args = { - 'volume': 'volume', - 'size': '90', # 80MB minimum - 'size_unit': 'mb', # 80MB minimum - 'vserver': 'ansibleSVM', - 'aggr_list': 'aggr1', - 'origin_volume': 'fc_vol_origin', - 'origin_vserver': 'ansibleSVM', - } - self.delete_flexcache(args['vserver'], args['volume']) - args.update(self.args) - set_module_args(args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection() - with patch.object(my_module, 'flexcache_create', wraps=my_obj.flexcache_create) as mock_create: - # with patch('__main__.my_module.flexcache_create', wraps=my_obj.flexcache_create) as mock_create: - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Create: ' + repr(exc.value)) - assert exc.value.args[0]['changed'] - mock_create.assert_called_with() - - def test_create_flexcache_idempotent(self): - ''' create flexcache - already exists ''' - args = { - 'volume': 'volume', - 'vserver': 'ansibleSVM', - 'aggr_list': 'aggr1', - 'origin_volume': 'fc_vol_origin', - 'origin_vserver': 'ansibleSVM', - } - args.update(self.args) - set_module_args(args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('vserver') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Create: ' + repr(exc.value)) - assert exc.value.args[0]['changed'] is False - - def test_create_flexcache_autoprovision(self): - ''' create flexcache with autoprovision''' - args = { - 'volume': 'volume', - 'size': '90', # 80MB minimum - 'size_unit': 'mb', # 80MB minimum - 'vserver': 'ansibleSVM', - 'auto_provision_as': 'flexgroup', - 'origin_volume': 'fc_vol_origin', - 'origin_vserver': 'ansibleSVM', - } - self.delete_flexcache(args['vserver'], args['volume']) - args.update(self.args) - set_module_args(args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection() - with patch.object(my_module, 'flexcache_create', wraps=my_obj.flexcache_create) as mock_create: - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Create: ' + repr(exc.value)) - assert exc.value.args[0]['changed'] - mock_create.assert_called_with() - - def test_create_flexcache_autoprovision_idempotent(self): - ''' create flexcache with autoprovision - already exists ''' - args = { - 'volume': 'volume', - 'vserver': 'ansibleSVM', - 'origin_volume': 'fc_vol_origin', - 'origin_vserver': 'ansibleSVM', - 'auto_provision_as': 'flexgroup', - } - args.update(self.args) - set_module_args(args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('vserver') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Create: ' + repr(exc.value)) - assert exc.value.args[0]['changed'] is False - - def test_create_flexcache_multiplier(self): - ''' create flexcache with aggregate multiplier''' - args = { - 'volume': 'volume', - 'size': '90', # 80MB minimum - 'size_unit': 'mb', # 80MB minimum - 'vserver': 'ansibleSVM', - 'aggr_list': 'aggr1', - 'origin_volume': 'fc_vol_origin', - 'origin_vserver': 'ansibleSVM', - 'aggr_list_multiplier': '2', - } - self.delete_flexcache(args['vserver'], args['volume']) - args.update(self.args) - set_module_args(args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection() - with patch.object(my_module, 'flexcache_create', wraps=my_obj.flexcache_create) as mock_create: - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Create: ' + repr(exc.value)) - assert exc.value.args[0]['changed'] - mock_create.assert_called_with() - - def test_create_flexcache_multiplier_idempotent(self): - ''' create flexcache with aggregate multiplier - already exists ''' - args = { - 'volume': 'volume', - 'vserver': 'ansibleSVM', - 'aggr_list': 'aggr1', - 'origin_volume': 'fc_vol_origin', - 'origin_vserver': 'ansibleSVM', - 'aggr_list_multiplier': '2', - } - args.update(self.args) - set_module_args(args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('vserver') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Create: ' + repr(exc.value)) - assert exc.value.args[0]['changed'] is False - - def test_delete_flexcache_exists_no_force(self): - ''' delete flexcache ''' - args = {'volume': 'volume', 'vserver': 'ansibleSVM', 'state': 'absent'} - args.update(self.args) - set_module_args(args) - my_obj = my_module() - error = '13001:Volume volume in Vserver ansibleSVM must be offline to be deleted. ' \ - 'Use "volume offline -vserver ansibleSVM -volume volume" command to offline ' \ - 'the volume' - if not self.onbox: - my_obj.server = MockONTAPConnection('vserver', 'flex', api_error=error) - with patch.object(my_module, 'flexcache_delete', wraps=my_obj.flexcache_delete) as mock_delete: - with pytest.raises(AnsibleFailJson) as exc: - my_obj.apply() - print('Delete: ' + repr(exc.value)) - msg = 'Error deleting FlexCache : NetApp API failed. Reason - %s' % error - assert exc.value.args[0]['msg'] == msg - mock_delete.assert_called_with() - - def test_delete_flexcache_exists_with_force(self): - ''' delete flexcache ''' - args = {'volume': 'volume', 'vserver': 'ansibleSVM', 'state': 'absent', 'force_offline': 'true'} - args.update(self.args) - set_module_args(args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('vserver', 'flex') - with patch.object(my_module, 'flexcache_delete', wraps=my_obj.flexcache_delete) as mock_delete: - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Delete: ' + repr(exc.value)) - assert exc.value.args[0]['changed'] - mock_delete.assert_called_with() - - def test_delete_flexcache_exists_junctionpath_no_force(self): - ''' delete flexcache ''' - args = {'volume': 'volume', 'vserver': 'ansibleSVM', 'junction_path': 'jpath', 'state': 'absent', 'force_offline': 'true'} - self.create_flexcache(args['vserver'], args['volume'], args['junction_path']) - args.update(self.args) - set_module_args(args) - my_obj = my_module() - error = '160:Volume volume on Vserver ansibleSVM must be unmounted before being taken offline or restricted.' - if not self.onbox: - my_obj.server = MockONTAPConnection('vserver', 'flex', api_error=error) - with patch.object(my_module, 'flexcache_delete', wraps=my_obj.flexcache_delete) as mock_delete: - with pytest.raises(AnsibleFailJson) as exc: - my_obj.apply() - print('Delete: ' + repr(exc.value)) - msg = 'Error deleting FlexCache : NetApp API failed. Reason - %s' % error - assert exc.value.args[0]['msg'] == msg - mock_delete.assert_called_with() - - def test_delete_flexcache_exists_junctionpath_with_force(self): - ''' delete flexcache ''' - args = {'volume': 'volume', 'vserver': 'ansibleSVM', 'junction_path': 'jpath', 'state': 'absent', 'force_offline': 'true', 'force_unmount': 'true'} - self.create_flexcache(args['vserver'], args['volume'], args['junction_path']) - args.update(self.args) - set_module_args(args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('vserver', 'flex') - with patch.object(my_module, 'flexcache_delete', wraps=my_obj.flexcache_delete) as mock_delete: - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Delete: ' + repr(exc.value)) - assert exc.value.args[0]['changed'] - mock_delete.assert_called_with() - - def test_delete_flexcache_not_exist(self): - ''' delete flexcache ''' - args = {'volume': 'volume', 'vserver': 'ansibleSVM', 'state': 'absent'} - args.update(self.args) - set_module_args(args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection() - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Delete: ' + repr(exc.value)) - assert exc.value.args[0]['changed'] is False - - def test_create_flexcache_size_error(self): - ''' create flexcache ''' - args = { - 'volume': 'volume_err', - 'size': '50', # 80MB minimum - 'size_unit': 'mb', # 80MB minimum - 'vserver': 'ansibleSVM', - 'aggr_list': 'aggr1', - 'origin_volume': 'fc_vol_origin', - 'origin_vserver': 'ansibleSVM', - } - args.update(self.args) - set_module_args(args) - my_obj = my_module() - error = 'Size "50MB" ("52428800B") is too small. Minimum size is "80MB" ("83886080B"). ' - if not self.onbox: - my_obj.server = MockONTAPConnection(job_error=error) - with patch.object(my_module, 'flexcache_create', wraps=my_obj.flexcache_create) as mock_create: - with pytest.raises(AnsibleFailJson) as exc: - my_obj.apply() - print('Create: ' + repr(exc.value)) - msg = 'Error when creating flexcache: %s' % error - assert exc.value.args[0]['msg'] == msg - mock_create.assert_called_with() - - @patch('time.sleep') - def test_create_flexcache_time_out(self, mock_sleep): - ''' create flexcache ''' - args = { - 'volume': 'volume_err', - 'size': '50', # 80MB minimum - 'size_unit': 'mb', # 80MB minimum - 'vserver': 'ansibleSVM', - 'aggr_list': 'aggr1', - 'origin_volume': 'fc_vol_origin', - 'origin_vserver': 'ansibleSVM', - 'time_out': '2' - } - args.update(self.args) - set_module_args(args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection(job_error='time_out') - with patch.object(my_module, 'flexcache_create', wraps=my_obj.flexcache_create) as mock_create: - with pytest.raises(AnsibleFailJson) as exc: - my_obj.apply() - print('Create: ' + repr(exc.value)) - msg = 'Error when creating flexcache: job completion exceeded expected timer of: %s seconds' \ - % args['time_out'] - assert exc.value.args[0]['msg'] == msg - mock_create.assert_called_with() diff --git a/test/units/modules/storage/netapp/test_na_ontap_igroup.py b/test/units/modules/storage/netapp/test_na_ontap_igroup.py deleted file mode 100644 index f52c89caca..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_igroup.py +++ /dev/null @@ -1,259 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_igroup \ - import NetAppOntapIgroup as igroup # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.data = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'igroup': - xml = self.build_igroup() - if self.kind == 'igroup_no_initiators': - xml = self.build_igroup_no_initiators() - self.xml_out = xml - return xml - - @staticmethod - def build_igroup(): - ''' build xml data for initiator ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'initiator-group-info': { - 'initiators': [ - { - 'initiator-info': { - 'initiator-name': 'init1' - }}, - { - 'initiator-info': { - 'initiator-name': 'init2' - }} - ] - } - } - } - xml.translate_struct(attributes) - return xml - - @staticmethod - def build_igroup_no_initiators(): - ''' build xml data for igroup with no initiators ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'initiator-group-info': { - 'vserver': 'test' - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - - def mock_args(self): - return { - 'vserver': 'vserver', - 'name': 'test', - 'initiators': 'init1', - 'ostype': 'linux', - 'initiator_group_type': 'fcp', - 'bind_portset': 'true', - 'hostname': 'hostname', - 'username': 'username', - 'password': 'password' - } - - def get_igroup_mock_object(self, kind=None): - """ - Helper method to return an na_ontap_igroup object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_igroup object - """ - obj = igroup() - obj.autosupport_log = Mock(return_value=None) - if kind is None: - obj.server = MockONTAPConnection() - else: - obj.server = MockONTAPConnection(kind=kind) - return obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - igroup() - - def test_get_nonexistent_igroup(self): - ''' Test if get_igroup returns None for non-existent igroup ''' - data = self.mock_args() - set_module_args(data) - result = self.get_igroup_mock_object().get_igroup('dummy') - assert result is None - - def test_get_existing_igroup_with_initiators(self): - ''' Test if get_igroup returns list of existing initiators ''' - data = self.mock_args() - set_module_args(data) - result = self.get_igroup_mock_object('igroup').get_igroup(data['name']) - assert data['initiators'] in result['initiators'] - assert result['initiators'] == ['init1', 'init2'] - - def test_get_existing_igroup_without_initiators(self): - ''' Test if get_igroup returns empty list() ''' - data = self.mock_args() - set_module_args(data) - result = self.get_igroup_mock_object('igroup_no_initiators').get_igroup(data['name']) - assert result['initiators'] == [] - - @patch('ansible.modules.storage.netapp.na_ontap_igroup.NetAppOntapIgroup.add_initiators') - @patch('ansible.modules.storage.netapp.na_ontap_igroup.NetAppOntapIgroup.remove_initiators') - def test_modify_initiator_calls_add_and_remove(self, remove, add): - '''Test remove_initiator() is called followed by add_initiator() on modify operation''' - data = self.mock_args() - data['initiators'] = 'replacewithme' - set_module_args(data) - obj = self.get_igroup_mock_object('igroup') - with pytest.raises(AnsibleExitJson) as exc: - current = obj.get_igroup(data['name']) - obj.apply() - remove.assert_called_with(current['initiators']) - add.assert_called_with() - - @patch('ansible.modules.storage.netapp.na_ontap_igroup.NetAppOntapIgroup.modify_initiator') - def test_modify_called_from_add(self, modify): - '''Test remove_initiator() and add_initiator() calls modify''' - data = self.mock_args() - data['initiators'] = 'replacewithme' - add, remove = 'igroup-add', 'igroup-remove' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_igroup_mock_object('igroup_no_initiators').apply() - modify.assert_called_with('replacewithme', add) - assert modify.call_count == 1 # remove nothing, add 1 new - - @patch('ansible.modules.storage.netapp.na_ontap_igroup.NetAppOntapIgroup.modify_initiator') - def test_modify_called_from_remove(self, modify): - '''Test remove_initiator() and add_initiator() calls modify''' - data = self.mock_args() - data['initiators'] = '' - remove = 'igroup-remove' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_igroup_mock_object('igroup').apply() - modify.assert_called_with('init2', remove) - assert modify.call_count == 2 # remove existing 2, add nothing - - @patch('ansible.modules.storage.netapp.na_ontap_igroup.NetAppOntapIgroup.add_initiators') - def test_successful_create(self, add): - ''' Test successful create ''' - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_igroup_mock_object().apply() - assert exc.value.args[0]['changed'] - add.assert_called_with() - - def test_successful_delete(self): - ''' Test successful delete ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_igroup_mock_object('igroup').apply() - assert exc.value.args[0]['changed'] - - def test_successful_modify(self): - ''' Test successful modify ''' - data = self.mock_args() - data['initiators'] = 'new' - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_igroup_mock_object('igroup').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_igroup.NetAppOntapIgroup.get_igroup') - def test_successful_rename(self, get_vserver): - '''Test successful rename''' - data = self.mock_args() - data['from_name'] = 'test' - data['name'] = 'test_new' - set_module_args(data) - current = { - 'initiators': ['init1', 'init2'] - } - get_vserver.side_effect = [ - None, - current - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_igroup_mock_object().apply() - assert exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_igroup_initiator.py b/test/units/modules/storage/netapp/test_na_ontap_igroup_initiator.py deleted file mode 100644 index e096273555..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_igroup_initiator.py +++ /dev/null @@ -1,217 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_igroup_initiator \ - import NetAppOntapIgroupInitiator as initiator # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.data = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'initiator': - xml = self.build_igroup_initiator() - elif self.kind == 'initiator_fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - @staticmethod - def build_igroup_initiator(): - ''' build xml data for initiator ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'initiator-group-info': { - 'initiators': [ - {'initiator-info': { - 'initiator-name': 'init1' - }}, - {'initiator-info': { - 'initiator-name': 'init2' - }} - ] - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - - def mock_args(self): - return { - 'vserver': 'vserver', - 'name': 'init1', - 'initiator_group': 'test', - 'hostname': 'hostname', - 'username': 'username', - 'password': 'password' - } - - def get_initiator_mock_object(self, kind=None): - """ - Helper method to return an na_ontap_initiator object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_initiator object - """ - obj = initiator() - obj.autosupport_log = Mock(return_value=None) - if kind is None: - obj.server = MockONTAPConnection() - else: - obj.server = MockONTAPConnection(kind=kind) - return obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - initiator() - - def test_get_nonexistent_initiator(self): - ''' Test if get_initiators returns None for non-existent initiator ''' - data = self.mock_args() - data['name'] = 'idontexist' - set_module_args(data) - result = self.get_initiator_mock_object('initiator').get_initiators() - assert data['name'] not in result - - def test_get_nonexistent_igroup(self): - ''' Test if get_initiators returns None for non-existent igroup ''' - data = self.mock_args() - data['name'] = 'idontexist' - set_module_args(data) - result = self.get_initiator_mock_object().get_initiators() - assert result == [] - - def test_get_existing_initiator(self): - ''' Test if get_initiator returns None for existing initiator ''' - data = self.mock_args() - set_module_args(data) - result = self.get_initiator_mock_object(kind='initiator').get_initiators() - assert data['name'] in result - assert result == ['init1', 'init2'] # from build_igroup_initiators() - - def test_successful_add(self): - ''' Test successful add''' - data = self.mock_args() - data['name'] = 'iamnew' - set_module_args(data) - obj = self.get_initiator_mock_object('initiator') - with pytest.raises(AnsibleExitJson) as exc: - current = obj.get_initiators() - obj.apply() - assert data['name'] not in current - assert exc.value.args[0]['changed'] - - def test_successful_add_idempotency(self): - ''' Test successful add idempotency ''' - data = self.mock_args() - set_module_args(data) - obj = self.get_initiator_mock_object('initiator') - with pytest.raises(AnsibleExitJson) as exc: - current_list = obj.get_initiators() - obj.apply() - assert data['name'] in current_list - assert not exc.value.args[0]['changed'] - - def test_successful_remove(self): - ''' Test successful remove ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - obj = self.get_initiator_mock_object('initiator') - with pytest.raises(AnsibleExitJson) as exc: - current_list = obj.get_initiators() - obj.apply() - assert data['name'] in current_list - assert exc.value.args[0]['changed'] - - def test_successful_remove_idempotency(self): - ''' Test successful remove idempotency''' - data = self.mock_args() - data['state'] = 'absent' - data['name'] = 'alreadyremoved' - set_module_args(data) - obj = self.get_initiator_mock_object('initiator') - with pytest.raises(AnsibleExitJson) as exc: - current_list = obj.get_initiators() - obj.apply() - assert data['name'] not in current_list - assert not exc.value.args[0]['changed'] - - def test_if_all_methods_catch_exception(self): - data = self.mock_args() - set_module_args(data) - my_obj = self.get_initiator_mock_object('initiator_fail') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.get_initiators() - assert 'Error fetching igroup info ' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.modify_initiator(data['name'], 'igroup-add') - assert 'Error modifying igroup initiator ' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_info.py b/test/units/modules/storage/netapp/test_na_ontap_info.py deleted file mode 100644 index 389e2128b7..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_info.py +++ /dev/null @@ -1,313 +0,0 @@ -# (c) 2018-2019, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests for ONTAP Ansible module na_ontap_info ''' - -from __future__ import print_function -import json -import pytest -import sys - -from units.compat import unittest -from units.compat.mock import patch -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_info import main as info_main -from ansible.modules.storage.netapp.na_ontap_info import __finditem as info_finditem -from ansible.modules.storage.netapp.na_ontap_info \ - import NetAppONTAPGatherInfo as info_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None): - ''' save arguments ''' - self.type = kind - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'vserver': - xml = self.build_vserver_info() - elif self.type == 'net_port': - xml = self.build_net_port_info() - elif self.type == 'zapi_error': - error = netapp_utils.zapi.NaApiError('test', 'error') - raise error - self.xml_out = xml - return xml - - @staticmethod - def build_vserver_info(): - ''' build xml data for vserser-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = netapp_utils.zapi.NaElement('attributes-list') - attributes.add_node_with_children('vserver-info', - **{'vserver-name': 'test_vserver'}) - xml.add_child_elem(attributes) - return xml - - @staticmethod - def build_net_port_info(): - ''' build xml data for net-port-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes_list = netapp_utils.zapi.NaElement('attributes-list') - num_net_port_info = 2 - for i in range(num_net_port_info): - net_port_info = netapp_utils.zapi.NaElement('net-port-info') - net_port_info.add_new_child('node', 'node_' + str(i)) - net_port_info.add_new_child('port', 'port_' + str(i)) - net_port_info.add_new_child('broadcast_domain', 'test_domain_' + str(i)) - net_port_info.add_new_child('ipspace', 'ipspace' + str(i)) - attributes_list.add_child_elem(net_port_info) - xml.add_child_elem(attributes_list) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - - def mock_args(self): - return { - 'hostname': 'hostname', - 'username': 'username', - 'password': 'password', - } - - def get_info_mock_object(self, kind=None): - """ - Helper method to return an na_ontap_info object - """ - module = basic.AnsibleModule( - argument_spec=netapp_utils.na_ontap_host_argument_spec(), - supports_check_mode=True - ) - obj = info_module(module) - obj.netapp_info = dict() - if kind is None: - obj.server = MockONTAPConnection() - else: - obj.server = MockONTAPConnection(kind) - return obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - self.get_info_mock_object() - print('Info: %s' % exc.value.args[0]['msg']) - - @patch('ansible.module_utils.netapp.ems_log_event') - def test_ensure_command_called(self, mock_ems_log): - ''' calling get_all will raise a KeyError exception ''' - set_module_args(self.mock_args()) - my_obj = self.get_info_mock_object('vserver') - with pytest.raises(KeyError) as exc: - my_obj.get_all(['net_interface_info']) - if sys.version_info >= (2, 7): - msg = 'net-interface-info' - assert exc.value.args[0] == msg - - @patch('ansible.module_utils.netapp.ems_log_event') - def test_get_generic_get_iter(self, mock_ems_log): - '''calling get_generic_get_iter will return expected dict''' - set_module_args(self.mock_args()) - obj = self.get_info_mock_object('net_port') - result = obj.get_generic_get_iter( - 'net-port-get-iter', - attribute='net-port-info', - field=('node', 'port'), - query={'max-records': '1024'} - ) - assert result.get('node_0:port_0') - assert result.get('node_1:port_1') - - @patch('ansible.modules.storage.netapp.na_ontap_info.NetAppONTAPGatherInfo.get_all') - def test_main(self, get_all): - '''test main method.''' - set_module_args(self.mock_args()) - get_all.side_effect = [ - {'test_get_all': - {'vserver_login_banner_info': 'test_vserver_login_banner_info', 'vserver_info': 'test_vserver_info'}} - ] - with pytest.raises(AnsibleExitJson) as exc: - info_main() - assert exc.value.args[0]['state'] == 'info' - - @patch('ansible.modules.storage.netapp.na_ontap_info.NetAppONTAPGatherInfo.get_generic_get_iter') - def test_get_ifgrp_info(self, get_generic_get_iter): - '''test get_ifgrp_info with empty ifgrp_info''' - set_module_args(self.mock_args()) - get_generic_get_iter.side_effect = [ - {} - ] - obj = self.get_info_mock_object() - obj.netapp_info['net_port_info'] = {} - result = obj.get_ifgrp_info() - assert result == {} - - def test_ontapi_error(self): - '''test ontapi will raise zapi error''' - set_module_args(self.mock_args()) - obj = self.get_info_mock_object('zapi_error') - with pytest.raises(AnsibleFailJson) as exc: - obj.ontapi() - assert exc.value.args[0]['msg'] == 'Error calling API system-get-ontapi-version: NetApp API failed. Reason - test:error' - - def test_call_api_error(self): - '''test call_api will raise zapi error''' - set_module_args(self.mock_args()) - obj = self.get_info_mock_object('zapi_error') - with pytest.raises(AnsibleFailJson) as exc: - obj.call_api('nvme-get-iter') - assert exc.value.args[0]['msg'] == 'Error calling API nvme-get-iter: NetApp API failed. Reason - test:error' - - def test_find_item(self): - '''test __find_item return expected key value''' - obj = {"A": 1, "B": {"C": {"D": 2}}} - key = "D" - result = info_finditem(obj, key) - assert result == 2 - - def test_subset_return_all_complete(self): - ''' Check all returns all of the entries if version is high enough ''' - version = '140' # change this if new ZAPIs are supported - set_module_args(self.mock_args()) - obj = self.get_info_mock_object('vserver') - subset = obj.get_subset(['all'], version) - assert set(obj.info_subsets.keys()) == subset - - def test_subset_return_all_partial(self): - ''' Check all returns a subset of the entries if version is low enough ''' - version = '120' # low enough so that some ZAPIs are not supported - set_module_args(self.mock_args()) - obj = self.get_info_mock_object('vserver') - subset = obj.get_subset(['all'], version) - all_keys = obj.info_subsets.keys() - assert set(all_keys) > subset - supported_keys = filter(lambda key: obj.info_subsets[key]['min_version'] <= version, all_keys) - assert set(supported_keys) == subset - - def test_subset_return_one(self): - ''' Check single entry returns one ''' - version = '120' # low enough so that some ZAPIs are not supported - set_module_args(self.mock_args()) - obj = self.get_info_mock_object('vserver') - subset = obj.get_subset(['net_interface_info'], version) - assert len(subset) == 1 - - def test_subset_return_multiple(self): - ''' Check that more than one entry returns the same number ''' - version = '120' # low enough so that some ZAPIs are not supported - set_module_args(self.mock_args()) - obj = self.get_info_mock_object('vserver') - subset_entries = ['net_interface_info', 'net_port_info'] - subset = obj.get_subset(subset_entries, version) - assert len(subset) == len(subset_entries) - - def test_subset_return_bad(self): - ''' Check that a bad subset entry will error out ''' - version = '120' # low enough so that some ZAPIs are not supported - set_module_args(self.mock_args()) - obj = self.get_info_mock_object('vserver') - with pytest.raises(AnsibleFailJson) as exc: - subset = obj.get_subset(['net_interface_info', 'my_invalid_subset'], version) - print('Info: %s' % exc.value.args[0]['msg']) - assert exc.value.args[0]['msg'] == 'Bad subset: my_invalid_subset' - - def test_subset_return_unsupported(self): - ''' Check that a new subset entry will error out on an older system ''' - version = '120' # low enough so that some ZAPIs are not supported - key = 'nvme_info' # only supported starting at 140 - set_module_args(self.mock_args()) - obj = self.get_info_mock_object('vserver') - with pytest.raises(AnsibleFailJson) as exc: - subset = obj.get_subset(['net_interface_info', key], version) - print('Info: %s' % exc.value.args[0]['msg']) - msg = 'Remote system at version %s does not support %s' % (version, key) - assert exc.value.args[0]['msg'] == msg - - def test_subset_return_none(self): - ''' Check usable subset can be empty ''' - version = '!' # lower then 0, so that no ZAPI is supported - set_module_args(self.mock_args()) - obj = self.get_info_mock_object('vserver') - subset = obj.get_subset(['all'], version) - assert len(subset) == 0 - - def test_subset_return_all_expect_one(self): - ''' Check !x returns all of the entries except x if version is high enough ''' - version = '140' # change this if new ZAPIs are supported - set_module_args(self.mock_args()) - obj = self.get_info_mock_object('vserver') - subset = obj.get_subset(['!net_interface_info'], version) - assert len(obj.info_subsets.keys()) == len(subset) + 1 - subset.add('net_interface_info') - assert set(obj.info_subsets.keys()) == subset - - def test_subset_return_all_expect_three(self): - ''' Check !x,!y,!z returns all of the entries except x, y, z if version is high enough ''' - version = '140' # change this if new ZAPIs are supported - set_module_args(self.mock_args()) - obj = self.get_info_mock_object('vserver') - subset = obj.get_subset(['!net_interface_info', '!nvme_info', '!ontap_version'], version) - assert len(obj.info_subsets.keys()) == len(subset) + 3 - subset.update(['net_interface_info', 'nvme_info', 'ontap_version']) - assert set(obj.info_subsets.keys()) == subset - - def test_subset_return_none_with_exclusion(self): - ''' Check usable subset can be empty with !x ''' - version = '!' # lower then 0, so that no ZAPI is supported - key = 'net_interface_info' - set_module_args(self.mock_args()) - obj = self.get_info_mock_object('vserver') - with pytest.raises(AnsibleFailJson) as exc: - subset = obj.get_subset(['!' + key], version) - print('Info: %s' % exc.value.args[0]['msg']) - msg = 'Remote system at version %s does not support %s' % (version, key) - assert exc.value.args[0]['msg'] == msg diff --git a/test/units/modules/storage/netapp/test_na_ontap_interface.py b/test/units/modules/storage/netapp/test_na_ontap_interface.py deleted file mode 100644 index 18119e5a37..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_interface.py +++ /dev/null @@ -1,272 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_interface \ - import NetAppOntapInterface as interface_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.type = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'interface': - xml = self.build_interface_info(self.params) - self.xml_out = xml - return xml - - @staticmethod - def build_interface_info(data): - ''' build xml data for vserser-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'net-interface-info': { - 'interface-name': data['name'], - 'administrative-status': data['administrative-status'], - 'failover-policy': data['failover-policy'], - 'firewall-policy': data['firewall-policy'], - 'is-auto-revert': data['is-auto-revert'], - 'home-node': data['home_node'], - 'home-port': data['home_port'], - 'address': data['address'], - 'netmask': data['netmask'], - 'role': data['role'], - 'protocols': data['protocols'] if data.get('protocols') else None, - 'dns-domain-name': data['dns_domain_name'], - 'listen-for-dns_query': data['listen_for_dns_query'], - 'is-dns-update-enabled': data['is_dns_update_enabled'] - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.mock_interface = { - 'name': 'test_lif', - 'administrative-status': 'up', - 'failover-policy': 'up', - 'firewall-policy': 'up', - 'is-auto-revert': 'true', - 'home_node': 'node', - 'role': 'test', - 'home_port': 'e0c', - 'address': '2.2.2.2', - 'netmask': '1.1.1.1', - 'dns_domain_name': 'test.com', - 'listen_for_dns_query': True, - 'is_dns_update_enabled': True - } - - def mock_args(self): - return { - 'vserver': 'vserver', - 'interface_name': self.mock_interface['name'], - 'home_node': self.mock_interface['home_node'], - 'role': self.mock_interface['role'], - 'home_port': self.mock_interface['home_port'], - 'address': self.mock_interface['address'], - 'netmask': self.mock_interface['netmask'], - 'hostname': 'hostname', - 'username': 'username', - 'password': 'password', - } - - def get_interface_mock_object(self, kind=None): - """ - Helper method to return an na_ontap_interface object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_interface object - """ - interface_obj = interface_module() - interface_obj.autosupport_log = Mock(return_value=None) - if kind is None: - interface_obj.server = MockONTAPConnection() - else: - interface_obj.server = MockONTAPConnection(kind=kind, data=self.mock_interface) - return interface_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - interface_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_create_error_missing_param(self): - ''' Test if create throws an error if required param 'role' is not specified''' - data = self.mock_args() - del data['role'] - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_interface_mock_object('interface').create_interface() - msg = 'Error: Missing one or more required parameters for creating interface: ' \ - 'home_port, netmask, role, home_node, address' - expected = sorted(','.split(msg)) - received = sorted(','.split(exc.value.args[0]['msg'])) - assert expected == received - - def test_get_nonexistent_interface(self): - ''' Test if get_interface returns None for non-existent interface ''' - set_module_args(self.mock_args()) - result = self.get_interface_mock_object().get_interface() - assert result is None - - def test_get_existing_interface(self): - ''' Test if get_interface returns None for existing interface ''' - set_module_args(self.mock_args()) - result = self.get_interface_mock_object(kind='interface').get_interface() - assert result['interface_name'] == self.mock_interface['name'] - - def test_successful_create(self): - ''' Test successful create ''' - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_interface_mock_object().apply() - assert exc.value.args[0]['changed'] - - def test_successful_create_for_NVMe(self): - ''' Test successful create for NVMe protocol''' - data = self.mock_args() - data['protocols'] = 'fc-nvme' - del data['address'] - del data['netmask'] - del data['home_port'] - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_interface_mock_object().apply() - assert exc.value.args[0]['changed'] - - def test_create_idempotency_for_NVMe(self): - ''' Test create idempotency for NVMe protocol ''' - data = self.mock_args() - data['protocols'] = 'fc-nvme' - del data['address'] - del data['netmask'] - del data['home_port'] - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_interface_mock_object('interface').apply() - assert not exc.value.args[0]['changed'] - - def test_create_error_for_NVMe(self): - ''' Test if create throws an error if required param 'protocols' uses NVMe''' - data = self.mock_args() - data['protocols'] = 'fc-nvme' - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_interface_mock_object('interface').create_interface() - msg = 'Error: Following parameters for creating interface are not supported for data-protocol fc-nvme: ' \ - 'netmask, firewall_policy, address' - expected = sorted(','.split(msg)) - received = sorted(','.split(exc.value.args[0]['msg'])) - assert expected == received - - def test_create_idempotency(self): - ''' Test create idempotency ''' - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_interface_mock_object('interface').apply() - assert not exc.value.args[0]['changed'] - - def test_successful_delete(self): - ''' Test delete existing interface ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_interface_mock_object('interface').apply() - assert exc.value.args[0]['changed'] - - def test_delete_idempotency(self): - ''' Test delete idempotency ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_interface_mock_object().apply() - assert not exc.value.args[0]['changed'] - - def test_successful_modify(self): - ''' Test successful modify interface_minutes ''' - data = self.mock_args() - data['home_port'] = 'new_port' - data['dns_domain_name'] = 'test2.com' - data['listen_for_dns_query'] = False - data['is_dns_update_enabled'] = False - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - interface_obj = self.get_interface_mock_object('interface') - interface_obj.apply() - assert exc.value.args[0]['changed'] - - def test_modify_idempotency(self): - ''' Test modify idempotency ''' - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_interface_mock_object('interface').apply() - assert not exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_ipspace.py b/test/units/modules/storage/netapp/test_na_ontap_ipspace.py deleted file mode 100644 index abaa11d358..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_ipspace.py +++ /dev/null @@ -1,138 +0,0 @@ -# (c) 2018, NTT Europe Ltd. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -""" unit test for Ansible module: na_ontap_ipspace """ - -from __future__ import print_function -import json -import pytest - -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils -from ansible.modules.storage.netapp.na_ontap_ipspace \ - import NetAppOntapIpspace as my_module -from units.compat import unittest -from units.compat.mock import patch - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - def __init__(self, kind=None, parm1=None): - ''' save arguments ''' - self.type = kind - self.parm1 = parm1 - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'ipspace': - xml = self.build_ipspace_info(self.parm1) - self.xml_out = xml - return xml - - @staticmethod - def build_ipspace_info(ipspace): - ''' build xml data for ipspace ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 1, - 'attributes-list': {'net-ipspaces-info': {'ipspace': ipspace}}} - xml.translate_struct(data) - print(xml.to_string()) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - - def set_default_args(self): - return dict({ - 'name': 'test_ipspace', - 'hostname': 'hostname', - 'username': 'username', - 'password': 'password' - }) - - def test_fail_requiredargs_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_ipspace_iscalled(self): - ''' test if get_ipspace() is called ''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - ipspace = my_obj.get_ipspace() - print('Info: test_get_ipspace: %s' % repr(ipspace)) - assert ipspace is None - - def test_ipspace_apply_iscalled(self): - ''' test if apply() is called ''' - module_args = {'name': 'test_apply_ips'} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - my_obj.server = self.server - ipspace = my_obj.get_ipspace() - print('Info: test_get_ipspace: %s' % repr(ipspace)) - assert ipspace is None - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_ipspace_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - my_obj.server = MockONTAPConnection('ipspace', 'test_apply_ips') - ipspace = my_obj.get_ipspace() - print('Info: test_get_ipspace: %s' % repr(ipspace)) - assert ipspace is not None - assert ipspace['name'] == 'test_apply_ips' - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_ipspace_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - ipspace = my_obj.get_ipspace() - assert ipspace['name'] == 'test_apply_ips' diff --git a/test/units/modules/storage/netapp/test_na_ontap_job_schedule.py b/test/units/modules/storage/netapp/test_na_ontap_job_schedule.py deleted file mode 100644 index 973474036b..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_job_schedule.py +++ /dev/null @@ -1,246 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests for Ansible module: na_ontap_job_schedule ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_job_schedule \ - import NetAppONTAPJob as job_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'job': - xml = self.build_job_schedule_cron_info(self.params) - elif self.kind == 'job_multiple': - xml = self.build_job_schedule_multiple_cron_info(self.params) - # TODO: mock invoke_elem for autosupport calls - elif self.kind == 'vserver': - xml = self.build_vserver_info() - self.xml_out = xml - return xml - - def autosupport_log(self): - ''' Mock autosupport log method, returns None ''' - return None - - @staticmethod - def build_job_schedule_cron_info(job_details): - ''' build xml data for vserser-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'job-schedule-cron-info': { - 'job-schedule-name': job_details['name'], - 'job-schedule-cron-minute': { - 'cron-minute': job_details['minutes'] - } - } - } - } - xml.translate_struct(attributes) - return xml - - @staticmethod - def build_job_schedule_multiple_cron_info(job_details): - ''' build xml data for vserser-info ''' - print("CALLED MULTIPLE BUILD") - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'job-schedule-cron-info': { - 'job-schedule-name': job_details['name'], - 'job-schedule-cron-minute': [ - {'cron-minute': '25'}, - {'cron-minute': '35'} - ], - 'job-schedule-cron-month': [ - {'cron-month': '5'}, - {'cron-month': '10'} - ] - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' Unit tests for na_ontap_job_schedule ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.mock_job = { - 'name': 'test_job', - 'minutes': '25' - } - - def mock_args(self): - return { - 'name': self.mock_job['name'], - 'job_minutes': [self.mock_job['minutes']], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - - def get_job_mock_object(self, kind=None): - """ - Helper method to return an na_ontap_job_schedule object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_job_schedule object - """ - job_obj = job_module() - job_obj.autosupport_log = Mock(return_value=None) - if kind is None: - job_obj.server = MockONTAPConnection() - else: - job_obj.server = MockONTAPConnection(kind=kind, data=self.mock_job) - return job_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - job_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_nonexistent_job(self): - ''' Test if get_job_schedule returns None for non-existent job ''' - set_module_args(self.mock_args()) - result = self.get_job_mock_object().get_job_schedule() - assert result is None - - def test_get_existing_job(self): - ''' Test if get_job_schedule retuns job details for existing job ''' - data = self.mock_args() - set_module_args(data) - result = self.get_job_mock_object('job').get_job_schedule() - assert result['name'] == self.mock_job['name'] - assert result['job_minutes'] == data['job_minutes'] - - def test_get_existing_job_multiple_minutes(self): - ''' Test if get_job_schedule retuns job details for existing job ''' - set_module_args(self.mock_args()) - result = self.get_job_mock_object('job_multiple').get_job_schedule() - print(str(result)) - assert result['name'] == self.mock_job['name'] - assert result['job_minutes'] == ['25', '35'] - assert result['job_months'] == ['5', '10'] - - def test_create_error_missing_param(self): - ''' Test if create throws an error if job_minutes is not specified''' - data = self.mock_args() - del data['job_minutes'] - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_job_mock_object('job').create_job_schedule() - msg = 'Error: missing required parameter job_minutes for create' - assert exc.value.args[0]['msg'] == msg - - def test_successful_create(self): - ''' Test successful create ''' - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_job_mock_object().apply() - assert exc.value.args[0]['changed'] - - def test_create_idempotency(self): - ''' Test create idempotency ''' - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_job_mock_object('job').apply() - assert not exc.value.args[0]['changed'] - - def test_successful_delete(self): - ''' Test delete existing job ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_job_mock_object('job').apply() - assert exc.value.args[0]['changed'] - - def test_delete_idempotency(self): - ''' Test delete idempotency ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_job_mock_object().apply() - assert not exc.value.args[0]['changed'] - - def test_successful_modify(self): - ''' Test successful modify job_minutes ''' - data = self.mock_args() - data['job_minutes'] = ['20'] - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_job_mock_object('job').apply() - assert exc.value.args[0]['changed'] - - def test_modify_idempotency(self): - ''' Test modify idempotency ''' - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_job_mock_object('job').apply() - assert not exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_kerberos_realm.py b/test/units/modules/storage/netapp/test_na_ontap_kerberos_realm.py deleted file mode 100644 index abe44766c2..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_kerberos_realm.py +++ /dev/null @@ -1,239 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test for ONTAP Kerberos Realm module ''' - -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import json -import pytest -import ansible.module_utils.netapp as netapp_utils -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -from ansible.modules.storage.netapp.na_ontap_kerberos_realm \ - import NetAppOntapKerberosRealm as my_module # module under test -from units.compat import unittest -from units.compat.mock import patch -from units.compat.mock import Mock - - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - print(Exception) - # pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - print(Exception) - # pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None): - ''' save arguments ''' - self.type = kind - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - - if self.type == 'present_realm': - xml = self.build_realm() - else: - xml = self.build_empty_realm() - - self.xml_out = xml - return xml - - @staticmethod - def build_realm(): - ''' build xml data for kerberos realm ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': "1", - 'attributes-list': { - 'kerberos-realm': { - 'admin-server-ip': "192.168.0.1", - 'admin-server-port': "749", - 'clock-skew': "5", - 'kdc-ip': "192.168.0.1", - 'kdc-port': "88", - 'kdc-vendor': "other", - 'password-server-ip': "192.168.0.1", - 'password-server-port': "464", - "permitted-enc-types": { - "string": ["des", "des3", "aes_128", "aes_256"] - }, - 'realm': "EXAMPLE.COM", - 'vserver-name': "vserver0" - } - } - } - xml.translate_struct(attributes) - return xml - - @staticmethod - def build_empty_realm(): - ''' build xml data for kerberos realm ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': "0", - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection(kind='present_realm') - - @staticmethod - def get_kerberos_realm_mock_object(kind=None): - """ - Helper method to return an na_ontap_volume object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_volume object - """ - krbrealm_obj = my_module() - krbrealm_obj.asup_log_for_cserver = Mock(return_value=None) - krbrealm_obj.cluster = Mock() - krbrealm_obj.cluster.invoke_successfully = Mock() - if kind is None: - krbrealm_obj.server = MockONTAPConnection() - else: - krbrealm_obj.server = MockONTAPConnection(kind=kind) - return krbrealm_obj - - @staticmethod - def mock_args(): - '''Set default arguments''' - return dict({ - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'https': True, - 'validate_certs': False - }) - - @staticmethod - def test_module_fail_when_required_args_missing(): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_module_fail_when_state_present_required_args_missing(self): - ''' required arguments are reported as errors ''' - data = self.mock_args() - data['state'] = 'present' - data['vserver'] = 'vserver1' - data['realm'] = 'NETAPP.COM' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args(data) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_nonexistent_realm(self): - ''' Test if get_krbrealm returns None for non-existent kerberos realm ''' - data = self.mock_args() - data['vserver'] = 'none' - data['realm'] = 'none' - data['state'] = 'present' - data['kdc_ip'] = 'none' - data['kdc_vendor'] = 'Other' - set_module_args(data) - result = self.get_kerberos_realm_mock_object().get_krbrealm() - assert result is None - - def test_get_existing_realm(self): - ''' Test if get_krbrealm returns details for existing kerberos realm ''' - data = self.mock_args() - data['vserver'] = 'vserver0' - data['realm'] = 'EXAMPLE.COM' - data['state'] = 'present' - data['kdc_ip'] = '10.0.0.1' - data['kdc_vendor'] = 'Other' - set_module_args(data) - result = self.get_kerberos_realm_mock_object('present_realm').get_krbrealm() - assert result['realm'] - - def test_successfully_modify_realm(self): - ''' Test modify realm successful for modifying kdc_ip. ''' - data = self.mock_args() - data['vserver'] = 'vserver0' - data['realm'] = 'EXAMPLE.COM' - data['kdc_ip'] = '192.168.10.10' - data['state'] = 'present' - data['kdc_ip'] = '10.0.0.1' - data['kdc_vendor'] = 'Other' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_kerberos_realm_mock_object('present_realm').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_kerberos_realm.NetAppOntapKerberosRealm.delete_krbrealm') - def test_successfully_delete_realm(self, delete_krbrealm): - ''' Test successfully delete realm ''' - data = self.mock_args() - data['state'] = 'absent' - data['vserver'] = 'vserver0' - data['realm'] = 'EXAMPLE.COM' - set_module_args(data) - obj = self.get_kerberos_realm_mock_object('present_realm') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert exc.value.args[0]['changed'] - delete_krbrealm.assert_called_with() - - @patch('ansible.modules.storage.netapp.na_ontap_kerberos_realm.NetAppOntapKerberosRealm.create_krbrealm') - def test_successfully_create_realm(self, create_krbrealm): - ''' Test successfully create realm ''' - data = self.mock_args() - data['state'] = 'present' - data['vserver'] = 'vserver1' - data['realm'] = 'NETAPP.COM' - data['kdc_ip'] = '10.0.0.1' - data['kdc_vendor'] = 'Other' - set_module_args(data) - obj = self.get_kerberos_realm_mock_object() - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert exc.value.args[0]['changed'] - create_krbrealm.assert_called_with() diff --git a/test/units/modules/storage/netapp/test_na_ontap_lun_copy.py b/test/units/modules/storage/netapp/test_na_ontap_lun_copy.py deleted file mode 100644 index bfadcaf081..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_lun_copy.py +++ /dev/null @@ -1,159 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_lun_copy \ - import NetAppOntapLUNCopy as my_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, parm1=None): - ''' save arguments ''' - self.type = kind - self.parm1 = parm1 - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'destination_vserver': - xml = self.build_lun_info(self.parm1) - self.xml_out = xml - return xml - - @staticmethod - def build_lun_info(data): - ''' build xml data for lun-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.mock_lun_copy = { - 'source_vserver': 'ansible', - 'destination_path': '/vol/test/test_copy_dest_dest_new_reviewd_new', - 'source_path': '/vol/test/test_copy_1', - 'destination_vserver': 'ansible', - 'state': 'present' - } - - def mock_args(self): - - return { - 'source_vserver': self.mock_lun_copy['source_vserver'], - 'destination_path': self.mock_lun_copy['destination_path'], - 'source_path': self.mock_lun_copy['source_path'], - 'destination_vserver': self.mock_lun_copy['destination_vserver'], - 'state': self.mock_lun_copy['state'], - 'hostname': 'hostname', - 'username': 'username', - 'password': 'password', - } - # self.server = MockONTAPConnection() - - def get_lun_copy_mock_object(self, kind=None): - """ - Helper method to return an na_ontap_lun_copy object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_interface object - """ - lun_copy_obj = my_module() - lun_copy_obj.autosupport_log = Mock(return_value=None) - if kind is None: - lun_copy_obj.server = MockONTAPConnection() - else: - lun_copy_obj.server = MockONTAPConnection(kind=kind) - return lun_copy_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_create_error_missing_param(self): - ''' Test if create throws an error if required param 'destination_vserver' is not specified''' - data = self.mock_args() - del data['destination_vserver'] - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_lun_copy_mock_object('lun_copy').copy_lun() - msg = 'Error: Missing one or more required parameters for copying lun: ' \ - 'destination_path, source_path, destination_path' - expected = sorted(','.split(msg)) - received = sorted(','.split(exc.value.args[0]['msg'])) - assert expected == received - - def test_successful_copy(self): - ''' Test successful create ''' - # data = self.mock_args() - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_lun_copy_mock_object().apply() - assert exc.value.args[0]['changed'] - - def test_copy_idempotency(self): - ''' Test create idempotency ''' - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_lun_copy_mock_object('destination_vserver').apply() - assert not exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_lun_map.py b/test/units/modules/storage/netapp/test_na_ontap_lun_map.py deleted file mode 100644 index c8c5d14957..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_lun_map.py +++ /dev/null @@ -1,191 +0,0 @@ -''' unit tests ONTAP Ansible module: na_ontap_lun_map ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_lun_map \ - import NetAppOntapLUNMap as my_module - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None): - ''' save arguments ''' - self.type = kind - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'lun_map': - xml = self.build_lun_info() - elif self.type == 'lun_map_fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - @staticmethod - def build_lun_info(): - ''' build xml data for lun-map-entry ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'initiator-groups': [{'initiator-group-info': {'initiator-group-name': 'ansible', 'lun-id': 2}}]} - xml.translate_struct(data) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.onbox = False - - def set_default_args(self): - if self.onbox: - hostname = '10.10.10.10' - username = 'admin' - password = 'password' - initiator_group_name = 'ansible' - vserver = 'ansible' - path = '/vol/ansible/test' - lun_id = 2 - else: - hostname = 'hostname' - username = 'username' - password = 'password' - initiator_group_name = 'ansible' - vserver = 'ansible' - path = '/vol/ansible/test' - lun_id = 2 - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'initiator_group_name': initiator_group_name, - 'vserver': vserver, - 'path': path, - 'lun_id': lun_id - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_get_called(self): - ''' test get_lun_map for non-existent lun''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - assert my_obj.get_lun_map is not None - - def test_ensure_get_called_existing(self): - ''' test get_lun_map for existing lun''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='lun_map') - assert my_obj.get_lun_map() - - @patch('ansible.modules.storage.netapp.na_ontap_lun_map.NetAppOntapLUNMap.create_lun_map') - def test_successful_create(self, create_lun_map): - ''' mapping lun and testing idempotency ''' - data = self.set_default_args() - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - create_lun_map.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - set_module_args(self.set_default_args()) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('lun_map') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_lun_map.NetAppOntapLUNMap.delete_lun_map') - def test_successful_delete(self, delete_lun_map): - ''' unmapping lun and testing idempotency ''' - data = self.set_default_args() - data['state'] = 'absent' - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('lun_map') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - delete_lun_map.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - def test_if_all_methods_catch_exception(self): - module_args = {} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('lun_map_fail') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.create_lun_map() - assert 'Error mapping lun' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.delete_lun_map() - assert 'Error unmapping lun' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_motd.py b/test/units/modules/storage/netapp/test_na_ontap_motd.py deleted file mode 100644 index dec9d2e91d..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_motd.py +++ /dev/null @@ -1,181 +0,0 @@ -# (c) 2019, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -""" unit tests for Ansible module: na_ontap_motd """ - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_motd \ - import NetAppONTAPMotd as my_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None): - ''' save arguments ''' - self.type = kind - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'motd': - xml = self.build_motd_info() - elif self.type == 'motd_fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - @staticmethod - def build_motd_info(): - ''' build xml data for motd ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 1, - 'attributes-list': {'vserver-motd-info': {'message': 'ansible', - 'vserver': 'ansible', - 'is-cluster-message-enabled': 'true'}}} - xml.translate_struct(data) - print(xml.to_string()) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - # whether to use a mock or a simulator - self.onbox = False - - def set_default_args(self): - if self.onbox: - hostname = '10.10.10.10' - username = 'admin' - password = 'password' - message = 'ansible' - vserver = 'ansible' - show_cluster_motd = 'true' - else: - hostname = 'hostname' - username = 'username' - password = 'password' - message = 'ansible' - vserver = 'ansible' - show_cluster_motd = 'true' - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'message': message, - 'vserver': vserver, - 'show_cluster_motd': show_cluster_motd - }) - - def call_command(self, module_args): - ''' utility function to call apply ''' - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('motd') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - return exc.value.args[0]['changed'] - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_motd_get_called(self): - ''' fetching details of motd ''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - assert my_obj.motd_get() is None - - def test_ensure_get_called_existing(self): - ''' test for existing motd''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='motd') - assert my_obj.motd_get() - - def test_motd_create(self): - ''' test for creating motd''' - set_module_args(self.set_default_args()) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection(kind='motd') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - def test_motd_delete(self): - ''' test for deleting motd''' - module_args = { - 'state': 'absent', - } - changed = self.call_command(module_args) - assert changed - - def test_if_all_methods_catch_exception(self): - set_module_args(self.set_default_args()) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('motd_fail') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.motd_get() - assert '' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.modify_motd() - assert 'Error creating motd: ' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_ndmp.py b/test/units/modules/storage/netapp/test_na_ontap_ndmp.py deleted file mode 100644 index 69cd58049f..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_ndmp.py +++ /dev/null @@ -1,166 +0,0 @@ -# (c) 2019, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_ndmp \ - import NetAppONTAPNdmp as ndmp_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.type = kind - self.data = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'ndmp': - xml = self.build_ndmp_info(self.data) - if self.type == 'error': - error = netapp_utils.zapi.NaApiError('test', 'error') - raise error - self.xml_out = xml - return xml - - @staticmethod - def build_ndmp_info(ndmp_details): - ''' build xml data for ndmp ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'ndmp-vserver-attributes-info': { - 'ignore_ctime_enabled': ndmp_details['ignore_ctime_enabled'], - 'backup_log_enable': ndmp_details['backup_log_enable'], - 'authtype': [ - {'ndmpd-authtypes': 'plaintext'}, - {'ndmpd-authtypes': 'challenge'} - ] - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.mock_ndmp = { - 'ignore_ctime_enabled': 'true', - 'backup_log_enable': 'false' - } - - def mock_args(self): - return { - 'ignore_ctime_enabled': self.mock_ndmp['ignore_ctime_enabled'], - 'backup_log_enable': self.mock_ndmp['backup_log_enable'], - 'vserver': 'ansible', - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'https': 'False' - } - - def get_ndmp_mock_object(self, kind=None): - """ - Helper method to return an na_ontap_ndmp object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_ndmp object - """ - obj = ndmp_module() - obj.asup_log_for_cserver = Mock(return_value=None) - obj.server = Mock() - obj.server.invoke_successfully = Mock() - if kind is None: - obj.server = MockONTAPConnection() - else: - obj.server = MockONTAPConnection(kind=kind, data=self.mock_ndmp) - return obj - - @patch('ansible.modules.storage.netapp.na_ontap_ndmp.NetAppONTAPNdmp.ndmp_get_iter') - def test_successful_modify(self, ger_ndmp): - ''' Test successful modify ndmp''' - data = self.mock_args() - set_module_args(data) - current = { - 'ignore_ctime_enabled': False, - 'backup_log_enable': True - } - ger_ndmp.side_effect = [ - current - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_ndmp_mock_object('ndmp').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_ndmp.NetAppONTAPNdmp.ndmp_get_iter') - def test_modify_error(self, ger_ndmp): - ''' Test modify error ''' - data = self.mock_args() - set_module_args(data) - current = { - 'ignore_ctime_enabled': False, - 'backup_log_enable': True - } - ger_ndmp.side_effect = [ - current - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_ndmp_mock_object('error').apply() - assert exc.value.args[0]['msg'] == 'Error modifying ndmp on ansible: NetApp API failed. Reason - test:error' diff --git a/test/units/modules/storage/netapp/test_na_ontap_net_ifgrp.py b/test/units/modules/storage/netapp/test_na_ontap_net_ifgrp.py deleted file mode 100644 index 498dc46930..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_net_ifgrp.py +++ /dev/null @@ -1,298 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_net_ifgrp \ - import NetAppOntapIfGrp as ifgrp_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'ifgrp': - xml = self.build_ifgrp_info(self.params) - elif self.kind == 'ifgrp-ports': - xml = self.build_ifgrp_ports_info(self.params) - elif self.kind == 'ifgrp-fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - @staticmethod - def build_ifgrp_info(ifgrp_details): - ''' build xml data for ifgrp-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'net-port-info': { - 'port': ifgrp_details['name'], - 'ifgrp-distribution-function': 'mac', - 'ifgrp-mode': ifgrp_details['mode'], - 'node': ifgrp_details['node'] - } - } - } - xml.translate_struct(attributes) - return xml - - @staticmethod - def build_ifgrp_ports_info(data): - ''' build xml data for ifgrp-ports ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'attributes': { - 'net-ifgrp-info': { - 'ports': [ - {'lif-bindable': data['ports'][0]}, - {'lif-bindable': data['ports'][1]}, - {'lif-bindable': data['ports'][2]} - ] - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.mock_ifgrp = { - 'name': 'test', - 'port': 'a1', - 'node': 'test_vserver', - 'mode': 'something' - } - - def mock_args(self): - return { - 'name': self.mock_ifgrp['name'], - 'distribution_function': 'mac', - 'ports': [self.mock_ifgrp['port']], - 'node': self.mock_ifgrp['node'], - 'mode': self.mock_ifgrp['mode'], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - - def get_ifgrp_mock_object(self, kind=None, data=None): - """ - Helper method to return an na_ontap_net_ifgrp object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_net_ifgrp object - """ - obj = ifgrp_module() - obj.autosupport_log = Mock(return_value=None) - if data is None: - data = self.mock_ifgrp - obj.server = MockONTAPConnection(kind=kind, data=data) - return obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - ifgrp_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_nonexistent_ifgrp(self): - ''' Test if get_ifgrp returns None for non-existent ifgrp ''' - set_module_args(self.mock_args()) - result = self.get_ifgrp_mock_object().get_if_grp() - assert result is None - - def test_get_existing_ifgrp(self): - ''' Test if get_ifgrp returns details for existing ifgrp ''' - set_module_args(self.mock_args()) - result = self.get_ifgrp_mock_object('ifgrp').get_if_grp() - assert result['name'] == self.mock_ifgrp['name'] - - def test_successful_create(self): - ''' Test successful create ''' - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_ifgrp_mock_object().apply() - assert exc.value.args[0]['changed'] - - def test_successful_delete(self): - ''' Test delete existing volume ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_ifgrp_mock_object('ifgrp').apply() - assert exc.value.args[0]['changed'] - - def test_successful_modify(self): - ''' Test delete existing volume ''' - data = self.mock_args() - data['ports'] = ['1', '2', '3'] - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_ifgrp_mock_object('ifgrp').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_net_ifgrp.NetAppOntapIfGrp.get_if_grp') - @patch('ansible.modules.storage.netapp.na_ontap_net_ifgrp.NetAppOntapIfGrp.create_if_grp') - def test_create_called(self, create_ifgrp, get_ifgrp): - data = self.mock_args() - set_module_args(data) - get_ifgrp.return_value = None - with pytest.raises(AnsibleExitJson) as exc: - self.get_ifgrp_mock_object().apply() - get_ifgrp.assert_called_with() - create_ifgrp.assert_called_with() - - @patch('ansible.modules.storage.netapp.na_ontap_net_ifgrp.NetAppOntapIfGrp.add_port_to_if_grp') - def test_if_ports_are_added_after_create(self, add_ports): - ''' Test successful create ''' - data = self.mock_args() - set_module_args(data) - self.get_ifgrp_mock_object().create_if_grp() - add_ports.assert_called_with('a1') - - @patch('ansible.modules.storage.netapp.na_ontap_net_ifgrp.NetAppOntapIfGrp.get_if_grp') - @patch('ansible.modules.storage.netapp.na_ontap_net_ifgrp.NetAppOntapIfGrp.delete_if_grp') - def test_delete_called(self, delete_ifgrp, get_ifgrp): - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - get_ifgrp.return_value = Mock() - with pytest.raises(AnsibleExitJson) as exc: - self.get_ifgrp_mock_object().apply() - get_ifgrp.assert_called_with() - delete_ifgrp.assert_called_with() - - def test_get_return_value(self): - data = self.mock_args() - set_module_args(data) - result = self.get_ifgrp_mock_object('ifgrp').get_if_grp() - assert result['name'] == data['name'] - assert result['mode'] == data['mode'] - assert result['node'] == data['node'] - - def test_get_ports_list(self): - data = self.mock_args() - data['ports'] = ['e0a', 'e0b', 'e0c'] - set_module_args(data) - result = self.get_ifgrp_mock_object('ifgrp-ports', data).get_if_grp_ports() - assert result['ports'] == data['ports'] - - def test_add_port_packet(self): - data = self.mock_args() - set_module_args(data) - obj = self.get_ifgrp_mock_object('ifgrp') - obj.add_port_to_if_grp('addme') - assert obj.server.xml_in['port'] == 'addme' - - @patch('ansible.modules.storage.netapp.na_ontap_net_ifgrp.NetAppOntapIfGrp.remove_port_to_if_grp') - @patch('ansible.modules.storage.netapp.na_ontap_net_ifgrp.NetAppOntapIfGrp.add_port_to_if_grp') - def test_modify_ports_calls_remove_existing_ports(self, add_port, remove_port): - ''' Test if already existing ports are not being added again ''' - data = self.mock_args() - data['ports'] = ['1', '2'] - set_module_args(data) - self.get_ifgrp_mock_object('ifgrp').modify_ports(current_ports=['1', '2', '3']) - assert remove_port.call_count == 1 - assert add_port.call_count == 0 - - @patch('ansible.modules.storage.netapp.na_ontap_net_ifgrp.NetAppOntapIfGrp.remove_port_to_if_grp') - @patch('ansible.modules.storage.netapp.na_ontap_net_ifgrp.NetAppOntapIfGrp.add_port_to_if_grp') - def test_modify_ports_calls_add_new_ports(self, add_port, remove_port): - ''' Test new ports are added ''' - data = self.mock_args() - data['ports'] = ['1', '2', '3', '4'] - set_module_args(data) - self.get_ifgrp_mock_object('ifgrp').modify_ports(current_ports=['1', '2']) - assert remove_port.call_count == 0 - assert add_port.call_count == 2 - - def test_get_ports_returns_none(self): - set_module_args(self.mock_args()) - result = self.get_ifgrp_mock_object().get_if_grp_ports() - assert result['ports'] == [] - result = self.get_ifgrp_mock_object().get_if_grp() - assert result is None - - def test_if_all_methods_catch_exception(self): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleFailJson) as exc: - self.get_ifgrp_mock_object('ifgrp-fail').get_if_grp() - assert 'Error getting if_group test' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - self.get_ifgrp_mock_object('ifgrp-fail').create_if_grp() - assert 'Error creating if_group test' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - self.get_ifgrp_mock_object('ifgrp-fail').get_if_grp_ports() - assert 'Error getting if_group ports test' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - self.get_ifgrp_mock_object('ifgrp-fail').add_port_to_if_grp('test-port') - assert 'Error adding port test-port to if_group test' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - self.get_ifgrp_mock_object('ifgrp-fail').remove_port_to_if_grp('test-port') - assert 'Error removing port test-port to if_group test' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - self.get_ifgrp_mock_object('ifgrp-fail').delete_if_grp() - assert 'Error deleting if_group test' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_net_port.py b/test/units/modules/storage/netapp/test_na_ontap_net_port.py deleted file mode 100644 index b557a964b6..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_net_port.py +++ /dev/null @@ -1,179 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_net_port \ - import NetAppOntapNetPort as port_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.type = kind - self.data = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'port': - xml = self.build_port_info(self.data) - self.xml_out = xml - return xml - - @staticmethod - def build_port_info(port_details): - ''' build xml data for net-port-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'net-port-info': { - # 'port': port_details['port'], - 'mtu': port_details['mtu'], - 'is-administrative-auto-negotiate': 'true', - 'ipspace': 'default', - 'administrative-flowcontrol': port_details['flowcontrol_admin'], - 'node': port_details['node'] - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.mock_port = { - 'node': 'test', - 'ports': 'a1', - 'flowcontrol_admin': 'something', - 'mtu': '1000' - } - - def mock_args(self): - return { - 'node': self.mock_port['node'], - 'flowcontrol_admin': self.mock_port['flowcontrol_admin'], - 'ports': [self.mock_port['ports']], - 'mtu': self.mock_port['mtu'], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - - def get_port_mock_object(self, kind=None, data=None): - """ - Helper method to return an na_ontap_net_port object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_net_port object - """ - obj = port_module() - obj.autosupport_log = Mock(return_value=None) - if data is None: - data = self.mock_port - obj.server = MockONTAPConnection(kind=kind, data=data) - return obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - port_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_nonexistent_port(self): - ''' Test if get_net_port returns None for non-existent port ''' - set_module_args(self.mock_args()) - result = self.get_port_mock_object().get_net_port('test') - assert result is None - - def test_get_existing_port(self): - ''' Test if get_net_port returns details for existing port ''' - set_module_args(self.mock_args()) - result = self.get_port_mock_object('port').get_net_port('test') - assert result['mtu'] == self.mock_port['mtu'] - assert result['flowcontrol_admin'] == self.mock_port['flowcontrol_admin'] - - def test_successful_modify(self): - ''' Test modify_net_port ''' - data = self.mock_args() - data['mtu'] = '2000' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_port_mock_object('port').apply() - assert exc.value.args[0]['changed'] - - def test_successful_modify_multiple_ports(self): - ''' Test modify_net_port ''' - data = self.mock_args() - data['ports'] = ['a1', 'a2'] - data['mtu'] = '2000' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_port_mock_object('port').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_net_port.NetAppOntapNetPort.get_net_port') - def test_get_called(self, get_port): - ''' Test get_net_port ''' - data = self.mock_args() - data['ports'] = ['a1', 'a2'] - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_port_mock_object('port').apply() - assert get_port.call_count == 2 diff --git a/test/units/modules/storage/netapp/test_na_ontap_net_routes.py b/test/units/modules/storage/netapp/test_na_ontap_net_routes.py deleted file mode 100644 index 6e383098f9..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_net_routes.py +++ /dev/null @@ -1,309 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_net_routes \ - import NetAppOntapNetRoutes as net_route_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'net_route': - xml = self.build_net_route_info(self.params) - self.xml_out = xml - return xml - - @staticmethod - def build_net_route_info(net_route_details): - ''' build xml data for net_route-attributes ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'attributes': { - 'net-vs-routes-info': { - 'address-family': 'ipv4', - 'destination': net_route_details['destination'], - 'gateway': net_route_details['gateway'], - 'metric': net_route_details['metric'], - 'vserver': net_route_details['vserver'] - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.mock_net_route = { - 'destination': '176.0.0.0/24', - 'gateway': '10.193.72.1', - 'vserver': 'test_vserver', - 'metric': '70' - } - - def mock_args(self): - return { - 'vserver': self.mock_net_route['vserver'], - 'destination': self.mock_net_route['destination'], - 'gateway': self.mock_net_route['gateway'], - 'metric': self.mock_net_route['metric'], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - - def get_net_route_mock_object(self, kind=None, data=None): - """ - Helper method to return an na_ontap_net_route object - :param kind: passes this param to MockONTAPConnection() - :param data: passes this data to MockONTAPConnection() - :return: na_ontap_net_route object - """ - net_route_obj = net_route_module() - net_route_obj.ems_log_event = Mock(return_value=None) - net_route_obj.cluster = Mock() - net_route_obj.cluster.invoke_successfully = Mock() - if kind is None: - net_route_obj.server = MockONTAPConnection() - else: - if data is None: - net_route_obj.server = MockONTAPConnection(kind='net_route', data=self.mock_net_route) - else: - net_route_obj.server = MockONTAPConnection(kind='net_route', data=data) - return net_route_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - net_route_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_nonexistent_net_route(self): - ''' Test if get_net_route returns None for non-existent net_route ''' - set_module_args(self.mock_args()) - result = self.get_net_route_mock_object().get_net_route() - assert result is None - - def test_get_existing_job(self): - ''' Test if get_net_route returns details for existing net_route ''' - set_module_args(self.mock_args()) - result = self.get_net_route_mock_object('net_route').get_net_route() - assert result['destination'] == self.mock_net_route['destination'] - assert result['gateway'] == self.mock_net_route['gateway'] - - def test_create_error_missing_param(self): - ''' Test if create throws an error if destination is not specified''' - data = self.mock_args() - del data['destination'] - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_net_route_mock_object('net_route').create_net_route() - msg = 'missing required arguments: destination' - assert exc.value.args[0]['msg'] == msg - - @patch('ansible.modules.storage.netapp.na_ontap_net_routes.NetAppOntapNetRoutes.create_net_route') - def test_successful_create(self, create_net_route): - ''' Test successful create ''' - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_net_route_mock_object().apply() - assert exc.value.args[0]['changed'] - create_net_route.assert_called_with() - - def test_create_idempotency(self): - ''' Test create idempotency ''' - set_module_args(self.mock_args()) - obj = self.get_net_route_mock_object('net_route') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert not exc.value.args[0]['changed'] - - def test_successful_delete(self): - ''' Test successful delete ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_net_route_mock_object('net_route').apply() - assert exc.value.args[0]['changed'] - - def test_delete_idempotency(self): - ''' Test delete idempotency ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_net_route_mock_object().apply() - assert not exc.value.args[0]['changed'] - - def test_successful_modify_metric(self): - ''' Test successful modify metric ''' - data = self.mock_args() - del data['metric'] - data['from_metric'] = '70' - data['metric'] = '40' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_net_route_mock_object('net_route').apply() - assert exc.value.args[0]['changed'] - - def test_modify_metric_idempotency(self): - ''' Test modify metric idempotency''' - data = self.mock_args() - data['metric'] = '70' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_net_route_mock_object('net_route').apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_net_routes.NetAppOntapNetRoutes.get_net_route') - def test_successful_modify_gateway(self, get_net_route): - ''' Test successful modify gateway ''' - data = self.mock_args() - del data['gateway'] - data['from_gateway'] = '10.193.72.1' - data['gateway'] = '10.193.0.1' - set_module_args(data) - current = { - 'destination': '176.0.0.0/24', - 'gateway': '10.193.72.1', - 'metric': '70', - 'vserver': 'test_server' - } - get_net_route.side_effect = [ - None, - current - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_net_route_mock_object().apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_net_routes.NetAppOntapNetRoutes.get_net_route') - def test__modify_gateway_idempotency(self, get_net_route): - ''' Test modify gateway idempotency ''' - data = self.mock_args() - del data['gateway'] - data['from_gateway'] = '10.193.72.1' - data['gateway'] = '10.193.0.1' - set_module_args(data) - current = { - 'destination': '178.0.0.1/24', - 'gateway': '10.193.72.1', - 'metric': '70', - 'vserver': 'test_server' - } - get_net_route.side_effect = [ - current, - None - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_net_route_mock_object('net_route', current).apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_net_routes.NetAppOntapNetRoutes.get_net_route') - def test_successful_modify_destination(self, get_net_route): - ''' Test successful modify destination ''' - data = self.mock_args() - del data['destination'] - data['from_destination'] = '176.0.0.0/24' - data['destination'] = '178.0.0.1/24' - set_module_args(data) - current = { - 'destination': '176.0.0.0/24', - 'gateway': '10.193.72.1', - 'metric': '70', - 'vserver': 'test_server' - } - get_net_route.side_effect = [ - None, - current - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_net_route_mock_object().apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_net_routes.NetAppOntapNetRoutes.get_net_route') - def test__modify_destination_idempotency(self, get_net_route): - ''' Test modify destination idempotency''' - data = self.mock_args() - del data['destination'] - data['from_destination'] = '176.0.0.0/24' - data['destination'] = '178.0.0.1/24' - set_module_args(data) - current = { - 'destination': '178.0.0.1/24', - 'gateway': '10.193.72.1', - 'metric': '70', - 'vserver': 'test_server' - } - get_net_route.side_effect = [ - current, - None - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_net_route_mock_object('net_route', current).apply() - assert not exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_net_subnet.py b/test/units/modules/storage/netapp/test_na_ontap_net_subnet.py deleted file mode 100644 index d18498143f..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_net_subnet.py +++ /dev/null @@ -1,264 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_net_subnet \ - import NetAppOntapSubnet as my_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.type = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if xml.get_child_by_name('query') is not None and \ - xml.get_child_by_name('query').get_child_by_name('vserver-info') is not None: - # assume this a a cserver request - xml = self.build_cserver_info() - elif self.type == 'subnet': - if xml.get_child_by_name('query'): - name_obj = xml.get_child_by_name('query').get_child_by_name('net-subnet-info').get_child_by_name('subnet-name') - xml_name = name_obj.get_content() - if xml_name == self.params.get('name'): - xml = self.build_subnet_info(self.params) - elif self.type == 'subnet_fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - @staticmethod - def build_cserver_info(): - ''' build xml data for vserver-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'vserver-info': { - 'vserver-name': 'cserver', - } - } - } - xml.translate_struct(attributes) - return xml - - @staticmethod - def build_subnet_info(data): - ''' build xml data for subnet-info ''' - xml = netapp_utils.zapi.NaElement('xml') - ip_ranges = [] - for elem in data['ip_ranges']: - ip_ranges.append({'ip-range': elem}) - attributes = { - 'num-records': 1, - 'attributes-list': { - 'net-subnet-info': { - 'broadcast-domain': data['broadcast_domain'], - 'gateway': data['gateway'], - 'ip-ranges': ip_ranges, - 'ipspace': data['ipspace'], - 'subnet': data['subnet'], - 'subnet-name': data['name'], - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - - def set_default_args(self): - return dict({ - 'name': 'test_subnet', - 'hostname': 'hostname', - 'username': 'username', - 'password': 'password', - 'broadcast_domain': 'Default', - 'gateway': '10.0.0.1', - 'ipspace': 'Default', - 'subnet': '10.0.0.0/24', - 'ip_ranges': ['10.0.0.10-10.0.0.20', '10.0.0.30'] - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_get_called(self): - ''' test get_subnet for non-existent subnet''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - assert my_obj.get_subnet() is None - - def test_ensure_get_called_existing(self): - ''' test get_subnet for existing subnet''' - data = self.set_default_args() - set_module_args(data) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='subnet', data=data) - assert my_obj.get_subnet() is not None - - @patch('ansible.module_utils.netapp.ems_log_event') - def test_fail_broadcast_domain_modify(self, mock_ems_log): - ''' test that boradcast_domain is not alterable ''' - data = self.set_default_args() - data.update({'broadcast_domain': 'Test'}) - set_module_args(data) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='subnet', data=self.set_default_args()) - with pytest.raises(AnsibleFailJson) as exc: - my_obj.apply() - assert 'cannot modify broadcast_domain parameter' in exc.value.args[0]['msg'] - - @patch('ansible.module_utils.netapp.ems_log_event') - @patch('ansible.modules.storage.netapp.na_ontap_net_subnet.NetAppOntapSubnet.create_subnet') - def test_successful_create(self, create_subnet, mock_ems_log): - ''' creating subnet and testing idempotency ''' - print("Create:") - data = self.set_default_args() - set_module_args(data) - my_obj = my_module() - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - create_subnet.assert_called_with() - - # to reset na_helper from remembering the previous 'changed' value - print("reset:") - data = self.set_default_args() - set_module_args(data) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='subnet', data=data) - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.ems_log_event') - @patch('ansible.modules.storage.netapp.na_ontap_net_subnet.NetAppOntapSubnet.rename_subnet') - def test_successful_rename(self, rename_subnet, mock_ems_log): - ''' renaming subnet ''' - data = self.set_default_args() - data.update({'from_name': data['name'], 'name': 'new_test_subnet'}) - set_module_args(data) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='subnet', data=self.set_default_args()) - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.ems_log_event') - @patch('ansible.modules.storage.netapp.na_ontap_net_subnet.NetAppOntapSubnet.delete_subnet') - def test_successful_delete(self, delete_subnet, mock_ems_log): - ''' deleting subnet and testing idempotency ''' - data = self.set_default_args() - data['state'] = 'absent' - set_module_args(data) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='subnet', data=data) - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - delete_subnet.assert_called_with() - - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.ems_log_event') - def test_successful_modify(self, mock_ems_log): - ''' modifying subnet and testing idempotency ''' - data = self.set_default_args() - data.update({'ip_ranges': ['10.0.0.10-10.0.0.25', '10.0.0.30']}) - set_module_args(data) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='subnet', data=self.set_default_args()) - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.ems_log_event') - def test_if_all_methods_catch_exception(self, mock_ems_log): - data = self.set_default_args() - set_module_args(data) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='subnet_fail', data=data) - with pytest.raises(AnsibleFailJson) as exc: - my_obj.create_subnet() - assert 'Error creating subnet' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.delete_subnet() - assert 'Error deleting subnet' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.modify_subnet() - assert 'Error modifying subnet' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.rename_subnet() - assert 'Error renaming subnet' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_nfs.py b/test/units/modules/storage/netapp/test_na_ontap_nfs.py deleted file mode 100644 index c1083894dd..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_nfs.py +++ /dev/null @@ -1,308 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_nfs \ - import NetAppONTAPNFS as nfs_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None, job_error=None): - ''' save arguments ''' - self.kind = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'nfs': - xml = self.build_nfs_info(self.params) - self.xml_out = xml - if self.kind == 'nfs_status': - xml = self.build_nfs_status_info(self.params) - return xml - - @staticmethod - def build_nfs_info(nfs_details): - ''' build xml data for volume-attributes ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - "attributes-list": { - "nfs-info": { - "auth-sys-extended-groups": "false", - "cached-cred-harvest-timeout": "86400000", - "cached-cred-negative-ttl": "7200000", - "cached-cred-positive-ttl": "86400000", - "cached-transient-err-ttl": "30000", - "chown-mode": "use_export_policy", - "enable-ejukebox": "true", - "extended-groups-limit": "32", - "file-session-io-grouping-count": "5000", - "file-session-io-grouping-duration": "120", - "ignore-nt-acl-for-root": "false", - "is-checksum-enabled-for-replay-cache": "true", - "is-mount-rootonly-enabled": "true", - "is-netgroup-dns-domain-search": "true", - "is-nfs-access-enabled": "false", - "is-nfs-rootonly-enabled": "false", - "is-nfsv2-enabled": "false", - "is-nfsv3-64bit-identifiers-enabled": "false", - "is-nfsv3-connection-drop-enabled": "true", - "is-nfsv3-enabled": "true", - "is-nfsv3-fsid-change-enabled": "true", - "is-nfsv4-fsid-change-enabled": "true", - "is-nfsv4-numeric-ids-enabled": "true", - "is-nfsv40-acl-enabled": "false", - "is-nfsv40-enabled": "true", - "is-nfsv40-migration-enabled": "false", - "is-nfsv40-read-delegation-enabled": "false", - "is-nfsv40-referrals-enabled": "false", - "is-nfsv40-req-open-confirm-enabled": "false", - "is-nfsv40-write-delegation-enabled": "false", - "is-nfsv41-acl-enabled": "false", - "is-nfsv41-acl-preserve-enabled": "true", - "is-nfsv41-enabled": "true", - "is-nfsv41-migration-enabled": "false", - "is-nfsv41-pnfs-enabled": "true", - "is-nfsv41-read-delegation-enabled": "false", - "is-nfsv41-referrals-enabled": "false", - "is-nfsv41-state-protection-enabled": "true", - "is-nfsv41-write-delegation-enabled": "false", - "is-qtree-export-enabled": "false", - "is-rquota-enabled": "false", - "is-tcp-enabled": "false", - "is-udp-enabled": "false", - "is-v3-ms-dos-client-enabled": "false", - "is-validate-qtree-export-enabled": "true", - "is-vstorage-enabled": "false", - "map-unknown-uid-to-default-windows-user": "true", - "mountd-port": "635", - "name-service-lookup-protocol": "udp", - "netgroup-trust-any-ns-switch-no-match": "false", - "nfsv4-acl-max-aces": "400", - "nfsv4-grace-seconds": "45", - "nfsv4-id-domain": "defaultv4iddomain.com", - "nfsv4-lease-seconds": "30", - "nfsv41-implementation-id-domain": "netapp.com", - "nfsv41-implementation-id-name": "NetApp Release Kalyaniblack__9.4.0", - "nfsv41-implementation-id-time": "1541070767", - "nfsv4x-session-num-slots": "180", - "nfsv4x-session-slot-reply-cache-size": "640", - "nlm-port": "4045", - "nsm-port": "4046", - "ntacl-display-permissive-perms": "false", - "ntfs-unix-security-ops": "use_export_policy", - "permitted-enc-types": { - "string": ["des", "des3", "aes_128", "aes_256"] - }, - "rpcsec-ctx-high": "0", - "rpcsec-ctx-idle": "0", - "rquotad-port": "4049", - "showmount": "true", - "showmount-timestamp": "1548372452", - "skip-root-owner-write-perm-check": "false", - "tcp-max-xfer-size": "1048576", - "udp-max-xfer-size": "32768", - "v3-search-unconverted-filename": "false", - "v4-inherited-acl-preserve": "false", - "vserver": "ansible" - } - }, - "num-records": "1" - } - xml.translate_struct(attributes) - return xml - - @staticmethod - def build_nfs_status_info(nfs_status_details): - ''' build xml data for volume-attributes ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'is-enabled': "true" - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.mock_nfs_group = { - 'vserver': 'nfs_vserver', - } - - def mock_args(self): - return { - 'vserver': self.mock_nfs_group['vserver'], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'https': 'False' - } - - def get_nfs_mock_object(self, kind=None): - """ - Helper method to return an na_ontap_volume object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_volume object - """ - nfsy_obj = nfs_module() - nfsy_obj.asup_log_for_cserver = Mock(return_value=None) - nfsy_obj.cluster = Mock() - nfsy_obj.cluster.invoke_successfully = Mock() - if kind is None: - nfsy_obj.server = MockONTAPConnection() - else: - nfsy_obj.server = MockONTAPConnection(kind=kind, data=self.mock_nfs_group) - return nfsy_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - nfs_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_nonexistent_nfs(self): - ''' Test if get_nfs_service returns None for non-existent nfs ''' - set_module_args(self.mock_args()) - result = self.get_nfs_mock_object().get_nfs_service() - assert result is None - - def test_get_existing_nfs(self): - ''' Test if get_policy_group returns details for existing nfs ''' - set_module_args(self.mock_args()) - result = self.get_nfs_mock_object('nfs').get_nfs_service() - assert result['is_nfsv3_enabled'] - - def test_get_nonexistent_nfs_status(self): - ''' Test if get__nfs_status returns None for non-existent nfs ''' - set_module_args(self.mock_args()) - result = self.get_nfs_mock_object().get_nfs_status() - assert result is None - - def test_get_existing_nfs_status(self): - ''' Test if get__nfs_status returns details for nfs ''' - set_module_args(self.mock_args()) - result = self.get_nfs_mock_object('nfs_status').get_nfs_status() - assert result - - def test_modify_nfs(self): - ''' Test if modify_nfs runs for existing nfs ''' - data = self.mock_args() - data['nfsv3'] = 'enabled' - data['nfsv3_fsid_change'] = 'enabled' - data['nfsv4'] = 'enabled' - data['nfsv41'] = 'enabled' - data['vstorage_state'] = 'enabled' - data['tcp'] = 'enabled' - data['udp'] = 'enabled' - data['nfsv4_id_domain'] = 'nfsv4_id_domain' - data['nfsv40_acl'] = 'enabled' - data['nfsv40_read_delegation'] = 'enabled' - data['nfsv40_write_delegation'] = 'enabled' - data['nfsv41_acl'] = 'enabled' - data['nfsv41_read_delegation'] = 'enabled' - data['nfsv41_write_delegation'] = 'enabled' - data['showmount'] = 'enabled' - data['tcp_max_xfer_size'] = '1048576' - set_module_args(data) - self.get_nfs_mock_object('nfs_status').modify_nfs() - - def test_successfully_modify_nfs(self): - ''' Test modify nfs successful for modifying tcp max xfer size. ''' - data = self.mock_args() - data['tcp_max_xfer_size'] = '8192' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_nfs_mock_object('nfs').apply() - assert exc.value.args[0]['changed'] - - def test_modify_nfs_idempotency(self): - ''' Test modify nfs idempotency ''' - data = self.mock_args() - data['tcp_max_xfer_size'] = '1048576' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_nfs_mock_object('nfs').apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_nfs.NetAppONTAPNFS.delete_nfs') - def test_successfully_delete_nfs(self, delete_nfs): - ''' Test successfully delete nfs ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - obj = self.get_nfs_mock_object('nfs') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert exc.value.args[0]['changed'] - delete_nfs.assert_called_with() - - @patch('ansible.modules.storage.netapp.na_ontap_nfs.NetAppONTAPNFS.get_nfs_service') - def test_successfully_enable_nfs(self, get_nfs_service): - ''' Test successfully enable nfs on non-existent nfs ''' - data = self.mock_args() - data['state'] = 'present' - set_module_args(data) - get_nfs_service.side_effect = [ - None, - {} - ] - obj = self.get_nfs_mock_object('nfs') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_nvme.py b/test/units/modules/storage/netapp/test_na_ontap_nvme.py deleted file mode 100644 index 190cd8ab7f..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_nvme.py +++ /dev/null @@ -1,216 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests ONTAP Ansible module: na_ontap_nvme''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_nvme \ - import NetAppONTAPNVMe as my_module - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None): - ''' save arguments ''' - self.type = kind - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'nvme': - xml = self.build_nvme_info() - elif self.type == 'nvme_fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - @staticmethod - def build_nvme_info(): - ''' build xml data for nvme-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 1, - 'attributes-list': [{'nvme-target-service-info': {'is-available': 'true'}}]} - xml.translate_struct(data) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.onbox = False - - def set_default_args(self): - if self.onbox: - hostname = '10.193.75.3' - username = 'admin' - password = 'netapp1!' - vserver = 'ansible' - status_admin = True - else: - hostname = 'hostname' - username = 'username' - password = 'password' - vserver = 'vserver' - status_admin = True - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'vserver': vserver, - 'status_admin': status_admin - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_get_called(self): - ''' test get_nvme() for non-existent nvme''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - assert my_obj.get_nvme() is None - - def test_ensure_get_called_existing(self): - ''' test get_nvme() for existing nvme''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='nvme') - assert my_obj.get_nvme() - - @patch('ansible.modules.storage.netapp.na_ontap_nvme.NetAppONTAPNVMe.create_nvme') - def test_successful_create(self, create_nvme): - ''' creating nvme and testing idempotency ''' - set_module_args(self.set_default_args()) - my_obj = my_module() - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - create_nvme.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('nvme') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_nvme.NetAppONTAPNVMe.delete_nvme') - def test_successful_delete(self, delete_nvme): - ''' deleting nvme and testing idempotency ''' - data = self.set_default_args() - data['state'] = 'absent' - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('nvme') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - delete_nvme.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_nvme.NetAppONTAPNVMe.modify_nvme') - def test_successful_modify(self, modify_nvme): - ''' modifying nvme and testing idempotency ''' - data = self.set_default_args() - data['status_admin'] = False - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('nvme') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - modify_nvme.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - data = self.set_default_args() - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('nvme') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - def test_if_all_methods_catch_exception(self): - module_args = {} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('nvme_fail') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.get_nvme() - assert 'Error fetching nvme info:' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.create_nvme() - assert 'Error creating nvme' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.delete_nvme() - assert 'Error deleting nvme' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.modify_nvme() - assert 'Error modifying nvme' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_nvme_namespace.py b/test/units/modules/storage/netapp/test_na_ontap_nvme_namespace.py deleted file mode 100644 index fd669112fa..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_nvme_namespace.py +++ /dev/null @@ -1,197 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests ONTAP Ansible module: na_ontap_nvme_namespace''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_nvme_namespace \ - import NetAppONTAPNVMENamespace as my_module - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None): - ''' save arguments ''' - self.type = kind - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'namespace': - xml = self.build_namespace_info() - elif self.type == 'quota_fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - @staticmethod - def build_namespace_info(): - ''' build xml data for namespace-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 2, - 'attributes-list': [{'nvme-namespace-info': {'path': 'abcd/vol'}}, - {'nvme-namespace-info': {'path': 'xyz/vol'}}]} - xml.translate_struct(data) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.onbox = False - - def set_default_args(self): - if self.onbox: - hostname = '10.193.75.3' - username = 'admin' - password = 'netapp1!' - vserver = 'ansible' - ostype = 'linux' - path = 'abcd/vol' - size = 20 - else: - hostname = 'hostname' - username = 'username' - password = 'password' - vserver = 'vserver' - ostype = 'linux' - path = 'abcd/vol' - size = 20 - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'ostype': ostype, - 'vserver': vserver, - 'path': path, - 'size': size - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_get_called(self): - ''' test get_namespace() for non-existent namespace''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - assert my_obj.get_namespace() is None - - def test_ensure_get_called_existing(self): - ''' test get_namespace() for existing namespace''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='namespace') - assert my_obj.get_namespace() - - @patch('ansible.modules.storage.netapp.na_ontap_nvme_namespace.NetAppONTAPNVMENamespace.create_namespace') - def test_successful_create(self, create_namespace): - ''' creating namespace and testing idempotency ''' - set_module_args(self.set_default_args()) - my_obj = my_module() - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - create_namespace.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('namespace') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_nvme_namespace.NetAppONTAPNVMENamespace.delete_namespace') - def test_successful_delete(self, delete_namespace): - ''' deleting namespace and testing idempotency ''' - data = self.set_default_args() - data['state'] = 'absent' - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('namespace') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - delete_namespace.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - def test_if_all_methods_catch_exception(self): - module_args = {} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('quota_fail') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.get_namespace() - assert 'Error fetching namespace info:' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.create_namespace() - assert 'Error creating namespace for path' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.delete_namespace() - assert 'Error deleting namespace for path' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_nvme_subsystem.py b/test/units/modules/storage/netapp/test_na_ontap_nvme_subsystem.py deleted file mode 100644 index b047817ff8..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_nvme_subsystem.py +++ /dev/null @@ -1,241 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests ONTAP Ansible module: na_ontap_nvme_subsystem ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_nvme_subsystem \ - import NetAppONTAPNVMESubsystem as my_module - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, parm1=None): - ''' save arguments ''' - self.type = kind - self.parm1 = parm1 - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'subsystem': - xml = self.build_subsystem_info(self.parm1) - self.xml_out = xml - return xml - - @staticmethod - def build_subsystem_info(vserver): - ''' build xml data for vserser-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 2, - 'attributes-list': [{'nvme-target-subsystem-map-info': {'path': 'abcd/vol'}}, - {'nvme-target-subsystem-map-info': {'path': 'xyz/vol'}}]} - xml.translate_struct(data) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.onbox = False - - def set_default_args(self): - if self.onbox: - hostname = '10.193.75.3' - username = 'admin' - password = 'netapp1!' - subsystem = 'test' - vserver = 'ansible' - ostype = 'linux' - paths = ['abcd/vol', 'xyz/vol'] - else: - hostname = 'hostname' - username = 'username' - password = 'password' - subsystem = 'test' - vserver = 'vserver' - ostype = 'linux' - paths = ['abcd/vol', 'xyz/vol'] - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'subsystem': subsystem, - 'ostype': ostype, - 'vserver': vserver, - 'paths': paths - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_get_called(self): - ''' test get_subsystem() for non-existent subsystem''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - assert my_obj.get_subsystem() is None - - def test_ensure_get_called_existing(self): - ''' test get_subsystem() for existing subsystem''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='subsystem') - assert my_obj.get_subsystem() - - @patch('ansible.modules.storage.netapp.na_ontap_nvme_subsystem.NetAppONTAPNVMESubsystem.create_subsystem') - def test_successful_create(self, create_subsystem): - ''' creating subsystem and testing idempotency ''' - set_module_args(self.set_default_args()) - my_obj = my_module() - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - create_subsystem.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('subsystem') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_nvme_subsystem.NetAppONTAPNVMESubsystem.delete_subsystem') - def test_successful_delete(self, delete_subsystem): - ''' deleting subsystem and testing idempotency ''' - data = self.set_default_args() - data['state'] = 'absent' - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('subsystem') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - delete_subsystem.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - def test_ensure_get_called(self): - ''' test get_subsystem_host_map() for non-existent subsystem''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - assert my_obj.get_subsystem_host_map('paths') is None - - def test_ensure_get_called_existing(self): - ''' test get_subsystem_host_map() for existing subsystem''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='subsystem') - assert my_obj.get_subsystem_host_map('paths') - - @patch('ansible.modules.storage.netapp.na_ontap_nvme_subsystem.NetAppONTAPNVMESubsystem.add_subsystem_host_map') - def test_successful_add_mock(self, add_subsystem_host_map): - ''' adding subsystem host/map and testing idempotency ''' - set_module_args(self.set_default_args()) - my_obj = my_module() - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - add_subsystem_host_map.assert_called_with(['abcd/vol', 'xyz/vol'], 'paths') - - @patch('ansible.modules.storage.netapp.na_ontap_nvme_subsystem.NetAppONTAPNVMESubsystem.remove_subsystem_host_map') - def test_successful_remove_mock(self, remove_subsystem_host_map): - ''' removing subsystem host/map and testing idempotency ''' - data = self.set_default_args() - data['paths'] = ['abcd/vol'] - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('subsystem') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - remove_subsystem_host_map.assert_called_with(['xyz/vol'], 'paths') - - def test_successful_add(self): - ''' adding subsystem host/map and testing idempotency ''' - set_module_args(self.set_default_args()) - my_obj = my_module() - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - - def test_successful_remove(self): - ''' removing subsystem host/map and testing idempotency ''' - data = self.set_default_args() - data['paths'] = ['abcd/vol'] - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('subsystem') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_object_store.py b/test/units/modules/storage/netapp/test_na_ontap_object_store.py deleted file mode 100644 index a15de05c79..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_object_store.py +++ /dev/null @@ -1,200 +0,0 @@ -# (c) 2019, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -""" unit tests for Ansible module: na_ontap_object_store """ - -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_object_store \ - import NetAppOntapObjectStoreConfig as my_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None): - ''' save arguments ''' - self.type = kind - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'object_store': - xml = self.build_object_store_info() - elif self.type == 'object_store_fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - @staticmethod - def build_object_store_info(): - ''' build xml data for object store ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'attributes': - {'aggr-object-store-config-info': - {'object-store-name': 'ansible'} - } - } - xml.translate_struct(data) - print(xml.to_string()) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - # whether to use a mock or a simulator - self.onbox = False - - def set_default_args(self): - if self.onbox: - hostname = '10.10.10.10' - username = 'admin' - password = 'password' - name = 'ansible' - else: - hostname = 'hostname' - username = 'username' - password = 'password' - name = 'ansible' - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'name': name - }) - - def call_command(self, module_args): - ''' utility function to call apply ''' - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - # mock the connection - my_obj.server = MockONTAPConnection('object_store') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - return exc.value.args[0]['changed'] - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_object_store_get_called(self): - ''' fetching details of object store ''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - assert my_obj.get_aggr_object_store() is not None - - def test_ensure_get_called_existing(self): - ''' test for existing object store''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='object_store') - assert my_obj.get_aggr_object_store() - - def test_object_store_create(self): - ''' test for creating object store''' - module_args = { - 'provider_type': 'abc', - 'server': 'abc', - 'container': 'abc', - 'access_key': 'abc', - 'secret_password': 'abc' - } - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - # mock the connection - my_obj.server = MockONTAPConnection(kind='object_store') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - def test_object_store_delete(self): - ''' test for deleting object store''' - module_args = { - 'state': 'absent', - } - changed = self.call_command(module_args) - assert changed - - def test_if_all_methods_catch_exception(self): - module_args = { - 'provider_type': 'abc', - 'server': 'abc', - 'container': 'abc', - 'access_key': 'abc', - 'secret_password': 'abc' - } - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('object_store_fail') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.get_aggr_object_store() - assert '' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.create_aggr_object_store() - assert 'Error provisioning object store config ' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.delete_aggr_object_store() - assert 'Error removing object store config ' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_ports.py b/test/units/modules/storage/netapp/test_na_ontap_ports.py deleted file mode 100644 index 84ea4699cf..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_ports.py +++ /dev/null @@ -1,173 +0,0 @@ -# (c) 2019, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests for ONTAP Ansible module: na_ontap_port''' - -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_ports \ - import NetAppOntapPorts as port_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - - def mock_args(self, choice): - if choice == 'broadcast_domain': - return { - 'names': ['test_port_1', 'test_port_2'], - 'resource_name': 'test_domain', - 'resource_type': 'broadcast_domain', - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - elif choice == 'portset': - return { - 'names': ['test_lif'], - 'resource_name': 'test_portset', - 'resource_type': 'portset', - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'vserver': 'test_vserver' - } - - def get_port_mock_object(self): - """ - Helper method to return an na_ontap_port object - """ - port_obj = port_module() - port_obj.asup_log_for_cserver = Mock(return_value=None) - port_obj.server = Mock() - port_obj.server.invoke_successfully = Mock() - - return port_obj - - @patch('ansible.modules.storage.netapp.na_ontap_ports.NetAppOntapPorts.add_broadcast_domain_ports') - @patch('ansible.modules.storage.netapp.na_ontap_ports.NetAppOntapPorts.get_broadcast_domain_ports') - def test_successfully_add_broadcast_domain_ports(self, get_broadcast_domain_ports, add_broadcast_domain_ports): - ''' Test successful add broadcast domain ports ''' - data = self.mock_args('broadcast_domain') - set_module_args(data) - get_broadcast_domain_ports.side_effect = [ - [] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_port_mock_object().apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_ports.NetAppOntapPorts.add_broadcast_domain_ports') - @patch('ansible.modules.storage.netapp.na_ontap_ports.NetAppOntapPorts.get_broadcast_domain_ports') - def test_add_broadcast_domain_ports_idempotency(self, get_broadcast_domain_ports, add_broadcast_domain_ports): - ''' Test add broadcast domain ports idempotency ''' - data = self.mock_args('broadcast_domain') - set_module_args(data) - get_broadcast_domain_ports.side_effect = [ - ['test_port_1', 'test_port_2'] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_port_mock_object().apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_ports.NetAppOntapPorts.add_portset_ports') - @patch('ansible.modules.storage.netapp.na_ontap_ports.NetAppOntapPorts.portset_get') - def test_successfully_add_portset_ports(self, portset_get, add_portset_ports): - ''' Test successful add portset ports ''' - data = self.mock_args('portset') - set_module_args(data) - portset_get.side_effect = [ - [] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_port_mock_object().apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_ports.NetAppOntapPorts.add_portset_ports') - @patch('ansible.modules.storage.netapp.na_ontap_ports.NetAppOntapPorts.portset_get') - def test_add_portset_ports_idempotency(self, portset_get, add_portset_ports): - ''' Test add portset ports idempotency ''' - data = self.mock_args('portset') - set_module_args(data) - portset_get.side_effect = [ - ['test_lif'] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_port_mock_object().apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_ports.NetAppOntapPorts.add_broadcast_domain_ports') - @patch('ansible.modules.storage.netapp.na_ontap_ports.NetAppOntapPorts.get_broadcast_domain_ports') - def test_successfully_remove_broadcast_domain_ports(self, get_broadcast_domain_ports, add_broadcast_domain_ports): - ''' Test successful remove broadcast domain ports ''' - data = self.mock_args('broadcast_domain') - data['state'] = 'absent' - set_module_args(data) - get_broadcast_domain_ports.side_effect = [ - ['test_port_1', 'test_port_2'] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_port_mock_object().apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_ports.NetAppOntapPorts.add_portset_ports') - @patch('ansible.modules.storage.netapp.na_ontap_ports.NetAppOntapPorts.portset_get') - def test_remove_add_portset_ports(self, portset_get, add_portset_ports): - ''' Test successful remove portset ports ''' - data = self.mock_args('portset') - data['state'] = 'absent' - set_module_args(data) - portset_get.side_effect = [ - ['test_lif'] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_port_mock_object().apply() - assert exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_portset.py b/test/units/modules/storage/netapp/test_na_ontap_portset.py deleted file mode 100644 index 7b5f356ddd..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_portset.py +++ /dev/null @@ -1,189 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests for ONTAP Ansible module: na_ontap_portset''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_portset \ - import NetAppONTAPPortset as my_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, parm1=None, parm2=None, parm3=None): - ''' save arguments ''' - self.type = kind - self.parm1 = parm1 - self.parm2 = parm2 - self.parm3 = parm3 - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'portset': - xml = self.build_portset_info(self.parm1, self.parm2, self.parm3) - self.xml_out = xml - return xml - - @staticmethod - def build_portset_info(portset, vserver, type): - ''' build xml data for vserser-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 1, - 'attributes-list': {'portset-info': {'portset-name': portset, - 'vserver': vserver, 'portset-type': type, - 'portset-port-total': '0'}}} - xml.translate_struct(data) - print(xml.to_string()) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.use_vsim = False - - def set_default_args(self): - if self.use_vsim: - hostname = '10.193.77.154' - username = 'admin' - password = 'netapp1!' - name = 'test' - type = 'mixed' - vserver = 'ansible_test' - ports = ['a1', 'a2'] - else: - hostname = 'hostname' - username = 'username' - password = 'password' - name = 'name' - type = 'mixed' - vserver = 'vserver' - ports = ['a1', 'a2'] - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'name': name, - 'type': type, - 'vserver': vserver, - 'ports': ports - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_portset_get_called(self): - ''' a more interesting test ''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - portset = my_obj.portset_get() - print('Info: test_portset_get: %s' % repr(portset)) - assert portset is None - - def test_ensure_portset_apply_called(self): - ''' Test successful create ''' - module_args = {'name': 'create'} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.use_vsim: - my_obj.server = self.server - portset = my_obj.portset_get() - print('Info: test_portset_get: %s' % repr(portset)) - assert portset is None - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_portset_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - if not self.use_vsim: - my_obj.server = MockONTAPConnection('portset', 'create', 'vserver', 'mixed') - portset = my_obj.portset_get() - print('Info: test_portset_get: %s' % repr(portset)) - assert portset is not None - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_portset_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - - def test_modify_ports(self): - ''' Test modify_portset method ''' - module_args = {'ports': ['l1', 'l2']} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.use_vsim: - my_obj.server = MockONTAPConnection('portset') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_portset_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - - def test_delete_portset(self): - ''' Test successful delete ''' - module_args = {'state': 'absent'} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.use_vsim: - my_obj.server = MockONTAPConnection('portset') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_portset_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_qos_adaptive_policy_group.py b/test/units/modules/storage/netapp/test_na_ontap_qos_adaptive_policy_group.py deleted file mode 100644 index 06683dff14..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_qos_adaptive_policy_group.py +++ /dev/null @@ -1,347 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_qos_adaptive_policy_group \ - import NetAppOntapAdaptiveQosPolicyGroup as qos_policy_group_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'policy': - xml = self.build_policy_group_info(self.params) - if self.kind == 'error': - error = netapp_utils.zapi.NaApiError('test', 'error') - raise error - self.xml_out = xml - return xml - - @staticmethod - def build_policy_group_info(vol_details): - ''' build xml data for volume-attributes ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'qos-adaptive-policy-group-info': { - 'absolute-min-iops': '50IOPS', - 'expected-iops': '150IOPS/TB', - 'peak-iops': '220IOPS/TB', - 'peak-iops-allocation': 'used_space', - 'num-workloads': 0, - 'pgid': 6941, - 'policy-group': vol_details['name'], - 'vserver': vol_details['vserver'] - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.mock_policy_group = { - 'name': 'policy_1', - 'vserver': 'policy_vserver', - 'absolute_min_iops': '50IOPS', - 'expected_iops': '150IOPS/TB', - 'peak_iops': '220IOPS/TB', - 'peak_iops_allocation': 'used_space' - } - - def mock_args(self): - return { - 'name': self.mock_policy_group['name'], - 'vserver': self.mock_policy_group['vserver'], - 'absolute_min_iops': '50IOPS', - 'expected_iops': '150IOPS/TB', - 'peak_iops': '220IOPS/TB', - 'peak_iops_allocation': 'used_space', - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'https': 'False' - } - - def get_policy_group_mock_object(self, kind=None): - """ - Helper method to return an na_ontap_volume object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_volume object - """ - policy_obj = qos_policy_group_module() - policy_obj.autosupport_log = Mock(return_value=None) - policy_obj.cluster = Mock() - policy_obj.cluster.invoke_successfully = Mock() - if kind is None: - policy_obj.server = MockONTAPConnection() - else: - policy_obj.server = MockONTAPConnection(kind=kind, data=self.mock_policy_group) - return policy_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - qos_policy_group_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_nonexistent_policy(self): - ''' Test if get_policy_group returns None for non-existent policy_group ''' - set_module_args(self.mock_args()) - result = self.get_policy_group_mock_object().get_policy_group() - assert result is None - - def test_get_existing_policy_group(self): - ''' Test if get_policy_group returns details for existing policy_group ''' - set_module_args(self.mock_args()) - result = self.get_policy_group_mock_object('policy').get_policy_group() - assert result['name'] == self.mock_policy_group['name'] - assert result['vserver'] == self.mock_policy_group['vserver'] - - def test_create_error_missing_param(self): - ''' Test if create throws an error if name is not specified''' - data = self.mock_args() - del data['name'] - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_policy_group_mock_object('policy').create_policy_group() - msg = 'missing required arguments: name' - assert exc.value.args[0]['msg'] == msg - - def test_successful_create(self): - ''' Test successful create ''' - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_group_mock_object().apply() - assert exc.value.args[0]['changed'] - - def test_create_idempotency(self): - ''' Test create idempotency ''' - set_module_args(self.mock_args()) - obj = self.get_policy_group_mock_object('policy') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_qos_adaptive_policy_group.NetAppOntapAdaptiveQosPolicyGroup.get_policy_group') - def test_create_error(self, get_policy_group): - ''' Test create error ''' - set_module_args(self.mock_args()) - get_policy_group.side_effect = [ - None - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_policy_group_mock_object('error').apply() - assert exc.value.args[0]['msg'] == 'Error creating adaptive qos policy group policy_1: NetApp API failed. Reason - test:error' - - def test_successful_delete(self): - ''' Test delete existing volume ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_group_mock_object('policy').apply() - assert exc.value.args[0]['changed'] - - def test_delete_idempotency(self): - ''' Test delete idempotency ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_group_mock_object().apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_qos_adaptive_policy_group.NetAppOntapAdaptiveQosPolicyGroup.get_policy_group') - def test_delete_error(self, get_policy_group): - ''' Test create idempotency''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - current = { - 'absolute_min_iops': '50IOPS', - 'expected_iops': '150IOPS/TB', - 'peak_iops': '220IOPS/TB', - 'peak_iops_allocation': 'used_space', - 'name': 'policy_1', - 'vserver': 'policy_vserver' - } - get_policy_group.side_effect = [ - current - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_policy_group_mock_object('error').apply() - assert exc.value.args[0]['msg'] == 'Error deleting adaptive qos policy group policy_1: NetApp API failed. Reason - test:error' - - def test_successful_modify_expected_iops(self): - ''' Test successful modify expected iops ''' - data = self.mock_args() - data['expected_iops'] = '175IOPS' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_group_mock_object('policy').apply() - assert exc.value.args[0]['changed'] - - def test_modify_expected_iops_idempotency(self): - ''' Test modify idempotency ''' - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_group_mock_object('policy').apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_qos_adaptive_policy_group.NetAppOntapAdaptiveQosPolicyGroup.get_policy_group') - def test_modify_error(self, get_policy_group): - ''' Test create idempotency ''' - data = self.mock_args() - data['expected_iops'] = '175IOPS' - set_module_args(data) - current = { - 'absolute_min_iops': '50IOPS', - 'expected_iops': '150IOPS/TB', - 'peak_iops': '220IOPS/TB', - 'peak_iops_allocation': 'used_space', - 'name': 'policy_1', - 'vserver': 'policy_vserver' - } - get_policy_group.side_effect = [ - current - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_policy_group_mock_object('error').apply() - assert exc.value.args[0]['msg'] == 'Error modifying adaptive qos policy group policy_1: NetApp API failed. Reason - test:error' - - @patch('ansible.modules.storage.netapp.na_ontap_qos_adaptive_policy_group.NetAppOntapAdaptiveQosPolicyGroup.get_policy_group') - def test_rename(self, get_policy_group): - ''' Test rename idempotency ''' - data = self.mock_args() - data['name'] = 'policy_2' - data['from_name'] = 'policy_1' - set_module_args(data) - current = { - 'absolute_min_iops': '50IOPS', - 'expected_iops': '150IOPS/TB', - 'peak_iops': '220IOPS/TB', - 'peak_iops_allocation': 'used_space', - 'name': 'policy_1', - 'vserver': 'policy_vserver' - } - get_policy_group.side_effect = [ - None, - current - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_group_mock_object('policy').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_qos_adaptive_policy_group.NetAppOntapAdaptiveQosPolicyGroup.get_policy_group') - def test_rename_idempotency(self, get_policy_group): - ''' Test rename idempotency ''' - data = self.mock_args() - data['name'] = 'policy_1' - data['from_name'] = 'policy_1' - current = { - 'absolute_min_iops': '50IOPS', - 'expected_iops': '150IOPS/TB', - 'peak_iops': '220IOPS/TB', - 'peak_iops_allocation': 'used_space', - 'name': 'policy_1', - 'vserver': 'policy_vserver' - } - get_policy_group.side_effect = [ - current, - current - ] - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_group_mock_object('policy').apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_qos_adaptive_policy_group.NetAppOntapAdaptiveQosPolicyGroup.get_policy_group') - def test_rename_error(self, get_policy_group): - ''' Test create idempotency ''' - data = self.mock_args() - data['from_name'] = 'policy_1' - data['name'] = 'policy_2' - set_module_args(data) - current = { - 'absolute_min_iops': '50IOPS', - 'expected_iops': '150IOPS/TB', - 'peak_iops': '220IOPS/TB', - 'peak_iops_allocation': 'used_space', - 'is_shared': 'true', - 'name': 'policy_1', - 'vserver': 'policy_vserver' - } - get_policy_group.side_effect = [ - None, - current - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_policy_group_mock_object('error').apply() - assert exc.value.args[0]['msg'] == 'Error renaming adaptive qos policy group policy_1: NetApp API failed. Reason - test:error' diff --git a/test/units/modules/storage/netapp/test_na_ontap_qos_policy_group.py b/test/units/modules/storage/netapp/test_na_ontap_qos_policy_group.py deleted file mode 100644 index 6278d49e82..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_qos_policy_group.py +++ /dev/null @@ -1,331 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_qos_policy_group \ - import NetAppOntapQosPolicyGroup as qos_policy_group_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'policy': - xml = self.build_policy_group_info(self.params) - if self.kind == 'error': - error = netapp_utils.zapi.NaApiError('test', 'error') - raise error - self.xml_out = xml - return xml - - @staticmethod - def build_policy_group_info(vol_details): - ''' build xml data for volume-attributes ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'qos-policy-group-info': { - 'is-shared': 'true', - 'max-throughput': '800KB/s,800IOPS', - 'min-throughput': '100IOPS', - 'num-workloads': 0, - 'pgid': 8690, - 'policy-group': vol_details['name'], - 'vserver': vol_details['vserver'] - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.mock_policy_group = { - 'name': 'policy_1', - 'vserver': 'policy_vserver', - 'max_throughput': '800KB/s,800IOPS', - 'min_throughput': '100IOPS' - } - - def mock_args(self): - return { - 'name': self.mock_policy_group['name'], - 'vserver': self.mock_policy_group['vserver'], - 'max_throughput': '800KB/s,800IOPS', - 'min_throughput': '100IOPS', - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'https': 'False' - } - - def get_policy_group_mock_object(self, kind=None): - """ - Helper method to return an na_ontap_volume object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_volume object - """ - policy_obj = qos_policy_group_module() - policy_obj.asup_log_for_cserver = Mock(return_value=None) - policy_obj.cluster = Mock() - policy_obj.cluster.invoke_successfully = Mock() - if kind is None: - policy_obj.server = MockONTAPConnection() - else: - policy_obj.server = MockONTAPConnection(kind=kind, data=self.mock_policy_group) - return policy_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - qos_policy_group_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_nonexistent_policy(self): - ''' Test if get_policy_group returns None for non-existent policy_group ''' - set_module_args(self.mock_args()) - result = self.get_policy_group_mock_object().get_policy_group() - assert result is None - - def test_get_existing_policy_group(self): - ''' Test if get_policy_group returns details for existing policy_group ''' - set_module_args(self.mock_args()) - result = self.get_policy_group_mock_object('policy').get_policy_group() - assert result['name'] == self.mock_policy_group['name'] - assert result['vserver'] == self.mock_policy_group['vserver'] - - def test_create_error_missing_param(self): - ''' Test if create throws an error if name is not specified''' - data = self.mock_args() - del data['name'] - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_policy_group_mock_object('policy').create_policy_group() - msg = 'missing required arguments: name' - assert exc.value.args[0]['msg'] == msg - - def test_successful_create(self): - ''' Test successful create ''' - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_group_mock_object().apply() - assert exc.value.args[0]['changed'] - - def test_create_idempotency(self): - ''' Test create idempotency ''' - set_module_args(self.mock_args()) - obj = self.get_policy_group_mock_object('policy') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_qos_policy_group.NetAppOntapQosPolicyGroup.get_policy_group') - def test_create_error(self, get_policy_group): - ''' Test create error ''' - set_module_args(self.mock_args()) - get_policy_group.side_effect = [ - None - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_policy_group_mock_object('error').apply() - assert exc.value.args[0]['msg'] == 'Error creating qos policy group policy_1: NetApp API failed. Reason - test:error' - - def test_successful_delete(self): - ''' Test delete existing volume ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_group_mock_object('policy').apply() - assert exc.value.args[0]['changed'] - - def test_delete_idempotency(self): - ''' Test delete idempotency ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_group_mock_object().apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_qos_policy_group.NetAppOntapQosPolicyGroup.get_policy_group') - def test_delete_error(self, get_policy_group): - ''' Test create idempotency ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - current = { - 'max_throughput': '800KB/s,800IOPS', - 'min_throughput': '100IOPS', - 'name': 'policy_1', - 'vserver': 'policy_vserver' - } - get_policy_group.side_effect = [ - current - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_policy_group_mock_object('error').apply() - assert exc.value.args[0]['msg'] == 'Error deleting qos policy group policy_1: NetApp API failed. Reason - test:error' - - def test_successful_modify_max_throughput(self): - ''' Test successful modify max throughput ''' - data = self.mock_args() - data['max_throughput'] = '900KB/s,800iops' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_group_mock_object('policy').apply() - assert exc.value.args[0]['changed'] - - def test_modify_max_throughput_idempotency(self): - ''' Test modify idempotency ''' - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_group_mock_object('policy').apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_qos_policy_group.NetAppOntapQosPolicyGroup.get_policy_group') - def test_modify_error(self, get_policy_group): - ''' Test create idempotency ''' - data = self.mock_args() - data['max_throughput'] = '900KB/s,900IOPS' - set_module_args(data) - current = { - 'max_throughput': '800KB/s,800IOPS', - 'min_throughput': '100IOPS', - 'name': 'policy_1', - 'vserver': 'policy_vserver' - } - get_policy_group.side_effect = [ - current - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_policy_group_mock_object('error').apply() - assert exc.value.args[0]['msg'] == 'Error modifying qos policy group policy_1: NetApp API failed. Reason - test:error' - - @patch('ansible.modules.storage.netapp.na_ontap_qos_policy_group.NetAppOntapQosPolicyGroup.get_policy_group') - def test_rename(self, get_policy_group): - ''' Test rename idempotency ''' - data = self.mock_args() - data['name'] = 'policy_2' - data['from_name'] = 'policy_1' - set_module_args(data) - current = { - 'max_throughput': '800KB/s,800IOPS', - 'min_throughput': '100IOPS', - 'name': 'policy_1', - 'vserver': 'policy_vserver' - } - get_policy_group.side_effect = [ - None, - current - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_group_mock_object('policy').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_qos_policy_group.NetAppOntapQosPolicyGroup.get_policy_group') - def test_rename_idempotency(self, get_policy_group): - ''' Test rename idempotency ''' - data = self.mock_args() - data['name'] = 'policy_1' - data['from_name'] = 'policy_1' - current = { - 'max_throughput': '800KB/s,800IOPS', - 'min_throughput': '100IOPS', - 'name': 'policy_1', - 'vserver': 'policy_vserver' - } - get_policy_group.side_effect = [ - current, - current - ] - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_group_mock_object('policy').apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_qos_policy_group.NetAppOntapQosPolicyGroup.get_policy_group') - def test_rename_error(self, get_policy_group): - ''' Test create idempotency ''' - data = self.mock_args() - data['from_name'] = 'policy_1' - data['name'] = 'policy_2' - set_module_args(data) - current = { - 'is_shared': 'true', - 'max_throughput': '800KB/s,800IOPS', - 'min_throughput': '100IOPS', - 'name': 'policy_1', - 'vserver': 'policy_vserver' - } - get_policy_group.side_effect = [ - None, - current - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_policy_group_mock_object('error').apply() - assert exc.value.args[0]['msg'] == 'Error renaming qos policy group policy_1: NetApp API failed. Reason - test:error' diff --git a/test/units/modules/storage/netapp/test_na_ontap_quotas.py b/test/units/modules/storage/netapp/test_na_ontap_quotas.py deleted file mode 100644 index 3791a5f4d3..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_quotas.py +++ /dev/null @@ -1,238 +0,0 @@ -''' unit tests ONTAP Ansible module: na_ontap_quotas ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_quotas \ - import NetAppONTAPQuotas as my_module - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None): - ''' save arguments ''' - self.type = kind - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'quotas': - xml = self.build_quota_info() - elif self.type == 'quota_fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - @staticmethod - def build_quota_info(): - ''' build xml data for quota-entry ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 1, - 'attributes-list': {'quota-entry': {'volume': 'ansible', - 'file-limit': '-', 'disk-limit': '-', 'threshold': '-'}}, - 'status': 'true'} - xml.translate_struct(data) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.onbox = False - - def set_default_args(self): - if self.onbox: - hostname = '10.193.75.3' - username = 'admin' - password = 'netapp1!' - volume = 'ansible' - vserver = 'ansible' - policy = 'ansible' - quota_target = '/vol/ansible' - type = 'user' - else: - hostname = 'hostname' - username = 'username' - password = 'password' - volume = 'ansible' - vserver = 'ansible' - policy = 'ansible' - quota_target = '/vol/ansible' - type = 'user' - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'volume': volume, - 'vserver': vserver, - 'policy': policy, - 'quota_target': quota_target, - 'type': type - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_get_called(self): - ''' test get_quota for non-existent quota''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - assert my_obj.get_quotas is not None - - def test_ensure_get_called_existing(self): - ''' test get_quota for existing quota''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='quotas') - assert my_obj.get_quotas() - - @patch('ansible.modules.storage.netapp.na_ontap_quotas.NetAppONTAPQuotas.quota_entry_set') - def test_successful_create(self, quota_entry_set): - ''' creating quota and testing idempotency ''' - data = self.set_default_args() - data.update({'file_limit': '3', - 'disk_limit': '4'}) - # data['file_limit'] = '3' - # data['disk_limit'] = '4' - # data['threshold'] = '4' - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - quota_entry_set.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - set_module_args(self.set_default_args()) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('quotas') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_quotas.NetAppONTAPQuotas.quota_entry_delete') - def test_successful_delete(self, quota_entry_delete): - ''' deleting quota and testing idempotency ''' - data = self.set_default_args() - data['state'] = 'absent' - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('quotas') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - quota_entry_delete.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - def test_successful_modify(self): - ''' modifying quota and testing idempotency ''' - data = self.set_default_args() - data['file_limit'] = '3' - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('quotas') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - - def test_quota_on_off(self): - ''' quota set on or off ''' - data = self.set_default_args() - data['set_quota_status'] = 'false' - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('quotas') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - def test_if_all_methods_catch_exception(self): - module_args = {} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('quota_fail') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.get_quota_status() - assert 'Error fetching quotas status info' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.get_quotas() - assert 'Error fetching quotas info' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.quota_entry_set() - assert 'Error adding/modifying quota entry' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.quota_entry_delete() - assert 'Error deleting quota entry' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.quota_entry_modify(module_args) - assert 'Error modifying quota entry' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.on_or_off_quota('quota-on') - assert 'Error setting quota-on for ansible' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_security_key_manager.py b/test/units/modules/storage/netapp/test_na_ontap_security_key_manager.py deleted file mode 100644 index d1e7a7a6a7..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_security_key_manager.py +++ /dev/null @@ -1,173 +0,0 @@ -# (c) 2019, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_security_key_manager \ - import NetAppOntapSecurityKeyManager as key_manager_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.type = kind - self.data = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'key_manager': - xml = self.build_port_info(self.data) - self.xml_out = xml - return xml - - @staticmethod - def build_port_info(key_manager_details): - ''' build xml data for-key-manager-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'key-manager-info': { - 'key-manager-ip-address': '0.0.0.0', - 'key-manager-server-status': 'available', - 'key-manager-tcp-port': '5696', - 'node-name': 'test_node' - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.mock_key_manager = { - 'node_name': 'test_node', - 'tcp_port': 5696, - 'ip_address': '0.0.0.0', - 'server_status': 'available' - } - - def mock_args(self): - return { - 'node': self.mock_key_manager['node_name'], - 'tcp_port': self.mock_key_manager['tcp_port'], - 'ip_address': self.mock_key_manager['ip_address'], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'https': 'False' - } - - def get_key_manager_mock_object(self, kind=None): - """ - Helper method to return an na_ontap_security_key_manager object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_security_key_manager object - """ - obj = key_manager_module() - obj.asup_log_for_cserver = Mock(return_value=None) - obj.cluster = Mock() - obj.cluster.invoke_successfully = Mock() - if kind is None: - obj.cluster = MockONTAPConnection() - else: - obj.cluster = MockONTAPConnection(kind=kind, data=self.mock_key_manager) - return obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - key_manager_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_nonexistent_key_manager(self): - ''' Test if get_key_manager() returns None for non-existent key manager ''' - set_module_args(self.mock_args()) - result = self.get_key_manager_mock_object().get_key_manager() - assert result is None - - def test_get_existing_key_manager(self): - ''' Test if get_key_manager() returns details for existing key manager ''' - set_module_args(self.mock_args()) - result = self.get_key_manager_mock_object('key_manager').get_key_manager() - assert result['ip_address'] == self.mock_key_manager['ip_address'] - - @patch('ansible.modules.storage.netapp.na_ontap_security_key_manager.NetAppOntapSecurityKeyManager.get_key_manager') - def test_successfully_add_key_manager(self, get_key_manager): - ''' Test successfully add key manager''' - data = self.mock_args() - data['state'] = 'present' - set_module_args(data) - get_key_manager.side_effect = [ - None - ] - obj = self.get_key_manager_mock_object('key_manager') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert exc.value.args[0]['changed'] - - def test_successfully_delete_key_manager(self): - ''' Test successfully delete key manager''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - obj = self.get_key_manager_mock_object('key_manager') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_service_processor_network.py b/test/units/modules/storage/netapp/test_na_ontap_service_processor_network.py deleted file mode 100644 index b07509eb92..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_service_processor_network.py +++ /dev/null @@ -1,232 +0,0 @@ -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_service_processor_network \ - import NetAppOntapServiceProcessorNetwork as sp_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.data = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'sp-enabled': - xml = self.build_sp_info(self.data) - elif self.kind == 'sp-disabled': - xml = self.build_sp_disabled_info(self.data) - else: - xml = self.build_info() - self.xml_out = xml - return xml - - @staticmethod - def build_sp_info(sp): - ''' build xml data for vserser-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': - { - 'service-processor-network-info': - { - 'node-name': sp['node'], - 'is-enabled': 'true', - 'address-type': sp['address_type'], - 'dhcp': 'v4', - 'gateway-ip-address': sp['gateway_ip_address'], - 'netmask': sp['netmask'], - 'ip-address': sp['ip_address'], - 'setup-status': 'succeeded', - } - } - } - xml.translate_struct(attributes) - return xml - - @staticmethod - def build_info(): - ''' build xml data for vserser-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 0 - } - xml.translate_struct(attributes) - return xml - - @staticmethod - def build_sp_disabled_info(sp): - ''' build xml data for vserser-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': - { - 'service-processor-network-info': - { - 'node-name': sp['node'], - 'is-enabled': 'false', - 'address-type': sp['address_type'], - 'setup-status': 'not_setup', - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.mock_sp = { - 'node': 'test-vsim1', - 'gateway_ip_address': '2.2.2.2', - 'address_type': 'ipv4', - 'ip_address': '1.1.1.1', - 'netmask': '255.255.248.0', - 'dhcp': 'v4' - } - - def mock_args(self, enable=True): - data = { - 'node': self.mock_sp['node'], - 'is_enabled': enable, - 'address_type': self.mock_sp['address_type'], - 'hostname': 'host', - 'username': 'admin', - 'password': 'password', - } - if enable is True: - data['ip_address'] = self.mock_sp['ip_address'] - data['gateway_ip_address'] = self.mock_sp['gateway_ip_address'] - data['netmask'] = self.mock_sp['netmask'] - data['dhcp'] = 'v4' - return data - - def get_sp_mock_object(self, kind=None): - """ - Helper method to return an na_ontap_volume object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_volume object - """ - sp_obj = sp_module() - sp_obj.autosupport_log = Mock(return_value=None) - if kind is None: - sp_obj.server = MockONTAPConnection() - else: - sp_obj.server = MockONTAPConnection(kind=kind, data=self.mock_sp) - return sp_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - sp_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_modify_error_on_disabled_sp(self): - ''' a more interesting test ''' - data = self.mock_args(enable=False) - data['ip_address'] = self.mock_sp['ip_address'] - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_sp_mock_object('sp-disabled').apply() - assert 'Error: Cannot modify a service processor network if it is disabled.' in \ - exc.value.args[0]['msg'] - - def test_modify_sp(self): - ''' a more interesting test ''' - data = self.mock_args() - data['ip_address'] = '3.3.3.3' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_sp_mock_object('sp-enabled').apply() - assert exc.value.args[0]['changed'] - - def test_modify_sp_wait(self): - ''' a more interesting test ''' - data = self.mock_args() - data['ip_address'] = '3.3.3.3' - data['wait_for_completion'] = True - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_sp_mock_object('sp-enabled').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_service_processor_network.NetAppOntapServiceProcessorNetwork.' - 'get_service_processor_network') - def test_non_existing_sp(self, get_sp): - set_module_args(self.mock_args()) - get_sp.return_value = None - with pytest.raises(AnsibleFailJson) as exc: - self.get_sp_mock_object().apply() - assert 'Error No Service Processor for node: test-vsim1' in exc.value.args[0]['msg'] - - @patch('ansible.modules.storage.netapp.na_ontap_service_processor_network.NetAppOntapServiceProcessorNetwork.' - 'get_sp_network_status') - @patch('time.sleep') - def test_wait_on_sp_status(self, get_sp, sleep): - data = self.mock_args() - data['gateway_ip_address'] = '4.4.4.4' - data['wait_for_completion'] = True - set_module_args(data) - get_sp.side_effect = ['in_progress', 'done'] - with pytest.raises(AnsibleExitJson) as exc: - self.get_sp_mock_object('sp-enabled').apply() - sleep.assert_called_once_with() - assert exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_snapmirror.py b/test/units/modules/storage/netapp/test_na_ontap_snapmirror.py deleted file mode 100644 index 9ef67ccdcf..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_snapmirror.py +++ /dev/null @@ -1,574 +0,0 @@ -''' unit tests ONTAP Ansible module: na_ontap_snapmirror ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_snapmirror \ - import NetAppONTAPSnapmirror as my_module - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, parm=None, status=None): - ''' save arguments ''' - self.type = kind - self.xml_in = None - self.xml_out = None - self.parm = parm - self.status = status - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'snapmirror': - xml = self.build_snapmirror_info(self.parm, self.status) - elif self.type == 'snapmirror_fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - @staticmethod - def build_snapmirror_info(mirror_state, status): - ''' build xml data for snapmirror-entry ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 1, - 'attributes-list': {'snapmirror-info': {'mirror-state': mirror_state, 'schedule': None, - 'source-location': 'ansible:ansible', - 'relationship-status': status, 'policy': 'ansible', - 'relationship-type': 'data_protection', - 'max-transfer-rate': 1000, - 'identity-preserve': 'true'}, - 'snapmirror-destination-info': {'destination-location': 'ansible'}}} - xml.translate_struct(data) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.source_server = MockONTAPConnection() - self.onbox = False - - def set_default_args(self): - if self.onbox: - hostname = '10.10.10.10' - username = 'admin' - password = 'password' - source_path = 'ansible:ansible' - destination_path = 'ansible:ansible' - policy = 'ansible' - source_vserver = 'ansible' - destination_vserver = 'ansible' - relationship_type = 'data_protection' - schedule = None - source_username = 'admin' - source_password = 'password' - else: - hostname = '10.10.10.10' - username = 'admin' - password = 'password' - source_path = 'ansible:ansible' - destination_path = 'ansible:ansible' - policy = 'ansible' - source_vserver = 'ansible' - destination_vserver = 'ansible' - relationship_type = 'data_protection' - schedule = None - source_username = 'admin' - source_password = 'password' - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'source_path': source_path, - 'destination_path': destination_path, - 'policy': policy, - 'source_vserver': source_vserver, - 'destination_vserver': destination_vserver, - 'relationship_type': relationship_type, - 'schedule': schedule, - 'source_username': source_username, - 'source_password': source_password - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_get_called(self): - ''' test snapmirror_get for non-existent snapmirror''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - assert my_obj.snapmirror_get is not None - - def test_ensure_get_called_existing(self): - ''' test snapmirror_get for existing snapmirror''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='snapmirror', status='idle') - assert my_obj.snapmirror_get() - - @patch('ansible.modules.storage.netapp.na_ontap_snapmirror.NetAppONTAPSnapmirror.snapmirror_create') - def test_successful_create(self, snapmirror_create): - ''' creating snapmirror and testing idempotency ''' - data = self.set_default_args() - data['schedule'] = 'abc' - data['identity_preserve'] = True - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - snapmirror_create.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', 'snapmirrored', status='idle') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_snapmirror.NetAppONTAPSnapmirror.snapmirror_create') - @patch('ansible.modules.storage.netapp.na_ontap_snapmirror.NetAppONTAPSnapmirror.check_elementsw_parameters') - def test_successful_element_ontap_create(self, check_param, snapmirror_create): - ''' creating ElementSW to ONTAP snapmirror ''' - data = self.set_default_args() - data['schedule'] = 'abc' - data['connection_type'] = 'elementsw_ontap' - data['source_hostname'] = '10.10.10.10' - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - snapmirror_create.assert_called_with() - check_param.assert_called_with() - - @patch('ansible.modules.storage.netapp.na_ontap_snapmirror.NetAppONTAPSnapmirror.snapmirror_create') - @patch('ansible.modules.storage.netapp.na_ontap_snapmirror.NetAppONTAPSnapmirror.check_elementsw_parameters') - @patch('ansible.modules.storage.netapp.na_ontap_snapmirror.NetAppONTAPSnapmirror.snapmirror_get') - def test_successful_ontap_element_create(self, snapmirror_get, check_param, snapmirror_create): - ''' creating ONTAP to ElementSW snapmirror ''' - data = self.set_default_args() - data['schedule'] = 'abc' - data['connection_type'] = 'ontap_elementsw' - data['source_hostname'] = '10.10.10.10' - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - snapmirror_get.side_effect = [ - Mock(), - None - ] - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - snapmirror_create.assert_called_with() - check_param.assert_called_with('destination') - - @patch('ansible.modules.storage.netapp.na_ontap_snapmirror.NetAppONTAPSnapmirror.delete_snapmirror') - def test_successful_delete(self, delete_snapmirror): - ''' deleting snapmirror and testing idempotency ''' - data = self.set_default_args() - data['state'] = 'absent' - data['source_hostname'] = '10.10.10.10' - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - my_obj.get_destination = Mock(return_value=True) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='idle') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - delete_snapmirror.assert_called_with(False, 'data_protection') - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - def test_successful_delete_error_check(self): - ''' check required parameter source cluster hostname deleting snapmirror''' - data = self.set_default_args() - data['state'] = 'absent' - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='idle') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.apply() - assert 'Missing parameters for delete:' in exc.value.args[0]['msg'] - - def test_successful_delete_check_get_destination(self): - ''' check required parameter source cluster hostname deleting snapmirror''' - data = self.set_default_args() - data['state'] = 'absent' - data['source_hostname'] = '10.10.10.10' - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='idle') - my_obj.source_server = MockONTAPConnection('snapmirror', status='idle') - res = my_obj.get_destination() - assert res is True - - def test_snapmirror_release(self): - data = self.set_default_args() - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.source_server = MockONTAPConnection('snapmirror', status='idle', parm='snapmirrored') - my_obj.snapmirror_release() - assert my_obj.source_server.xml_in['destination-location'] == data['destination_path'] - - @patch('ansible.modules.storage.netapp.na_ontap_snapmirror.NetAppONTAPSnapmirror.snapmirror_abort') - def test_successful_abort(self, snapmirror_abort): - ''' deleting snapmirror and testing idempotency ''' - data = self.set_default_args() - data['state'] = 'absent' - data['source_hostname'] = '10.10.10.10' - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='transferring') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - snapmirror_abort.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_snapmirror.NetAppONTAPSnapmirror.snapmirror_modify') - def test_successful_modify(self, snapmirror_modify): - ''' modifying snapmirror and testing idempotency ''' - data = self.set_default_args() - data['policy'] = 'ansible2' - data['schedule'] = 'abc2' - data['max_transfer_rate'] = 2000 - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='idle') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - snapmirror_modify.assert_called_with({'policy': 'ansible2', 'schedule': 'abc2', 'max_transfer_rate': 2000}) - # to reset na_helper from remembering the previous 'changed' value - data = self.set_default_args() - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='idle', parm='snapmirrored') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_snapmirror.NetAppONTAPSnapmirror.snapmirror_initialize') - def test_successful_initialize(self, snapmirror_initialize): - ''' initialize snapmirror and testing idempotency ''' - data = self.set_default_args() - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='transferring') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - snapmirror_initialize.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - data = self.set_default_args() - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='idle', parm='snapmirrored') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_snapmirror.NetAppONTAPSnapmirror.snapmirror_update') - def test_successful_update(self, snapmirror_update): - ''' update snapmirror and testing idempotency ''' - data = self.set_default_args() - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='idle', parm='snapmirrored') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - snapmirror_update.assert_called_with() - - def test_elementsw_volume_exists(self): - ''' elementsw_volume_exists ''' - data = self.set_default_args() - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - mock_helper = Mock() - mock_helper.volume_id_exists.side_effect = [1000, None] - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='idle', parm='snapmirrored') - res = my_obj.check_if_elementsw_volume_exists('10.10.10.10:/lun/1000', mock_helper) - assert res is None - with pytest.raises(AnsibleFailJson) as exc: - my_obj.check_if_elementsw_volume_exists('10.10.10.10:/lun/1000', mock_helper) - assert 'Error: Source volume does not exist in the ElementSW cluster' in exc.value.args[0]['msg'] - - def test_elementsw_svip_exists(self): - ''' svip_exists ''' - data = self.set_default_args() - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - mock_helper = Mock() - mock_helper.get_cluster_info.return_value.cluster_info.svip = '10.10.10.10' - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='idle', parm='snapmirrored') - res = my_obj.validate_elementsw_svip('10.10.10.10:/lun/1000', mock_helper) - assert res is None - - def test_elementsw_svip_exists_negative(self): - ''' svip_exists negative testing''' - data = self.set_default_args() - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - mock_helper = Mock() - mock_helper.get_cluster_info.return_value.cluster_info.svip = '10.10.10.10' - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='idle', parm='snapmirrored') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.validate_elementsw_svip('10.10.10.11:/lun/1000', mock_helper) - assert 'Error: Invalid SVIP' in exc.value.args[0]['msg'] - - @patch('ansible.modules.storage.netapp.na_ontap_snapmirror.NetAppONTAPSnapmirror.set_element_connection') - @patch('ansible.modules.storage.netapp.na_ontap_snapmirror.NetAppONTAPSnapmirror.validate_elementsw_svip') - @patch('ansible.modules.storage.netapp.na_ontap_snapmirror.NetAppONTAPSnapmirror.check_if_elementsw_volume_exists') - def test_check_elementsw_params_source(self, validate_volume, validate_svip, connection): - ''' check elementsw parameters for source ''' - data = self.set_default_args() - data['source_path'] = '10.10.10.10:/lun/1000' - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - mock_elem, mock_helper = Mock(), Mock() - connection.return_value = mock_helper, mock_elem - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='idle', parm='snapmirrored') - my_obj.check_elementsw_parameters('source') - connection.called_once_with('source') - validate_svip.called_once_with(data['source_path'], mock_elem) - validate_volume.called_once_with(data['source_path'], mock_helper) - - def test_check_elementsw_params_negative(self): - ''' check elementsw parameters for source negative testing ''' - data = self.set_default_args() - del data['source_path'] - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='idle', parm='snapmirrored') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.check_elementsw_parameters('source') - assert 'Error: Missing required parameter source_path' in exc.value.args[0]['msg'] - - def test_check_elementsw_params_invalid(self): - ''' check elementsw parameters for source invalid testing ''' - data = self.set_default_args() - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='idle', parm='snapmirrored') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.check_elementsw_parameters('source') - assert 'Error: invalid source_path' in exc.value.args[0]['msg'] - - def test_elementsw_source_path_format(self): - ''' test element_source_path_format_matches ''' - data = self.set_default_args() - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='idle', parm='snapmirrored') - match = my_obj.element_source_path_format_matches('1.1.1.1:dummy') - assert match is None - match = my_obj.element_source_path_format_matches('10.10.10.10:/lun/10') - assert match is not None - - @patch('ansible.module_utils.netapp.create_sf_connection') - def test_set_elem_connection(self, create_sf_connection): - ''' test set_elem_connection ''' - data = self.set_default_args() - data['source_hostname'] = 'test_source' - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - create_sf_connection.return_value = Mock() - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='idle', parm='snapmirrored') - my_obj.set_element_connection('source') - assert my_obj.module.params['hostname'] == data['source_hostname'] - assert my_obj.module.params['username'] == data['source_username'] - assert my_obj.module.params['password'] == data['source_password'] - - def test_remote_volume_exists(self): - ''' test check_if_remote_volume_exists ''' - data = self.set_default_args() - data['source_volume'] = 'test_vol' - data['destination_volume'] = 'test_vol2' - set_module_args(data) - my_obj = my_module() - my_obj.set_source_cluster_connection = Mock(return_value=None) - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='idle', parm='snapmirrored') - my_obj.source_server = MockONTAPConnection('snapmirror', status='idle', parm='snapmirrored') - res = my_obj.check_if_remote_volume_exists() - assert res - - @patch('ansible.module_utils.netapp.create_sf_connection') - def test_set_elem_connection_destination(self, create_sf_connection): - ''' test set_elem_connection for destination''' - data = self.set_default_args() - data['source_hostname'] = 'test_source' - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - create_sf_connection.return_value = Mock() - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror', status='idle', parm='snapmirrored') - my_obj.set_element_connection('destination') - assert my_obj.module.params['hostname'] == data['hostname'] - assert my_obj.module.params['username'] == data['username'] - assert my_obj.module.params['password'] == data['password'] - - def test_if_all_methods_catch_exception(self): - data = self.set_default_args() - data['source_hostname'] = '10.10.10.10' - data['source_volume'] = 'ansible' - data['destination_volume'] = 'ansible2' - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('snapmirror_fail') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.snapmirror_get() - assert 'Error fetching snapmirror info: ' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.snapmirror_abort() - assert 'Error aborting SnapMirror relationship :' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.snapmirror_break() - assert 'Error breaking SnapMirror relationship :' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.snapmirror_get = Mock(return_value={'mirror_state': 'transferring'}) - my_obj.snapmirror_initialize() - assert 'Error initializing SnapMirror :' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.snapmirror_update() - assert 'Error updating SnapMirror :' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.set_source_cluster_connection = Mock(return_value=True) - my_obj.source_server = MockONTAPConnection('snapmirror_fail') - my_obj.check_if_remote_volume_exists() - assert 'Error fetching source volume details' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.check_if_remote_volume_exists = Mock(return_value=True) - my_obj.source_server = MockONTAPConnection() - my_obj.snapmirror_create() - assert 'Error creating SnapMirror ' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.snapmirror_quiesce() - assert 'Error Quiescing SnapMirror :' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.snapmirror_quiesce = Mock(return_value=None) - my_obj.get_destination = Mock(return_value=None) - my_obj.snapmirror_break = Mock(return_value=None) - my_obj.delete_snapmirror(False, 'data_protection') - assert 'Error deleting SnapMirror :' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.snapmirror_modify({'policy': 'ansible2', 'schedule': 'abc2'}) - assert 'Error modifying SnapMirror schedule or policy :' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_snapshot.py b/test/units/modules/storage/netapp/test_na_ontap_snapshot.py deleted file mode 100644 index d4e140b396..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_snapshot.py +++ /dev/null @@ -1,226 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests ONTAP Ansible module: na_ontap_nvme_snapshot''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_snapshot \ - import NetAppOntapSnapshot as my_module - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None): - ''' save arguments ''' - self.type = kind - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'snapshot': - xml = self.build_snapshot_info() - elif self.type == 'snapshot_fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - @staticmethod - def build_snapshot_info(): - ''' build xml data for snapshot-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 1, - 'attributes-list': {'snapshot-info': {'comment': 'new comment', - 'name': 'ansible', - 'snapmirror-label': 'label12'}}} - xml.translate_struct(data) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.onbox = False - - def set_default_args(self): - if self.onbox: - hostname = '10.193.75.3' - username = 'admin' - password = 'netapp1!' - vserver = 'ansible' - volume = 'ansible' - snapshot = 'ansible' - comment = 'new comment' - snapmirror_label = 'label12' - else: - hostname = 'hostname' - username = 'username' - password = 'password' - vserver = 'vserver' - volume = 'ansible' - snapshot = 'ansible' - comment = 'new comment' - snapmirror_label = 'label12' - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'vserver': vserver, - 'volume': volume, - 'snapshot': snapshot, - 'comment': comment, - 'snapmirror_label': snapmirror_label - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_get_called(self): - ''' test get_snapshot() for non-existent snapshot''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - assert my_obj.get_snapshot() is None - - def test_ensure_get_called_existing(self): - ''' test get_snapshot() for existing snapshot''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='snapshot') - assert my_obj.get_snapshot() - - @patch('ansible.modules.storage.netapp.na_ontap_snapshot.NetAppOntapSnapshot.create_snapshot') - def test_successful_create(self, create_snapshot): - ''' creating snapshot and testing idempotency ''' - set_module_args(self.set_default_args()) - my_obj = my_module() - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - create_snapshot.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('snapshot') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_snapshot.NetAppOntapSnapshot.modify_snapshot') - def test_successful_modify(self, modify_snapshot): - ''' modifying snapshot and testing idempotency ''' - data = self.set_default_args() - data['comment'] = 'adding comment' - data['snapmirror_label'] = 'label22' - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('snapshot') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - modify_snapshot.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - data['comment'] = 'new comment' - data['snapmirror_label'] = 'label12' - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('snapshot') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_snapshot.NetAppOntapSnapshot.delete_snapshot') - def test_successful_delete(self, delete_snapshot): - ''' deleting snapshot and testing idempotency ''' - data = self.set_default_args() - data['state'] = 'absent' - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('snapshot') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - delete_snapshot.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - def test_if_all_methods_catch_exception(self): - module_args = {} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('snapshot_fail') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.create_snapshot() - assert 'Error creating snapshot ansible:' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.delete_snapshot() - assert 'Error deleting snapshot ansible:' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.modify_snapshot() - assert 'Error modifying snapshot ansible:' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_snapshot_policy.py b/test/units/modules/storage/netapp/test_na_ontap_snapshot_policy.py deleted file mode 100644 index 19b0864b64..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_snapshot_policy.py +++ /dev/null @@ -1,654 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests ONTAP Ansible module: na_ontap_snapshot_policy''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_snapshot_policy \ - import NetAppOntapSnapshotPolicy as my_module - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None): - ''' save arguments ''' - self.type = kind - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'policy': - xml = self.build_snapshot_policy_info() - elif self.type == 'snapshot_policy_info_policy_disabled': - xml = self.build_snapshot_policy_info_policy_disabled() - elif self.type == 'snapshot_policy_info_comment_modified': - xml = self.build_snapshot_policy_info_comment_modified() - elif self.type == 'snapshot_policy_info_schedules_added': - xml = self.build_snapshot_policy_info_schedules_added() - elif self.type == 'snapshot_policy_info_schedules_deleted': - xml = self.build_snapshot_policy_info_schedules_deleted() - elif self.type == 'snapshot_policy_info_modified_schedule_counts': - xml = self.build_snapshot_policy_info_modified_schedule_counts() - elif self.type == 'policy_fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - def asup_log_for_cserver(self): - ''' mock autosupport log''' - return None - - @staticmethod - def build_snapshot_policy_info(): - ''' build xml data for snapshot-policy-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 1, - 'attributes-list': { - 'snapshot-policy-info': { - 'comment': 'new comment', - 'enabled': 'true', - 'policy': 'ansible', - 'snapshot-policy-schedules': { - 'snapshot-schedule-info': { - 'count': 100, - 'schedule': 'hourly', - 'snapmirror-label': '' - } - }, - 'vserver-name': 'hostname' - } - }} - xml.translate_struct(data) - return xml - - @staticmethod - def build_snapshot_policy_info_comment_modified(): - ''' build xml data for snapshot-policy-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 1, - 'attributes-list': { - 'snapshot-policy-info': { - 'comment': 'modified comment', - 'enabled': 'true', - 'policy': 'ansible', - 'snapshot-policy-schedules': { - 'snapshot-schedule-info': { - 'count': 100, - 'schedule': 'hourly', - 'snapmirror-label': '' - } - }, - 'vserver-name': 'hostname' - } - }} - xml.translate_struct(data) - return xml - - @staticmethod - def build_snapshot_policy_info_policy_disabled(): - ''' build xml data for snapshot-policy-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 1, - 'attributes-list': { - 'snapshot-policy-info': { - 'comment': 'new comment', - 'enabled': 'false', - 'policy': 'ansible', - 'snapshot-policy-schedules': { - 'snapshot-schedule-info': { - 'count': 100, - 'schedule': 'hourly', - 'snapmirror-label': '' - } - }, - 'vserver-name': 'hostname' - } - }} - xml.translate_struct(data) - return xml - - @staticmethod - def build_snapshot_policy_info_schedules_added(): - ''' build xml data for snapshot-policy-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 1, - 'attributes-list': { - 'snapshot-policy-info': { - 'comment': 'new comment', - 'enabled': 'true', - 'policy': 'ansible', - 'snapshot-policy-schedules': [ - { - 'snapshot-schedule-info': { - 'count': 100, - 'schedule': 'hourly', - 'snapmirror-label': '' - } - }, - { - 'snapshot-schedule-info': { - 'count': 5, - 'schedule': 'daily', - 'snapmirror-label': 'daily' - } - }, - { - 'snapshot-schedule-info': { - 'count': 10, - 'schedule': 'weekly', - 'snapmirror-label': '' - } - } - ], - 'vserver-name': 'hostname' - } - }} - xml.translate_struct(data) - return xml - - @staticmethod - def build_snapshot_policy_info_schedules_deleted(): - ''' build xml data for snapshot-policy-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 1, - 'attributes-list': { - 'snapshot-policy-info': { - 'comment': 'new comment', - 'enabled': 'true', - 'policy': 'ansible', - 'snapshot-policy-schedules': [ - { - 'snapshot-schedule-info': { - 'schedule': 'daily', - 'count': 5, - 'snapmirror-label': 'daily' - } - } - ], - 'vserver-name': 'hostname' - } - }} - xml.translate_struct(data) - return xml - - @staticmethod - def build_snapshot_policy_info_modified_schedule_counts(): - ''' build xml data for snapshot-policy-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 1, - 'attributes-list': { - 'snapshot-policy-info': { - 'comment': 'new comment', - 'enabled': 'true', - 'policy': 'ansible', - 'snapshot-policy-schedules': [ - { - 'snapshot-schedule-info': { - 'count': 10, - 'schedule': 'hourly', - 'snapmirror-label': '' - } - }, - { - 'snapshot-schedule-info': { - 'count': 50, - 'schedule': 'daily', - 'snapmirror-label': 'daily' - } - }, - { - 'snapshot-schedule-info': { - 'count': 100, - 'schedule': 'weekly', - 'snapmirror-label': '' - } - } - ], - 'vserver-name': 'hostname' - } - }} - xml.translate_struct(data) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.onbox = False - - def set_default_args(self): - if self.onbox: - hostname = '10.10.10.10' - username = 'admin' - password = '1234' - name = 'ansible' - enabled = True - count = 100 - schedule = 'hourly' - comment = 'new comment' - else: - hostname = 'hostname' - username = 'username' - password = 'password' - name = 'ansible' - enabled = True - count = 100 - schedule = 'hourly' - comment = 'new comment' - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'name': name, - 'enabled': enabled, - 'count': count, - 'schedule': schedule, - 'comment': comment - }) - - def set_default_current(self): - default_args = self.set_default_args() - return dict({ - 'name': default_args['name'], - 'enabled': default_args['enabled'], - 'count': [default_args['count']], - 'schedule': [default_args['schedule']], - 'snapmirror_label': [''], - 'comment': default_args['comment'], - 'vserver': default_args['hostname'] - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_get_called(self): - ''' test get_snapshot_policy() for non-existent snapshot policy''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - assert my_obj.get_snapshot_policy() is None - - def test_ensure_get_called_existing(self): - ''' test get_snapshot_policy() for existing snapshot policy''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='policy') - assert my_obj.get_snapshot_policy() - - @patch('ansible.modules.storage.netapp.na_ontap_snapshot_policy.NetAppOntapSnapshotPolicy.create_snapshot_policy') - def test_successful_create(self, create_snapshot): - ''' creating snapshot policy and testing idempotency ''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - create_snapshot.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('policy') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_snapshot_policy.NetAppOntapSnapshotPolicy.modify_snapshot_policy') - def test_successful_modify_comment(self, modify_snapshot): - ''' modifying snapshot policy comment and testing idempotency ''' - data = self.set_default_args() - data['comment'] = 'modified comment' - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('policy') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - current = self.set_default_current() - modify_snapshot.assert_called_with(current) - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapshot_policy_info_comment_modified') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_snapshot_policy.NetAppOntapSnapshotPolicy.modify_snapshot_policy') - def test_successful_disable_policy(self, modify_snapshot): - ''' disabling snapshot policy and testing idempotency ''' - data = self.set_default_args() - data['enabled'] = False - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('policy') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - current = self.set_default_current() - modify_snapshot.assert_called_with(current) - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapshot_policy_info_policy_disabled') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_snapshot_policy.NetAppOntapSnapshotPolicy.modify_snapshot_policy') - def test_successful_enable_policy(self, modify_snapshot): - ''' enabling snapshot policy and testing idempotency ''' - data = self.set_default_args() - data['enabled'] = True - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapshot_policy_info_policy_disabled') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - current = self.set_default_current() - current['enabled'] = False - modify_snapshot.assert_called_with(current) - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('policy') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_snapshot_policy.NetAppOntapSnapshotPolicy.modify_snapshot_policy') - def test_successful_modify_schedules_add(self, modify_snapshot): - ''' adding snapshot policy schedules and testing idempotency ''' - data = self.set_default_args() - data['schedule'] = ['hourly', 'daily', 'weekly'] - data['count'] = [100, 5, 10] - data['snapmirror_label'] = ['', 'daily', ''] - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('policy') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - current = self.set_default_current() - modify_snapshot.assert_called_with(current) - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapshot_policy_info_schedules_added') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_snapshot_policy.NetAppOntapSnapshotPolicy.modify_snapshot_policy') - def test_successful_modify_schedules_delete(self, modify_snapshot): - ''' deleting snapshot policy schedules and testing idempotency ''' - data = self.set_default_args() - data['schedule'] = ['daily'] - data['count'] = [5] - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('policy') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - current = self.set_default_current() - modify_snapshot.assert_called_with(current) - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapshot_policy_info_schedules_deleted') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_snapshot_policy.NetAppOntapSnapshotPolicy.modify_snapshot_policy') - def test_successful_modify_schedules(self, modify_snapshot): - ''' modifying snapshot policy schedule counts and testing idempotency ''' - data = self.set_default_args() - data['schedule'] = ['hourly', 'daily', 'weekly'] - data['count'] = [10, 50, 100] - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('policy') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - current = self.set_default_current() - modify_snapshot.assert_called_with(current) - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('snapshot_policy_info_modified_schedule_counts') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_snapshot_policy.NetAppOntapSnapshotPolicy.delete_snapshot_policy') - def test_successful_delete(self, delete_snapshot): - ''' deleting snapshot policy and testing idempotency ''' - data = self.set_default_args() - data['state'] = 'absent' - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = MockONTAPConnection('policy') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - delete_snapshot.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - def test_valid_schedule_count(self): - ''' validate when schedule has same number of elements ''' - data = self.set_default_args() - data['schedule'] = ['hourly', 'daily', 'weekly', 'monthly', '5min'] - data['count'] = [1, 2, 3, 4, 5] - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = self.server - my_obj.create_snapshot_policy() - create_xml = my_obj.server.xml_in - assert data['count'][2] == int(create_xml['count3']) - assert data['schedule'][4] == create_xml['schedule5'] - - def test_valid_schedule_count_with_snapmirror_labels(self): - ''' validate when schedule has same number of elements with snapmirror labels ''' - data = self.set_default_args() - data['schedule'] = ['hourly', 'daily', 'weekly', 'monthly', '5min'] - data['count'] = [1, 2, 3, 4, 5] - data['snapmirror_label'] = ['hourly', 'daily', 'weekly', 'monthly', '5min'] - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = self.server - my_obj.create_snapshot_policy() - create_xml = my_obj.server.xml_in - assert data['count'][2] == int(create_xml['count3']) - assert data['schedule'][4] == create_xml['schedule5'] - assert data['snapmirror_label'][3] == create_xml['snapmirror-label4'] - - def test_invalid_params(self): - ''' validate error when schedule does not have same number of elements ''' - data = self.set_default_args() - data['schedule'] = ['s1', 's2'] - data['count'] = [1, 2, 3] - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleFailJson) as exc: - my_obj.create_snapshot_policy() - msg = 'Error: A Snapshot policy must have at least 1 ' \ - 'schedule and can have up to a maximum of 5 schedules, with a count ' \ - 'representing the maximum number of Snapshot copies for each schedule' - assert exc.value.args[0]['msg'] == msg - - def test_invalid_schedule_count(self): - ''' validate error when schedule has more than 5 elements ''' - data = self.set_default_args() - data['schedule'] = ['s1', 's2', 's3', 's4', 's5', 's6'] - data['count'] = [1, 2, 3, 4, 5, 6] - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleFailJson) as exc: - my_obj.create_snapshot_policy() - msg = 'Error: A Snapshot policy must have at least 1 ' \ - 'schedule and can have up to a maximum of 5 schedules, with a count ' \ - 'representing the maximum number of Snapshot copies for each schedule' - assert exc.value.args[0]['msg'] == msg - - def test_invalid_schedule_count_less_than_one(self): - ''' validate error when schedule has less than 1 element ''' - data = self.set_default_args() - data['schedule'] = [] - data['count'] = [] - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleFailJson) as exc: - my_obj.create_snapshot_policy() - msg = 'Error: A Snapshot policy must have at least 1 ' \ - 'schedule and can have up to a maximum of 5 schedules, with a count ' \ - 'representing the maximum number of Snapshot copies for each schedule' - assert exc.value.args[0]['msg'] == msg - - def test_invalid_schedule_count_is_none(self): - ''' validate error when schedule is None ''' - data = self.set_default_args() - data['schedule'] = None - data['count'] = None - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleFailJson) as exc: - my_obj.create_snapshot_policy() - msg = 'Error: A Snapshot policy must have at least 1 ' \ - 'schedule and can have up to a maximum of 5 schedules, with a count ' \ - 'representing the maximum number of Snapshot copies for each schedule' - assert exc.value.args[0]['msg'] == msg - - def test_invalid_schedule_count_with_snapmirror_labels(self): - ''' validate error when schedule with snapmirror labels does not have same number of elements ''' - data = self.set_default_args() - data['schedule'] = ['s1', 's2', 's3'] - data['count'] = [1, 2, 3] - data['snapmirror_label'] = ['sm1', 'sm2'] - set_module_args(data) - my_obj = my_module() - my_obj.asup_log_for_cserver = Mock(return_value=None) - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleFailJson) as exc: - my_obj.create_snapshot_policy() - msg = 'Error: Each Snapshot Policy schedule must have an accompanying SnapMirror Label' - assert exc.value.args[0]['msg'] == msg - - def test_if_all_methods_catch_exception(self): - module_args = {} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('policy_fail') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.create_snapshot_policy() - assert 'Error creating snapshot policy ansible:' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.delete_snapshot_policy() - assert 'Error deleting snapshot policy ansible:' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_software_update.py b/test/units/modules/storage/netapp/test_na_ontap_software_update.py deleted file mode 100644 index cb9f39eb28..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_software_update.py +++ /dev/null @@ -1,163 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests ONTAP Ansible module: na_ontap_software_update ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_software_update \ - import NetAppONTAPSoftwareUpdate as my_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, parm1=None, parm2=None): - ''' save arguments ''' - self.type = kind - self.parm1 = parm1 - self.parm2 = parm2 - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'software_update': - xml = self.build_software_update_info(self.parm1, self.parm2) - self.xml_out = xml - return xml - - def autosupport_log(self): - ''' mock autosupport log''' - return None - - @staticmethod - def build_software_update_info(status, node): - ''' build xml data for software-update-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = { - 'num-records': 1, - 'attributes-list': {'cluster-image-info': {'node-id': node}}, - 'progress-status': status, - 'attributes': {'ndu-progress-info': {'overall-status': 'completed', - 'completed-node-count': '0'}}, - } - xml.translate_struct(data) - print(xml.to_string()) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.use_vsim = False - - def set_default_args(self): - if self.use_vsim: - hostname = '10.10.10.10' - username = 'admin' - password = 'admin' - node = 'vsim1' - package_version = 'Fattire__9.3.0' - package_url = 'abc.com' - else: - hostname = 'hostname' - username = 'username' - password = 'password' - node = 'abc' - package_version = 'test' - package_url = 'abc.com' - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'nodes': node, - 'package_version': package_version, - 'package_url': package_url, - 'https': 'true' - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_image_get_called(self): - ''' a more interesting test ''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - cluster_image_get = my_obj.cluster_image_get() - print('Info: test_software_update_get: %s' % repr(cluster_image_get)) - assert cluster_image_get is None - - def test_ensure_apply_for_update_called(self): - ''' updating software and checking idempotency ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'package_url': 'abc.com'}) - set_module_args(module_args) - my_obj = my_module() - my_obj.autosupport_log = Mock(return_value=None) - if not self.use_vsim: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_software_update_apply: %s' % repr(exc.value)) - assert not exc.value.args[0]['changed'] - if not self.use_vsim: - my_obj.server = MockONTAPConnection('software_update', 'async_pkg_get_phase_complete', 'abc') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_software_update_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_svm.py b/test/units/modules/storage/netapp/test_na_ontap_svm.py deleted file mode 100644 index fe3c918eea..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_svm.py +++ /dev/null @@ -1,267 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_svm \ - import NetAppOntapSVM as svm_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.type = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'vserver': - xml = self.build_vserver_info(self.params) - self.xml_out = xml - return xml - - @staticmethod - def build_vserver_info(vserver): - ''' build xml data for vserser-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 1, 'attributes-list': {'vserver-info': { - 'vserver-name': vserver['name'], - 'ipspace': vserver['ipspace'], - 'root-volume': vserver['root_volume'], - 'root-volume-aggregate': vserver['root_volume_aggregate'], - 'language': vserver['language'], - 'comment': vserver['comment'], - 'snapshot-policy': vserver['snapshot_policy'], - 'vserver-subtype': vserver['subtype'], - 'allowed-protocols': [{'protocol': 'nfs'}, {'protocol': 'cifs'}], - 'aggr-list': [{'aggr-name': 'aggr_1'}, {'aggr-name': 'aggr_2'}], - }}} - xml.translate_struct(data) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.mock_vserver = { - 'name': 'test_svm', - 'root_volume': 'ansible_vol', - 'root_volume_aggregate': 'ansible_aggr', - 'aggr_list': 'aggr_1,aggr_2', - 'ipspace': 'ansible_ipspace', - 'subtype': 'default', - 'language': 'c.utf_8', - 'snapshot_policy': 'old_snapshot_policy', - 'comment': 'this is a comment' - } - - def mock_args(self): - return { - 'name': self.mock_vserver['name'], - 'root_volume': self.mock_vserver['root_volume'], - 'root_volume_aggregate': self.mock_vserver['root_volume_aggregate'], - 'aggr_list': self.mock_vserver['aggr_list'], - 'ipspace': self.mock_vserver['ipspace'], - 'comment': self.mock_vserver['comment'], - 'subtype': 'default', - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - - def get_vserver_mock_object(self, kind=None, data=None): - """ - Helper method to return an na_ontap_volume object - :param kind: passes this param to MockONTAPConnection() - :param data: passes this param to MockONTAPConnection() - :return: na_ontap_volume object - """ - vserver_obj = svm_module() - vserver_obj.asup_log_for_cserver = Mock(return_value=None) - vserver_obj.cluster = Mock() - vserver_obj.cluster.invoke_successfully = Mock() - if kind is None: - vserver_obj.server = MockONTAPConnection() - else: - if data is None: - vserver_obj.server = MockONTAPConnection(kind='vserver', data=self.mock_vserver) - else: - vserver_obj.server = MockONTAPConnection(kind='vserver', data=data) - return vserver_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - svm_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_nonexistent_vserver(self): - ''' test if get_vserver() throws an error if vserver is not specified ''' - data = self.mock_args() - set_module_args(data) - result = self.get_vserver_mock_object().get_vserver() - assert result is None - - def test_create_error_missing_name(self): - ''' Test if create throws an error if name is not specified''' - data = self.mock_args() - del data['name'] - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_vserver_mock_object('vserver').create_vserver() - msg = 'missing required arguments: name' - assert exc.value.args[0]['msg'] == msg - - @patch('ansible.modules.storage.netapp.na_ontap_svm.NetAppOntapSVM.create_vserver') - def test_successful_create(self, create_vserver): - '''Test successful create''' - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_vserver_mock_object().apply() - assert exc.value.args[0]['changed'] - create_vserver.assert_called_with() - - @patch('ansible.modules.storage.netapp.na_ontap_svm.NetAppOntapSVM.create_vserver') - def test_create_idempotency(self, create_vserver): - '''Test successful create''' - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_vserver_mock_object('vserver').apply() - assert not exc.value.args[0]['changed'] - create_vserver.assert_not_called() - - def test_successful_delete(self): - '''Test successful delete''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_vserver_mock_object('vserver').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_svm.NetAppOntapSVM.delete_vserver') - def test_delete_idempotency(self, delete_vserver): - '''Test delete idempotency''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_vserver_mock_object().apply() - assert not exc.value.args[0]['changed'] - delete_vserver.assert_not_called() - - @patch('ansible.modules.storage.netapp.na_ontap_svm.NetAppOntapSVM.get_vserver') - def test_successful_rename(self, get_vserver): - '''Test successful rename''' - data = self.mock_args() - data['from_name'] = 'test_svm' - data['name'] = 'test_new_svm' - set_module_args(data) - current = { - 'name': 'test_svm', - 'root_volume': 'ansible_vol', - 'root_volume_aggregate': 'ansible_aggr', - 'ipspace': 'ansible_ipspace', - 'subtype': 'default', - 'language': 'c.utf_8' - } - get_vserver.side_effect = [ - None, - current - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_vserver_mock_object().apply() - assert exc.value.args[0]['changed'] - - def test_successful_modify_language(self): - '''Test successful modify language''' - data = self.mock_args() - data['language'] = 'c' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_vserver_mock_object('vserver').apply() - assert exc.value.args[0]['changed'] - - def test_successful_modify_snapshot_policy(self): - '''Test successful modify language''' - data = self.mock_args() - data['snapshot_policy'] = 'new_snapshot_policy' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_vserver_mock_object('vserver').apply() - assert exc.value.args[0]['changed'] - - def test_successful_modify_allowed_protocols(self): - '''Test successful modify allowed protocols''' - data = self.mock_args() - data['allowed_protocols'] = 'protocol_1,protocol_2' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_vserver_mock_object('vserver').apply() - assert exc.value.args[0]['changed'] - - def test_successful_modify_aggr_list(self): - '''Test successful modify aggr-list''' - data = self.mock_args() - data['aggr_list'] = 'aggr_3,aggr_4' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_vserver_mock_object('vserver').apply() - assert exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_ucadapter.py b/test/units/modules/storage/netapp/test_na_ontap_ucadapter.py deleted file mode 100644 index 3a0ca710ec..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_ucadapter.py +++ /dev/null @@ -1,159 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests ONTAP Ansible module: na_ontap_ucadapter ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_ucadapter \ - import NetAppOntapadapter as my_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, parm1=None): - ''' save arguments ''' - self.type = kind - self.parm1 = parm1 - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'ucadapter': - xml = self.build_ucadapter_info(self.parm1) - self.xml_out = xml - return xml - - def autosupport_log(self): - ''' mock autosupport log''' - return None - - @staticmethod - def build_ucadapter_info(status): - ''' build xml data for ucadapter_info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'attributes': {'uc-adapter-info': { - 'mode': 'fc', - 'pending-mode': 'abc', - 'type': 'target', - 'pending-type': 'intitiator', - 'status': status, - }}} - xml.translate_struct(data) - print(xml.to_string()) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.use_vsim = False - - def set_default_args(self): - if self.use_vsim: - hostname = '10.192.39.6' - username = 'admin' - password = 'netapp123' - node_name = 'bumblebee-reloaded-01' - adapter_name = '0f' - else: - hostname = 'hostname' - username = 'username' - password = 'password' - node_name = 'abc' - adapter_name = '0f' - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'node_name': node_name, - 'adapter_name': adapter_name, - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_ucadapter_get_called(self): - ''' fetching ucadapter details ''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - get_adapter = my_obj.get_adapter() - print('Info: test_ucadapter_get: %s' % repr(get_adapter)) - assert get_adapter is None - - def test_ensure_apply_for_ucadapter_called(self): - ''' configuring ucadaptor and checking idempotency ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'type': 'target'}) - module_args.update({'mode': 'initiator'}) - set_module_args(module_args) - my_obj = my_module() - my_obj.autosupport_log = Mock(return_value=None) - if not self.use_vsim: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_ucadapter_apply: %s' % repr(exc.value)) - assert not exc.value.args[0]['changed'] - if not self.use_vsim: - my_obj.server = MockONTAPConnection('ucadapter', 'up') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_ucadapter_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_unix_group.py b/test/units/modules/storage/netapp/test_na_ontap_unix_group.py deleted file mode 100644 index e34df9baa4..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_unix_group.py +++ /dev/null @@ -1,288 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_unix_group \ - import NetAppOntapUnixGroup as group_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'group': - xml = self.build_group_info(self.params) - elif self.kind == 'group-fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - @staticmethod - def build_group_info(data): - ''' build xml data for vserser-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = \ - {'attributes-list': {'unix-group-info': {'group-name': data['name'], - 'group-id': data['id']}}, - 'num-records': 1} - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.mock_group = { - 'name': 'test', - 'id': '11', - 'vserver': 'something', - } - - def mock_args(self): - return { - 'name': self.mock_group['name'], - 'id': self.mock_group['id'], - 'vserver': self.mock_group['vserver'], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - - def get_group_mock_object(self, kind=None, data=None): - """ - Helper method to return an na_ontap_unix_group object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_unix_group object - """ - obj = group_module() - obj.autosupport_log = Mock(return_value=None) - if data is None: - data = self.mock_group - obj.server = MockONTAPConnection(kind=kind, data=data) - return obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - group_module() - - def test_get_nonexistent_group(self): - ''' Test if get_unix_group returns None for non-existent group ''' - set_module_args(self.mock_args()) - result = self.get_group_mock_object().get_unix_group() - assert result is None - - def test_get_existing_group(self): - ''' Test if get_unix_group returns details for existing group ''' - set_module_args(self.mock_args()) - result = self.get_group_mock_object('group').get_unix_group() - assert result['name'] == self.mock_group['name'] - - def test_get_xml(self): - set_module_args(self.mock_args()) - obj = self.get_group_mock_object('group') - result = obj.get_unix_group() - assert obj.server.xml_in['query'] - assert obj.server.xml_in['query']['unix-group-info'] - group_info = obj.server.xml_in['query']['unix-group-info'] - assert group_info['group-name'] == self.mock_group['name'] - assert group_info['vserver'] == self.mock_group['vserver'] - - def test_create_error_missing_params(self): - data = self.mock_args() - del data['id'] - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_group_mock_object('group').create_unix_group() - assert 'Error: Missing a required parameter for create: (id)' == exc.value.args[0]['msg'] - - @patch('ansible.modules.storage.netapp.na_ontap_unix_group.NetAppOntapUnixGroup.create_unix_group') - def test_create_called(self, create_group): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_group_mock_object().apply() - assert exc.value.args[0]['changed'] - create_group.assert_called_with() - - def test_create_xml(self): - '''Test create ZAPI element''' - set_module_args(self.mock_args()) - create = self.get_group_mock_object() - with pytest.raises(AnsibleExitJson) as exc: - create.apply() - mock_key = { - 'group-name': 'name', - 'group-id': 'id', - } - for key in ['group-name', 'group-id']: - assert create.server.xml_in[key] == self.mock_group[mock_key[key]] - - @patch('ansible.modules.storage.netapp.na_ontap_unix_group.NetAppOntapUnixGroup.modify_unix_group') - @patch('ansible.modules.storage.netapp.na_ontap_unix_group.NetAppOntapUnixGroup.delete_unix_group') - def test_delete_called(self, delete_group, modify_group): - ''' Test delete existing group ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_group_mock_object('group').apply() - assert exc.value.args[0]['changed'] - delete_group.assert_called_with() - assert modify_group.call_count == 0 - - @patch('ansible.modules.storage.netapp.na_ontap_unix_group.NetAppOntapUnixGroup.get_unix_group') - @patch('ansible.modules.storage.netapp.na_ontap_unix_group.NetAppOntapUnixGroup.modify_unix_group') - def test_modify_called(self, modify_group, get_group): - ''' Test modify group group_id ''' - data = self.mock_args() - data['id'] = 20 - set_module_args(data) - get_group.return_value = {'id': 10} - obj = self.get_group_mock_object('group') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - get_group.assert_called_with() - modify_group.assert_called_with({'id': 20}) - - def test_modify_only_id(self): - ''' Test modify group id ''' - set_module_args(self.mock_args()) - modify = self.get_group_mock_object('group') - modify.modify_unix_group({'id': 123}) - print(modify.server.xml_in.to_string()) - assert modify.server.xml_in['group-id'] == '123' - with pytest.raises(KeyError): - modify.server.xml_in['id'] - - def test_modify_xml(self): - ''' Test modify group full_name ''' - set_module_args(self.mock_args()) - modify = self.get_group_mock_object('group') - modify.modify_unix_group({'id': 25}) - assert modify.server.xml_in['group-name'] == self.mock_group['name'] - assert modify.server.xml_in['group-id'] == '25' - - @patch('ansible.modules.storage.netapp.na_ontap_unix_group.NetAppOntapUnixGroup.create_unix_group') - @patch('ansible.modules.storage.netapp.na_ontap_unix_group.NetAppOntapUnixGroup.delete_unix_group') - @patch('ansible.modules.storage.netapp.na_ontap_unix_group.NetAppOntapUnixGroup.modify_unix_group') - def test_do_nothing(self, modify, delete, create): - ''' changed is False and none of the opetaion methods are called''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - obj = self.get_group_mock_object() - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - create.assert_not_called() - delete.assert_not_called() - modify.assert_not_called() - - def test_get_exception(self): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleFailJson) as exc: - self.get_group_mock_object('group-fail').get_unix_group() - assert 'Error getting UNIX group' in exc.value.args[0]['msg'] - - def test_create_exception(self): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleFailJson) as exc: - self.get_group_mock_object('group-fail').create_unix_group() - assert 'Error creating UNIX group' in exc.value.args[0]['msg'] - - def test_modify_exception(self): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleFailJson) as exc: - self.get_group_mock_object('group-fail').modify_unix_group({'id': '123'}) - assert 'Error modifying UNIX group' in exc.value.args[0]['msg'] - - def test_delete_exception(self): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleFailJson) as exc: - self.get_group_mock_object('group-fail').delete_unix_group() - assert 'Error removing UNIX group' in exc.value.args[0]['msg'] - - @patch('ansible.modules.storage.netapp.na_ontap_unix_group.NetAppOntapUnixGroup.get_unix_group') - def test_add_user_exception(self, get_unix_group): - data = self.mock_args() - data['users'] = 'test_user' - set_module_args(data) - get_unix_group.side_effect = [ - {'users': []} - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_group_mock_object('group-fail').modify_users_in_group() - print(exc.value.args[0]['msg']) - assert 'Error adding user' in exc.value.args[0]['msg'] - - @patch('ansible.modules.storage.netapp.na_ontap_unix_group.NetAppOntapUnixGroup.get_unix_group') - def test_delete_user_exception(self, get_unix_group): - data = self.mock_args() - data['users'] = '' - set_module_args(data) - get_unix_group.side_effect = [ - {'users': ['test_user']} - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_group_mock_object('group-fail').modify_users_in_group() - print(exc.value.args[0]['msg']) - assert 'Error deleting user' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_unix_user.py b/test/units/modules/storage/netapp/test_na_ontap_unix_user.py deleted file mode 100644 index 2051db2daf..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_unix_user.py +++ /dev/null @@ -1,282 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_unix_user \ - import NetAppOntapUnixUser as user_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'user': - xml = self.build_user_info(self.params) - elif self.kind == 'user-fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - @staticmethod - def build_user_info(data): - ''' build xml data for vserser-info ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = \ - {'attributes-list': {'unix-user-info': {'user-id': data['id'], - 'group-id': data['group_id'], 'full-name': data['full_name']}}, - 'num-records': 1} - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.mock_user = { - 'name': 'test', - 'id': '11', - 'group_id': '12', - 'vserver': 'something', - 'full_name': 'Test User' - } - - def mock_args(self): - return { - 'name': self.mock_user['name'], - 'group_id': self.mock_user['group_id'], - 'id': self.mock_user['id'], - 'vserver': self.mock_user['vserver'], - 'full_name': self.mock_user['full_name'], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - - def get_user_mock_object(self, kind=None, data=None): - """ - Helper method to return an na_ontap_unix_user object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_unix_user object - """ - obj = user_module() - obj.autosupport_log = Mock(return_value=None) - if data is None: - data = self.mock_user - obj.server = MockONTAPConnection(kind=kind, data=data) - return obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - user_module() - - def test_get_nonexistent_user(self): - ''' Test if get_unix_user returns None for non-existent user ''' - set_module_args(self.mock_args()) - result = self.get_user_mock_object().get_unix_user() - assert result is None - - def test_get_existing_user(self): - ''' Test if get_unix_user returns details for existing user ''' - set_module_args(self.mock_args()) - result = self.get_user_mock_object('user').get_unix_user() - assert result['full_name'] == self.mock_user['full_name'] - - def test_get_xml(self): - set_module_args(self.mock_args()) - obj = self.get_user_mock_object('user') - result = obj.get_unix_user() - assert obj.server.xml_in['query'] - assert obj.server.xml_in['query']['unix-user-info'] - user_info = obj.server.xml_in['query']['unix-user-info'] - assert user_info['user-name'] == self.mock_user['name'] - assert user_info['vserver'] == self.mock_user['vserver'] - - def test_create_error_missing_params(self): - data = self.mock_args() - del data['group_id'] - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_user_mock_object('user').create_unix_user() - assert 'Error: Missing one or more required parameters for create: (group_id, id)' == exc.value.args[0]['msg'] - - @patch('ansible.modules.storage.netapp.na_ontap_unix_user.NetAppOntapUnixUser.create_unix_user') - def test_create_called(self, create_user): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_user_mock_object().apply() - assert exc.value.args[0]['changed'] - create_user.assert_called_with() - - def test_create_xml(self): - '''Test create ZAPI element''' - set_module_args(self.mock_args()) - create = self.get_user_mock_object() - with pytest.raises(AnsibleExitJson) as exc: - create.apply() - mock_key = { - 'user-name': 'name', - 'group-id': 'group_id', - 'user-id': 'id', - 'full-name': 'full_name' - } - for key in ['user-name', 'user-id', 'group-id', 'full-name']: - assert create.server.xml_in[key] == self.mock_user[mock_key[key]] - - def test_create_wihtout_full_name(self): - '''Test create ZAPI element''' - data = self.mock_args() - del data['full_name'] - set_module_args(data) - create = self.get_user_mock_object() - with pytest.raises(AnsibleExitJson) as exc: - create.apply() - with pytest.raises(KeyError): - create.server.xml_in['full-name'] - - @patch('ansible.modules.storage.netapp.na_ontap_unix_user.NetAppOntapUnixUser.modify_unix_user') - @patch('ansible.modules.storage.netapp.na_ontap_unix_user.NetAppOntapUnixUser.delete_unix_user') - def test_delete_called(self, delete_user, modify_user): - ''' Test delete existing user ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_user_mock_object('user').apply() - assert exc.value.args[0]['changed'] - delete_user.assert_called_with() - assert modify_user.call_count == 0 - - @patch('ansible.modules.storage.netapp.na_ontap_unix_user.NetAppOntapUnixUser.get_unix_user') - @patch('ansible.modules.storage.netapp.na_ontap_unix_user.NetAppOntapUnixUser.modify_unix_user') - def test_modify_called(self, modify_user, get_user): - ''' Test modify user group_id ''' - data = self.mock_args() - data['group_id'] = 20 - set_module_args(data) - get_user.return_value = {'group_id': 10} - obj = self.get_user_mock_object('user') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - get_user.assert_called_with() - modify_user.assert_called_with({'group_id': 20}) - - def test_modify_only_id(self): - ''' Test modify user id ''' - set_module_args(self.mock_args()) - modify = self.get_user_mock_object('user') - modify.modify_unix_user({'id': 123}) - assert modify.server.xml_in['user-id'] == '123' - with pytest.raises(KeyError): - modify.server.xml_in['group-id'] - with pytest.raises(KeyError): - modify.server.xml_in['full-name'] - - def test_modify_xml(self): - ''' Test modify user full_name ''' - set_module_args(self.mock_args()) - modify = self.get_user_mock_object('user') - modify.modify_unix_user({'full_name': 'New Name', - 'group_id': '25'}) - assert modify.server.xml_in['user-name'] == self.mock_user['name'] - assert modify.server.xml_in['full-name'] == 'New Name' - assert modify.server.xml_in['group-id'] == '25' - - @patch('ansible.modules.storage.netapp.na_ontap_unix_user.NetAppOntapUnixUser.create_unix_user') - @patch('ansible.modules.storage.netapp.na_ontap_unix_user.NetAppOntapUnixUser.delete_unix_user') - @patch('ansible.modules.storage.netapp.na_ontap_unix_user.NetAppOntapUnixUser.modify_unix_user') - def test_do_nothing(self, modify, delete, create): - ''' changed is False and none of the opetaion methods are called''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - obj = self.get_user_mock_object() - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - create.assert_not_called() - delete.assert_not_called() - modify.assert_not_called() - - def test_get_exception(self): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleFailJson) as exc: - self.get_user_mock_object('user-fail').get_unix_user() - assert 'Error getting UNIX user' in exc.value.args[0]['msg'] - - def test_create_exception(self): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleFailJson) as exc: - self.get_user_mock_object('user-fail').create_unix_user() - assert 'Error creating UNIX user' in exc.value.args[0]['msg'] - - def test_modify_exception(self): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleFailJson) as exc: - self.get_user_mock_object('user-fail').modify_unix_user({'id': '123'}) - assert 'Error modifying UNIX user' in exc.value.args[0]['msg'] - - def test_delete_exception(self): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleFailJson) as exc: - self.get_user_mock_object('user-fail').delete_unix_user() - assert 'Error removing UNIX user' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_user.py b/test/units/modules/storage/netapp/test_na_ontap_user.py deleted file mode 100644 index f4b0475dd8..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_user.py +++ /dev/null @@ -1,320 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests ONTAP Ansible module: na_ontap_user ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_user \ - import NetAppOntapUser as my_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, parm1=None, parm2=None): - ''' save arguments ''' - self.type = kind - self.parm1 = parm1 - self.parm2 = parm2 - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'user': - xml = self.build_user_info(self.parm1, self.parm2) - elif self.type == 'user_fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - @staticmethod - def set_vserver(vserver): - '''mock set vserver''' - pass - - @staticmethod - def build_user_info(locked, role_name): - ''' build xml data for user-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'num-records': 1, - 'attributes-list': {'security-login-account-info': {'is-locked': locked, 'role-name': role_name}}} - - xml.translate_struct(data) - print(xml.to_string()) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.onbox = False - - def set_default_args(self): - if self.onbox: - hostname = '10.10.10.10' - username = 'username' - password = 'password' - user_name = 'test' - vserver = 'ansible_test' - application = 'console' - authentication_method = 'password' - else: - hostname = 'hostname' - username = 'username' - password = 'password' - user_name = 'name' - vserver = 'vserver' - application = 'console' - authentication_method = 'password' - - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'name': user_name, - 'vserver': vserver, - 'applications': application, - 'authentication_method': authentication_method - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_user_get_called(self): - ''' a more interesting test ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'role_name': 'test'}) - set_module_args(module_args) - my_obj = my_module() - my_obj.server = self.server - user_info = my_obj.get_user() - print('Info: test_user_get: %s' % repr(user_info)) - assert user_info is None - - def test_ensure_user_apply_called(self): - ''' creating user and checking idempotency ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'name': 'create'}) - module_args.update({'role_name': 'test'}) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_user_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - if not self.onbox: - my_obj.server = MockONTAPConnection('user', 'false') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_user_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - - def test_ensure_user_apply_for_delete_called(self): - ''' deleting user and checking idempotency ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'name': 'create'}) - module_args.update({'role_name': 'test'}) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('user', 'false', 'test') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_user_apply: %s' % repr(exc.value)) - assert not exc.value.args[0]['changed'] - module_args.update({'state': 'absent'}) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('user', 'false', 'test') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_user_delete: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - - def test_ensure_user_lock_called(self): - ''' changing user_lock to True and checking idempotency''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'name': 'create'}) - module_args.update({'role_name': 'test'}) - module_args.update({'lock_user': 'false'}) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('user', 'false', 'test') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_user_apply: %s' % repr(exc.value)) - assert not exc.value.args[0]['changed'] - module_args.update({'lock_user': 'true'}) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('user', 'false') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_user_lock: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - - def test_ensure_user_unlock_called(self): - ''' changing user_lock to False and checking idempotency''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'name': 'create'}) - module_args.update({'role_name': 'test'}) - module_args.update({'lock_user': 'false'}) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('user', 'false', 'test') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_user_apply: %s' % repr(exc.value)) - assert not exc.value.args[0]['changed'] - module_args.update({'lock_user': 'false'}) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('user', 'true', 'test') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_user_unlock: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - - def test_ensure_user_set_password_called(self): - ''' set password ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'name': 'create'}) - module_args.update({'role_name': 'test'}) - module_args.update({'set_password': '123456'}) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('user', 'true') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_user_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - - def test_ensure_user_role_update_called(self): - ''' set password ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'name': 'create'}) - module_args.update({'role_name': 'test123'}) - module_args.update({'set_password': '123456'}) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('user', 'true') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_user_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - - def test_ensure_user_role_update_additional_application_called(self): - ''' set password ''' - module_args = {} - module_args.update(self.set_default_args()) - module_args.update({'name': 'create'}) - module_args.update({'role_name': 'test123'}) - module_args.update({'application': 'http'}) - module_args.update({'set_password': '123456'}) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('user', 'true') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - print('Info: test_user_apply: %s' % repr(exc.value)) - assert exc.value.args[0]['changed'] - - def test_if_all_methods_catch_exception(self): - data = self.set_default_args() - data.update({'role_name': 'test'}) - set_module_args(data) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('user_fail') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.get_user() - assert 'Error getting user ' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.create_user(data['applications']) - assert 'Error creating user ' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.lock_given_user() - assert 'Error locking user ' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.unlock_given_user() - assert 'Error unlocking user ' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.delete_user(data['applications']) - assert 'Error removing user ' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.change_password() - assert 'Error setting password for user ' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.modify_user(data['applications']) - assert 'Error modifying user ' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_user_role.py b/test/units/modules/storage/netapp/test_na_ontap_user_role.py deleted file mode 100644 index bb3dfd615e..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_user_role.py +++ /dev/null @@ -1,238 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_user_role \ - import NetAppOntapUserRole as role_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'role': - xml = self.build_role_info(self.params) - if self.kind == 'error': - error = netapp_utils.zapi.NaApiError('test', 'error') - raise error - self.xml_out = xml - return xml - - @staticmethod - def build_role_info(vol_details): - ''' build xml data for role-attributes ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'security-login-role-info': { - 'access-level': 'all', - 'command-directory-name': 'volume', - 'role-name': 'testrole', - 'role-query': 'show', - 'vserver': 'ansible' - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.mock_role = { - 'name': 'testrole', - 'access_level': 'all', - 'command_directory_name': 'volume', - 'vserver': 'ansible' - } - - def mock_args(self): - return { - 'name': self.mock_role['name'], - 'vserver': self.mock_role['vserver'], - 'command_directory_name': self.mock_role['command_directory_name'], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'https': 'False' - } - - def get_role_mock_object(self, kind=None): - """ - Helper method to return an na_ontap_user_role object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_user_role object - """ - role_obj = role_module() - role_obj.asup_log_for_cserver = Mock(return_value=None) - role_obj.cluster = Mock() - role_obj.cluster.invoke_successfully = Mock() - if kind is None: - role_obj.server = MockONTAPConnection() - else: - role_obj.server = MockONTAPConnection(kind=kind, data=self.mock_role) - return role_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - role_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_nonexistent_policy(self): - ''' Test if get_role returns None for non-existent role ''' - set_module_args(self.mock_args()) - result = self.get_role_mock_object().get_role() - assert result is None - - def test_get_existing_role(self): - ''' Test if get_role returns details for existing role ''' - set_module_args(self.mock_args()) - result = self.get_role_mock_object('role').get_role() - assert result['name'] == self.mock_role['name'] - - def test_successful_create(self): - ''' Test successful create ''' - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_role_mock_object().apply() - assert exc.value.args[0]['changed'] - - def test_create_idempotency(self): - ''' Test create idempotency ''' - data = self.mock_args() - data['query'] = 'show' - set_module_args(data) - obj = self.get_role_mock_object('role') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_user_role.NetAppOntapUserRole.get_role') - def test_create_error(self, get_role): - ''' Test create error ''' - set_module_args(self.mock_args()) - get_role.side_effect = [ - None - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_role_mock_object('error').apply() - assert exc.value.args[0]['msg'] == 'Error creating role testrole: NetApp API failed. Reason - test:error' - - @patch('ansible.modules.storage.netapp.na_ontap_user_role.NetAppOntapUserRole.get_role') - def test_successful_modify(self, get_role): - ''' Test successful modify ''' - data = self.mock_args() - data['query'] = 'show' - set_module_args(data) - current = self.mock_role - current['query'] = 'show-space' - get_role.side_effect = [ - current - ] - obj = self.get_role_mock_object() - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_user_role.NetAppOntapUserRole.get_role') - def test_modify_idempotency(self, get_role): - ''' Test modify idempotency ''' - data = self.mock_args() - data['query'] = 'show' - set_module_args(data) - current = self.mock_role - current['query'] = 'show' - get_role.side_effect = [ - current - ] - obj = self.get_role_mock_object() - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_user_role.NetAppOntapUserRole.get_role') - def test_modify_error(self, get_role): - ''' Test modify error ''' - data = self.mock_args() - data['query'] = 'show' - set_module_args(data) - current = self.mock_role - current['query'] = 'show-space' - get_role.side_effect = [ - current - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_role_mock_object('error').apply() - assert exc.value.args[0]['msg'] == 'Error modifying role testrole: NetApp API failed. Reason - test:error' - - def test_successful_delete(self): - ''' Test delete existing role ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_role_mock_object('role').apply() - assert exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_volume.py b/test/units/modules/storage/netapp/test_na_ontap_volume.py deleted file mode 100644 index 207a9a36ea..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_volume.py +++ /dev/null @@ -1,970 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_volume \ - import NetAppOntapVolume as vol_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None, job_error=None): - ''' save arguments ''' - self.kind = kind - self.params = data - self.xml_in = None - self.xml_out = None - self.job_error = job_error - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'volume': - xml = self.build_volume_info(self.params) - elif self.kind == 'job_info': - xml = self.build_job_info(self.job_error) - elif self.kind == 'error_modify': - xml = self.build_modify_error() - elif self.kind == 'failure_modify_async': - xml = self.build_failure_modify_async() - elif self.kind == 'success_modify_async': - xml = self.build_success_modify_async() - elif self.kind == 'zapi_error': - error = netapp_utils.zapi.NaApiError('test', 'error') - raise error - self.xml_out = xml - return xml - - @staticmethod - def build_volume_info(vol_details): - ''' build xml data for volume-attributes ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'volume-attributes': { - 'volume-id-attributes': { - 'containing-aggregate-name': vol_details['aggregate'], - 'junction-path': vol_details['junction_path'], - 'style-extended': 'flexvol', - 'comment': vol_details['comment'] - }, - 'volume-language-attributes': { - 'language-code': 'en' - }, - 'volume-export-attributes': { - 'policy': 'default' - }, - 'volume-performance-attributes': { - 'is-atime-update-enabled': 'true' - }, - 'volume-state-attributes': { - 'state': "online", - 'is-nvfail-enabled': 'true' - }, - 'volume-space-attributes': { - 'space-guarantee': 'none', - 'size': vol_details['size'], - 'percentage-snapshot-reserve': vol_details['percent_snapshot_space'], - 'space-slo': 'thick' - }, - 'volume-snapshot-attributes': { - 'snapshot-policy': vol_details['snapshot_policy'] - }, - 'volume-comp-aggr-attributes': { - 'tiering-policy': 'snapshot-only' - }, - 'volume-security-attributes': { - 'volume-security-unix-attributes': { - 'permissions': vol_details['unix_permissions'] - } - }, - 'volume-vserver-dr-protection-attributes': { - 'vserver-dr-protection': vol_details['vserver_dr_protection'], - }, - 'volume-qos-attributes': { - 'policy-group-name': vol_details['qos_policy_group'], - 'adaptive-policy-group-name': vol_details['qos_adaptive_policy_group'] - } - } - } - } - xml.translate_struct(attributes) - return xml - - @staticmethod - def build_flex_group_info(vol_details): - ''' build xml data for flexGroup volume-attributes ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'volume-attributes': { - 'volume-id-attributes': { - 'aggr-list': vol_details['aggregate'], - 'junction-path': vol_details['junction_path'], - 'style-extended': 'flexgroup', - 'comment': vol_details['comment'] - }, - 'volume-language-attributes': { - 'language-code': 'en' - }, - 'volume-export-attributes': { - 'policy': 'default' - }, - 'volume-performance-attributes': { - 'is-atime-update-enabled': 'true' - }, - 'volume-state-attributes': { - 'state': "online" - }, - 'volume-space-attributes': { - 'space-guarantee': 'none', - 'size': vol_details['size'] - }, - 'volume-snapshot-attributes': { - 'snapshot-policy': vol_details['snapshot_policy'] - }, - 'volume-security-attributes': { - 'volume-security-unix-attributes': { - 'permissions': vol_details['unix_permissions'] - } - } - } - } - } - xml.translate_struct(attributes) - return xml - - @staticmethod - def build_job_info(error): - ''' build xml data for a job ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = netapp_utils.zapi.NaElement('attributes') - if error is None: - state = 'success' - elif error == 'time_out': - state = 'running' - elif error == 'failure': - state = 'failure' - else: - state = 'other' - attributes.add_node_with_children('job-info', **{ - 'job-state': state, - 'job-progress': 'dummy', - 'job-completion': error, - }) - xml.add_child_elem(attributes) - xml.add_new_child('result-status', 'in_progress') - xml.add_new_child('result-jobid', '1234') - return xml - - @staticmethod - def build_modify_error(): - ''' build xml data for modify error ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = netapp_utils.zapi.NaElement('failure-list') - info_list_obj = netapp_utils.zapi.NaElement('volume-modify-iter-info') - info_list_obj.add_new_child('error-message', 'modify error message') - attributes.add_child_elem(info_list_obj) - xml.add_child_elem(attributes) - return xml - - @staticmethod - def build_success_modify_async(): - ''' build xml data for success modify async ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = netapp_utils.zapi.NaElement('success-list') - info_list_obj = netapp_utils.zapi.NaElement('volume-modify-iter-async-info') - info_list_obj.add_new_child('status', 'in_progress') - info_list_obj.add_new_child('jobid', '1234') - attributes.add_child_elem(info_list_obj) - xml.add_child_elem(attributes) - return xml - - @staticmethod - def build_failure_modify_async(): - ''' build xml data for failure modify async ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = netapp_utils.zapi.NaElement('failure-list') - info_list_obj = netapp_utils.zapi.NaElement('volume-modify-iter-async-info') - info_list_obj.add_new_child('status', 'failed') - info_list_obj.add_new_child('jobid', '1234') - info_list_obj.add_new_child('error-message', 'modify error message') - attributes.add_child_elem(info_list_obj) - xml.add_child_elem(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.mock_vol = { - 'name': 'test_vol', - 'aggregate': 'test_aggr', - 'junction_path': '/test', - 'vserver': 'test_vserver', - 'size': 20971520, - 'unix_permissions': '755', - 'snapshot_policy': 'default', - 'qos_policy_group': 'performance', - 'qos_adaptive_policy_group': 'performance', - 'percent_snapshot_space': 60, - 'language': 'en', - 'vserver_dr_protection': 'unprotected', - 'comment': 'test comment' - } - - def mock_args(self, tag=None): - args = { - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'name': self.mock_vol['name'], - 'vserver': self.mock_vol['vserver'], - 'space_guarantee': 'none', - 'policy': 'default', - 'language': self.mock_vol['language'], - 'is_online': True, - 'unix_permissions': '---rwxr-xr-x', - 'snapshot_policy': 'default', - 'qos_policy_group': 'performance', - 'qos_adaptive_policy_group': 'performance', - 'size': 20, - 'size_unit': 'mb', - 'junction_path': '/test', - 'percent_snapshot_space': 60, - 'type': 'type', - 'nvfail_enabled': True, - 'space_slo': 'thick', - 'comment': self.mock_vol['comment'] - } - if tag is None: - args['aggregate_name'] = self.mock_vol['aggregate'] - return args - - elif tag == 'flexGroup_manual': - args['aggr_list'] = 'aggr_0,aggr_1' - args['aggr_list_multiplier'] = 2 - return args - - elif tag == 'flexGroup_auto': - args['auto_provision_as'] = 'flexgroup' - return args - - def get_volume_mock_object(self, kind=None, job_error=None): - """ - Helper method to return an na_ontap_volume object - :param kind: passes this param to MockONTAPConnection(). - :param job_error: error message when getting job status. - :return: na_ontap_volume object - """ - vol_obj = vol_module() - vol_obj.ems_log_event = Mock(return_value=None) - vol_obj.cluster = Mock() - vol_obj.cluster.invoke_successfully = Mock() - vol_obj.volume_style = None - if kind is None: - vol_obj.server = MockONTAPConnection() - elif kind == 'volume': - vol_obj.server = MockONTAPConnection(kind='volume', data=self.mock_vol) - elif kind == 'job_info': - vol_obj.server = MockONTAPConnection(kind='job_info', data=self.mock_vol, job_error=job_error) - elif kind == 'error_modify': - vol_obj.server = MockONTAPConnection(kind='error_modify', data=self.mock_vol) - elif kind == 'failure_modify_async': - vol_obj.server = MockONTAPConnection(kind='failure_modify_async', data=self.mock_vol) - elif kind == 'success_modify_async': - vol_obj.server = MockONTAPConnection(kind='success_modify_async', data=self.mock_vol) - elif kind == 'zapi_error': - vol_obj.server = MockONTAPConnection(kind='zapi_error', data=self.mock_vol) - return vol_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - vol_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_nonexistent_volume(self): - ''' Test if get_volume returns None for non-existent volume ''' - set_module_args(self.mock_args()) - result = self.get_volume_mock_object().get_volume() - assert result is None - - def test_get_existing_volume(self): - ''' Test if get_volume returns details for existing volume ''' - set_module_args(self.mock_args()) - result = self.get_volume_mock_object('volume').get_volume() - assert result['name'] == self.mock_vol['name'] - assert result['size'] == self.mock_vol['size'] - - def test_create_error_missing_param(self): - ''' Test if create throws an error if aggregate_name is not specified''' - data = self.mock_args() - del data['aggregate_name'] - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_volume_mock_object('volume').create_volume() - msg = 'Error provisioning volume test_vol: aggregate_name is required' - assert exc.value.args[0]['msg'] == msg - - def test_successful_create(self): - ''' Test successful create ''' - data = self.mock_args() - data['size'] = 20 - data['encrypt'] = True - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_volume_mock_object().apply() - assert exc.value.args[0]['changed'] - - def test_create_idempotency(self): - ''' Test create idempotency ''' - set_module_args(self.mock_args()) - obj = self.get_volume_mock_object('volume') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert not exc.value.args[0]['changed'] - - def test_successful_delete(self): - ''' Test delete existing volume ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_volume_mock_object('volume').apply() - assert exc.value.args[0]['changed'] - - def test_delete_idempotency(self): - ''' Test delete idempotency ''' - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_volume_mock_object().apply() - assert not exc.value.args[0]['changed'] - - def test_successful_modify_size(self): - ''' Test successful modify size ''' - data = self.mock_args() - data['size'] = 200 - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_volume_mock_object('volume').apply() - assert exc.value.args[0]['changed'] - - def test_modify_idempotency(self): - ''' Test modify idempotency ''' - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_volume_mock_object('volume').apply() - assert not exc.value.args[0]['changed'] - - def test_modify_error(self): - ''' Test modify idempotency ''' - data = self.mock_args() - set_module_args(data) - with pytest.raises(AnsibleFailJson) as exc: - self.get_volume_mock_object('error_modify').volume_modify_attributes(dict()) - assert exc.value.args[0]['msg'] == 'Error modifying volume test_vol: modify error message' - - def test_mount_volume(self): - ''' Test mount volume ''' - data = self.mock_args() - data['junction_path'] = "/test123" - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_volume_mock_object('volume').apply() - assert exc.value.args[0]['changed'] - - def test_unmount_volume(self): - ''' Test unmount volume ''' - data = self.mock_args() - data['junction_path'] = "" - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_volume_mock_object('volume').apply() - assert exc.value.args[0]['changed'] - - def test_successful_modify_space(self): - ''' Test successful modify space ''' - data = self.mock_args() - data['space_guarantee'] = 'volume' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_volume_mock_object('volume').apply() - assert exc.value.args[0]['changed'] - - def test_successful_modify_unix_permissions(self): - ''' Test successful modify unix_permissions ''' - data = self.mock_args() - data['unix_permissions'] = '---rw-r-xr-x' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_volume_mock_object('volume').apply() - assert exc.value.args[0]['changed'] - - def test_successful_modify_snapshot_policy(self): - ''' Test successful modify snapshot_policy ''' - data = self.mock_args() - data['snapshot_policy'] = 'default-1weekly' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_volume_mock_object('volume').apply() - assert exc.value.args[0]['changed'] - - def test_successful_modify_percent_snapshot_space(self): - ''' Test successful modify percent_snapshot_space ''' - data = self.mock_args() - data['percent_snapshot_space'] = '90' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_volume_mock_object('volume').apply() - assert exc.value.args[0]['changed'] - - def test_successful_modify_qos_policy_group(self): - ''' Test successful modify qos_policy_group ''' - data = self.mock_args() - data['qos_policy_group'] = 'extreme' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_volume_mock_object('volume').apply() - assert exc.value.args[0]['changed'] - - def test_successful_modify_qos_adaptive_policy_group(self): - ''' Test successful modify qos_adaptive_policy_group ''' - data = self.mock_args() - data['qos_adaptive_policy_group'] = 'extreme' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_volume_mock_object('volume').apply() - assert exc.value.args[0]['changed'] - - def test_successful_move(self): - ''' Test successful modify aggregate ''' - data = self.mock_args() - data['aggregate_name'] = 'different_aggr' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_volume_mock_object('volume').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_successful_rename(self, get_volume): - ''' Test successful rename volume ''' - data = self.mock_args() - data['from_name'] = self.mock_vol['name'] - data['name'] = 'new_name' - set_module_args(data) - current = { - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'name': self.mock_vol['name'], - 'vserver': self.mock_vol['vserver'], - } - get_volume.side_effect = [ - None, - current - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_volume_mock_object().apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_successful_rename_async(self, get_volume): - ''' Test successful rename volume ''' - data = self.mock_args() - data['from_name'] = self.mock_vol['name'] - data['name'] = 'new_name' - set_module_args(data) - current = { - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'name': self.mock_vol['name'], - 'vserver': self.mock_vol['vserver'], - 'is_infinite': True - } - get_volume.side_effect = [ - None, - current - ] - obj = self.get_volume_mock_object('job_info') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.change_volume_state') - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.volume_mount') - def test_modify_helper(self, mount_volume, change_state): - data = self.mock_args() - set_module_args(data) - modify = { - 'is_online': False, - 'junction_path': 'something' - } - obj = self.get_volume_mock_object('volume') - obj.modify_volume(modify) - change_state.assert_called_with() - mount_volume.assert_called_with() - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_compare_chmod_value_true_1(self, get_volume): - data = self.mock_args() - data['unix_permissions'] = '------------' - set_module_args(data) - current = { - 'unix_permissions': '0' - } - get_volume.side_effect = [ - current - ] - obj = self.get_volume_mock_object() - assert obj.compare_chmod_value(current) - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_compare_chmod_value_true_2(self, get_volume): - data = self.mock_args() - data['unix_permissions'] = '---rwxrwxrwx' - set_module_args(data) - current = { - 'unix_permissions': '777' - } - get_volume.side_effect = [ - current - ] - obj = self.get_volume_mock_object() - assert obj.compare_chmod_value(current) - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_compare_chmod_value_true_3(self, get_volume): - data = self.mock_args() - data['unix_permissions'] = '---rwxr-xr-x' - set_module_args(data) - current = { - 'unix_permissions': '755' - } - get_volume.side_effect = [ - current - ] - obj = self.get_volume_mock_object() - assert obj.compare_chmod_value(current) - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_compare_chmod_value_true_3(self, get_volume): - data = self.mock_args() - data['unix_permissions'] = '755' - set_module_args(data) - current = { - 'unix_permissions': '755' - } - get_volume.side_effect = [ - current - ] - obj = self.get_volume_mock_object() - assert obj.compare_chmod_value(current) - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_compare_chmod_value_false_1(self, get_volume): - data = self.mock_args() - data['unix_permissions'] = '---rwxrwxrwx' - set_module_args(data) - current = { - 'unix_permissions': '0' - } - get_volume.side_effect = [ - current - ] - obj = self.get_volume_mock_object() - assert not obj.compare_chmod_value(current) - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_compare_chmod_value_false_2(self, get_volume): - data = self.mock_args() - data['unix_permissions'] = '---rwxrwxrwx' - set_module_args(data) - current = None - get_volume.side_effect = [ - current - ] - obj = self.get_volume_mock_object() - assert not obj.compare_chmod_value(current) - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_compare_chmod_value_invalid_input_1(self, get_volume): - data = self.mock_args() - data['unix_permissions'] = '---xwrxwrxwr' - set_module_args(data) - current = { - 'unix_permissions': '777' - } - get_volume.side_effect = [ - current - ] - obj = self.get_volume_mock_object() - assert not obj.compare_chmod_value(current) - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_compare_chmod_value_invalid_input_2(self, get_volume): - data = self.mock_args() - data['unix_permissions'] = '---rwx-wx--a' - set_module_args(data) - current = { - 'unix_permissions': '0' - } - get_volume.side_effect = [ - current - ] - obj = self.get_volume_mock_object() - assert not obj.compare_chmod_value(current) - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_compare_chmod_value_invalid_input_3(self, get_volume): - data = self.mock_args() - data['unix_permissions'] = '---' - set_module_args(data) - current = { - 'unix_permissions': '0' - } - get_volume.side_effect = [ - current - ] - obj = self.get_volume_mock_object() - assert not obj.compare_chmod_value(current) - - def test_successful_create_flex_group_manually(self): - ''' Test successful create flexGroup manually ''' - data = self.mock_args('flexGroup_manual') - data['time_out'] = 20 - set_module_args(data) - obj = self.get_volume_mock_object('job_info') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert exc.value.args[0]['changed'] - - def test_successful_create_flex_group_auto_provision(self): - ''' Test successful create flexGroup auto provision ''' - data = self.mock_args('flexGroup_auto') - data['time_out'] = 20 - set_module_args(data) - obj = self.get_volume_mock_object('job_info') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_successful_delete_flex_group(self, get_volume): - ''' Test successful delete flexGroup ''' - data = self.mock_args('flexGroup_manual') - data['state'] = 'absent' - set_module_args(data) - current = { - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'name': self.mock_vol['name'], - 'vserver': self.mock_vol['vserver'], - 'style_extended': 'flexgroup', - 'unix_permissions': '755' - } - get_volume.side_effect = [ - current - ] - obj = self.get_volume_mock_object('job_info') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_successful_resize_flex_group(self, get_volume): - ''' Test successful reszie flexGroup ''' - data = self.mock_args('flexGroup_manual') - data['size'] = 400 - data['size_unit'] = 'mb' - set_module_args(data) - current = { - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'name': self.mock_vol['name'], - 'vserver': self.mock_vol['vserver'], - 'style_extended': 'flexgroup', - 'size': 20971520, - 'unix_permissions': '755' - } - get_volume.side_effect = [ - current - ] - obj = self.get_volume_mock_object('job_info') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.check_job_status') - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_successful_modify_unix_permissions_flex_group(self, get_volume, check_job_status): - ''' Test successful modify unix permissions flexGroup ''' - data = self.mock_args('flexGroup_manual') - data['time_out'] = 20 - data['unix_permissions'] = '---rw-r-xr-x' - set_module_args(data) - current = { - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'name': self.mock_vol['name'], - 'vserver': self.mock_vol['vserver'], - 'style_extended': 'flexgroup', - 'unix_permissions': '777' - } - get_volume.side_effect = [ - current - ] - check_job_status.side_effect = [ - None - ] - obj = self.get_volume_mock_object('success_modify_async') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_successful_modify_unix_permissions_flex_group_0_time_out(self, get_volume): - ''' Test successful modify unix permissions flexGroup ''' - data = self.mock_args('flexGroup_manual') - data['time_out'] = 0 - data['unix_permissions'] = '---rw-r-xr-x' - set_module_args(data) - current = { - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'name': self.mock_vol['name'], - 'vserver': self.mock_vol['vserver'], - 'style_extended': 'flexgroup', - 'unix_permissions': '777' - } - get_volume.side_effect = [ - current - ] - obj = self.get_volume_mock_object('success_modify_async') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.check_job_status') - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_error_modify_unix_permissions_flex_group(self, get_volume, check_job_status): - ''' Test error modify unix permissions flexGroup ''' - data = self.mock_args('flexGroup_manual') - data['time_out'] = 20 - data['unix_permissions'] = '---rw-r-xr-x' - set_module_args(data) - current = { - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'name': self.mock_vol['name'], - 'vserver': self.mock_vol['vserver'], - 'style_extended': 'flexgroup', - 'unix_permissions': '777' - } - get_volume.side_effect = [ - current - ] - check_job_status.side_effect = ['error'] - obj = self.get_volume_mock_object('success_modify_async') - with pytest.raises(AnsibleFailJson) as exc: - obj.apply() - assert exc.value.args[0]['msg'] == 'Error when modify volume: error' - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_failure_modify_unix_permissions_flex_group(self, get_volume): - ''' Test failure modify unix permissions flexGroup ''' - data = self.mock_args('flexGroup_manual') - data['unix_permissions'] = '---rw-r-xr-x' - data['time_out'] = 20 - set_module_args(data) - current = { - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'name': self.mock_vol['name'], - 'vserver': self.mock_vol['vserver'], - 'style_extended': 'flexvol', - 'unix_permissions': '777' - } - get_volume.side_effect = [ - current - ] - obj = self.get_volume_mock_object('failure_modify_async') - with pytest.raises(AnsibleFailJson) as exc: - obj.apply() - assert exc.value.args[0]['msg'] == 'Error modifying volume test_vol: modify error message' - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_successful_offline_state_flex_group(self, get_volume): - ''' Test successful offline flexGroup state ''' - data = self.mock_args('flexGroup_manual') - data['is_online'] = False - set_module_args(data) - current = { - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'name': self.mock_vol['name'], - 'vserver': self.mock_vol['vserver'], - 'style_extended': 'flexgroup', - 'is_online': True, - 'junction_path': 'anything', - 'unix_permissions': '755' - } - get_volume.side_effect = [ - current - ] - obj = self.get_volume_mock_object('job_info') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_volume.NetAppOntapVolume.get_volume') - def test_successful_online_state_flex_group(self, get_volume): - ''' Test successful online flexGroup state ''' - data = self.mock_args('flexGroup_manual') - set_module_args(data) - current = { - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'name': self.mock_vol['name'], - 'vserver': self.mock_vol['vserver'], - 'style_extended': 'flexgroup', - 'is_online': False, - 'junction_path': 'anything', - 'unix_permissions': '755' - } - get_volume.side_effect = [ - current - ] - obj = self.get_volume_mock_object('job_info') - with pytest.raises(AnsibleExitJson) as exc: - obj.apply() - assert exc.value.args[0]['changed'] - - def test_check_job_status_error(self): - ''' Test check job status error ''' - data = self.mock_args('flexGroup_manual') - data['time_out'] = 0 - set_module_args(data) - obj = self.get_volume_mock_object('job_info', job_error='failure') - result = obj.check_job_status('123') - assert result == 'failure' - - def test_check_job_status_time_out_is_0(self): - ''' Test check job status time out is 0''' - data = self.mock_args('flexGroup_manual') - data['time_out'] = 0 - set_module_args(data) - obj = self.get_volume_mock_object('job_info', job_error='time_out') - result = obj.check_job_status('123') - assert result == 'job completion exceeded expected timer of: 0 seconds' - - def test_check_job_status_unexpected(self): - ''' Test check job status unexpected state ''' - data = self.mock_args('flexGroup_manual') - data['time_out'] = 20 - set_module_args(data) - obj = self.get_volume_mock_object('job_info', job_error='other') - with pytest.raises(AnsibleFailJson) as exc: - obj.check_job_status('123') - assert exc.value.args[0]['failed'] - - def test_error_assign_efficiency_policy(self): - data = self.mock_args() - data['efficiency_policy'] = 'test_policy' - set_module_args(data) - obj = self.get_volume_mock_object('zapi_error') - with pytest.raises(AnsibleFailJson) as exc: - obj.assign_efficiency_policy() - assert exc.value.args[0]['msg'] == 'Error enable efficiency on volume test_vol: NetApp API failed. Reason - test:error' - - def test_error_assign_efficiency_policy_async(self): - data = self.mock_args() - data['efficiency_policy'] = 'test_policy' - set_module_args(data) - obj = self.get_volume_mock_object('zapi_error') - with pytest.raises(AnsibleFailJson) as exc: - obj.assign_efficiency_policy_async() - assert exc.value.args[0]['msg'] == 'Error enable efficiency on volume test_vol: NetApp API failed. Reason - test:error' - - def test_successful_modify_tiering_policy(self): - ''' Test successful modify tiering policy ''' - data = self.mock_args() - data['tiering_policy'] = 'auto' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_volume_mock_object('volume').apply() - assert exc.value.args[0]['changed'] - - def test_successful_modify_vserver_dr_protection(self): - ''' Test successful modify vserver_dr_protection ''' - data = self.mock_args() - data['vserver_dr_protection'] = 'protected' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_volume_mock_object('volume').apply() - assert exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_volume_autosize.py b/test/units/modules/storage/netapp/test_na_ontap_volume_autosize.py deleted file mode 100644 index 75dad9c3b0..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_volume_autosize.py +++ /dev/null @@ -1,242 +0,0 @@ -# (c) 2019, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests for Ansible module: na_ontap_volume_autosize ''' - -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_volume_autosize \ - import NetAppOntapVolumeAutosize as autosize_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -# REST API canned responses when mocking send_request -SRR = { - # common responses - 'is_rest': (200, None), - 'is_zapi': (400, "Unreachable"), - 'empty_good': ({}, None), - 'end_of_sequence': (None, "Unexpected call to send_request"), - 'generic_error': (None, "Expected error"), - # module specific responses - 'get_uuid': ({'records': [{'uuid': 'testuuid'}]}, None), - 'get_autosize': ({'uuid': 'testuuid', - 'name': 'testname', - 'autosize': {"maximum": 10737418240, - "minimum": 22020096, - "grow_threshold": 99, - "shrink_threshold": 40, - "mode": "grow" - } - }, None) -} - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'autosize': - xml = self.build_autosize_info(self.params) - self.xml_out = xml - return xml - - @staticmethod - def build_autosize_info(autosize_details): - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'grow-threshold-percent': autosize_details['grow_threshold_percent'], - 'maximum-size': '10485760', - 'minimum-size': '21504', - 'increment_size': '10240', - 'mode': autosize_details['mode'], - 'shrink-threshold-percent': autosize_details['shrink_threshold_percent'] - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' Unit tests for na_ontap_job_schedule ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.mock_autosize = { - 'grow_threshold_percent': 99, - 'maximum_size': '10g', - 'minimum_size': '21m', - 'increment_size': '10m', - 'mode': 'grow', - 'shrink_threshold_percent': 40, - 'vserver': 'test_vserver', - 'volume': 'test_volume' - } - - def mock_args(self, rest=False): - if rest: - return { - 'vserver': self.mock_autosize['vserver'], - 'volume': self.mock_autosize['volume'], - 'grow_threshold_percent': self.mock_autosize['grow_threshold_percent'], - 'maximum_size': self.mock_autosize['maximum_size'], - 'minimum_size': self.mock_autosize['minimum_size'], - 'mode': self.mock_autosize['mode'], - 'shrink_threshold_percent': self.mock_autosize['shrink_threshold_percent'], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - else: - return { - 'vserver': self.mock_autosize['vserver'], - 'volume': self.mock_autosize['volume'], - 'grow_threshold_percent': self.mock_autosize['grow_threshold_percent'], - 'maximum_size': self.mock_autosize['maximum_size'], - 'minimum_size': self.mock_autosize['minimum_size'], - 'increment_size': self.mock_autosize['increment_size'], - 'mode': self.mock_autosize['mode'], - 'shrink_threshold_percent': self.mock_autosize['shrink_threshold_percent'], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - - def get_autosize_mock_object(self, type='zapi', kind=None): - autosize_obj = autosize_module() - if type == 'zapi': - if kind is None: - autosize_obj.server = MockONTAPConnection() - elif kind == 'autosize': - autosize_obj.server = MockONTAPConnection(kind='autosize', data=self.mock_autosize) - return autosize_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - autosize_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_idempotent_modify(self): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_autosize_mock_object('zapi', 'autosize').apply() - assert not exc.value.args[0]['changed'] - - def test_successful_modify(self): - data = self.mock_args() - data['maximum_size'] = '11g' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_autosize_mock_object('zapi', 'autosize').apply() - assert exc.value.args[0]['changed'] - - def test_successful_reset(self): - data = {} - data['reset'] = True - data['hostname'] = 'test' - data['username'] = 'test_user' - data['password'] = 'test_pass!' - data['volume'] = 'test_vol' - data['vserver'] = 'test_vserver' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_autosize_mock_object('zapi', 'autosize').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.OntapRestAPI.send_request') - def test_rest_error(self, mock_request): - data = self.mock_args(rest=True) - set_module_args(data) - mock_request.side_effect = [ - SRR['is_rest'], - SRR['generic_error'], - SRR['end_of_sequence'] - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_autosize_mock_object(type='rest').apply() - assert exc.value.args[0]['msg'] == SRR['generic_error'][1] - - @patch('ansible.module_utils.netapp.OntapRestAPI.send_request') - def test_rest_successful_modify(self, mock_request): - data = self.mock_args(rest=True) - data['maximum_size'] = '11g' - set_module_args(data) - mock_request.side_effect = [ - SRR['is_rest'], - SRR['get_uuid'], - SRR['get_autosize'], - SRR['empty_good'], - SRR['end_of_sequence'] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_autosize_mock_object(type='rest').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.OntapRestAPI.send_request') - def test_rest_idempotent_modify(self, mock_request): - data = self.mock_args(rest=True) - set_module_args(data) - mock_request.side_effect = [ - SRR['is_rest'], - SRR['get_uuid'], - SRR['get_autosize'], - SRR['empty_good'], - SRR['end_of_sequence'] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_autosize_mock_object(type='rest').apply() - assert not exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_volume_clone.py b/test/units/modules/storage/netapp/test_na_ontap_volume_clone.py deleted file mode 100644 index 2aadb0660d..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_volume_clone.py +++ /dev/null @@ -1,179 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests ONTAP Ansible module: na_ontap_volume_clone''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_volume_clone \ - import NetAppONTAPVolumeClone as my_module - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None): - ''' save arguments ''' - self.type = kind - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'volume_clone': - xml = self.build_volume_clone_info() - elif self.type == 'volume_clone_fail': - raise netapp_utils.zapi.NaApiError(code='TEST', message="This exception is from the unit test") - self.xml_out = xml - return xml - - @staticmethod - def build_volume_clone_info(): - ''' build xml data for volume-clone-info ''' - xml = netapp_utils.zapi.NaElement('xml') - data = {'attributes': {'volume-clone-info': {'volume': 'ansible', - 'parent-volume': 'ansible'}}} - xml.translate_struct(data) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.server = MockONTAPConnection() - self.onbox = False - - def set_default_args(self): - if self.onbox: - hostname = '10.10.10.10' - username = 'username' - password = 'password' - vserver = 'ansible' - volume = 'ansible' - parent_volume = 'ansible' - else: - hostname = '10.10.10.10' - username = 'username' - password = 'password' - vserver = 'ansible' - volume = 'ansible' - parent_volume = 'ansible' - return dict({ - 'hostname': hostname, - 'username': username, - 'password': password, - 'vserver': vserver, - 'volume': volume, - 'parent_volume': parent_volume - }) - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - my_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_ensure_get_called(self): - ''' test get_volume_clone() for non-existent volume clone''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = self.server - assert my_obj.get_volume_clone() is None - - def test_ensure_get_called_existing(self): - ''' test get_volume_clone() for existing volume clone''' - set_module_args(self.set_default_args()) - my_obj = my_module() - my_obj.server = MockONTAPConnection(kind='volume_clone') - assert my_obj.get_volume_clone() - - @patch('ansible.modules.storage.netapp.na_ontap_volume_clone.NetAppONTAPVolumeClone.create_volume_clone') - def test_successful_create(self, create_volume_clone): - ''' creating volume_clone and testing idempotency ''' - module_args = { - 'parent_snapshot': 'abc', - 'parent_vserver': 'abc', - 'volume_type': 'dp', - 'qos_policy_group_name': 'abc', - 'junction_path': 'abc', - 'uid': '1', - 'gid': '1' - } - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = self.server - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert exc.value.args[0]['changed'] - create_volume_clone.assert_called_with() - # to reset na_helper from remembering the previous 'changed' value - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('volume_clone') - with pytest.raises(AnsibleExitJson) as exc: - my_obj.apply() - assert not exc.value.args[0]['changed'] - - def test_if_all_methods_catch_exception(self): - module_args = {} - module_args.update(self.set_default_args()) - set_module_args(module_args) - my_obj = my_module() - if not self.onbox: - my_obj.server = MockONTAPConnection('volume_clone_fail') - with pytest.raises(AnsibleFailJson) as exc: - my_obj.get_volume_clone() - assert 'Error fetching volume clone information ' in exc.value.args[0]['msg'] - with pytest.raises(AnsibleFailJson) as exc: - my_obj.create_volume_clone() - assert 'Error creating volume clone: ' in exc.value.args[0]['msg'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_vscan.py b/test/units/modules/storage/netapp/test_na_ontap_vscan.py deleted file mode 100644 index bdc9eb1c59..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_vscan.py +++ /dev/null @@ -1,231 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests for Ansible module: na_ontap_vscan''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_vscan \ - import NetAppOntapVscan as vscan_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') -HAS_NETAPP_ZAPI_MSG = "pip install netapp_lib is required" - - -# REST API canned responses when mocking send_request -SRR = { - # common responses - 'is_rest': (200, None), - 'is_zapi': (400, "Unreachable"), - 'empty_good': ({}, None), - 'end_of_sequence': (None, "Ooops, the UT needs one more SRR response"), - 'generic_error': (None, "Expected error"), - # module specific responses - 'enabled': ({'records': [{'enabled': True, 'svm': {'uuid': 'testuuid'}}]}, None), - 'disabled': ({'records': [{'enabled': False, 'svm': {'uuid': 'testuuid'}}]}, None), -} - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'enable': - xml = self.build_vscan_status_info(self.params) - self.xml_out = xml - return xml - - @staticmethod - def build_vscan_status_info(status): - xml = netapp_utils.zapi.NaElement('xml') - attributes = {'num-records': 1, - 'attributes-list': {'vscan-status-info': {'is-vscan-enabled': status}}} - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' Unit tests for na_ontap_job_schedule ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - - def mock_args(self): - return { - 'enable': False, - 'vserver': 'vserver', - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - - def get_vscan_mock_object(self, type='zapi', kind=None, status=None): - vscan_obj = vscan_module() - if type == 'zapi': - if kind is None: - vscan_obj.server = MockONTAPConnection() - else: - vscan_obj.server = MockONTAPConnection(kind=kind, data=status) - # For rest, mocking is achieved through side_effect - return vscan_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - vscan_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_successfully_enable(self): - data = self.mock_args() - data['enable'] = True - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_vscan_mock_object('zapi', 'enable', 'false').apply() - assert exc.value.args[0]['changed'] - - def test_idempotently_enable(self): - data = self.mock_args() - data['enable'] = True - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_vscan_mock_object('zapi', 'enable', 'true').apply() - assert not exc.value.args[0]['changed'] - - def test_successfully_disable(self): - data = self.mock_args() - data['enable'] = False - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_vscan_mock_object('zapi', 'enable', 'true').apply() - assert exc.value.args[0]['changed'] - - def test_idempotently_disable(self): - data = self.mock_args() - data['enable'] = False - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_vscan_mock_object('zapi', 'enable', 'false').apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.OntapRestAPI.send_request') - def test_rest_error(self, mock_request): - data = self.mock_args() - set_module_args(data) - mock_request.side_effect = [ - SRR['is_rest'], - SRR['generic_error'], - SRR['end_of_sequence'] - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_vscan_mock_object(type='rest').apply() - assert exc.value.args[0]['msg'] == SRR['generic_error'][1] - - @patch('ansible.module_utils.netapp.OntapRestAPI.send_request') - def test_rest_successly_enable(self, mock_request): - data = self.mock_args() - data['enable'] = True - set_module_args(data) - mock_request.side_effect = [ - SRR['is_rest'], - SRR['disabled'], - SRR['empty_good'], - SRR['end_of_sequence'] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_vscan_mock_object(type='rest').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.OntapRestAPI.send_request') - def test_rest_idempotently_enable(self, mock_request): - data = self.mock_args() - data['enable'] = True - set_module_args(data) - mock_request.side_effect = [ - SRR['is_rest'], - SRR['enabled'], - SRR['end_of_sequence'] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_vscan_mock_object(type='rest').apply() - assert not exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.OntapRestAPI.send_request') - def test_rest_successly_disable(self, mock_request): - data = self.mock_args() - data['enable'] = False - set_module_args(data) - mock_request.side_effect = [ - SRR['is_rest'], - SRR['enabled'], - SRR['empty_good'], - SRR['end_of_sequence'] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_vscan_mock_object(type='rest').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.module_utils.netapp.OntapRestAPI.send_request') - def test_rest_idempotently_disable(self, mock_request): - data = self.mock_args() - data['enable'] = False - set_module_args(data) - mock_request.side_effect = [ - SRR['is_rest'], - SRR['disabled'], - SRR['end_of_sequence'] - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_vscan_mock_object(type='rest').apply() - assert not exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_vscan_on_access_policy.py b/test/units/modules/storage/netapp/test_na_ontap_vscan_on_access_policy.py deleted file mode 100644 index 50494f54ab..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_vscan_on_access_policy.py +++ /dev/null @@ -1,156 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests for Ansible module: na_ontap_vscan_scanner_pool ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_vscan_on_access_policy \ - import NetAppOntapVscanOnAccessPolicy as policy_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') -HAS_NETAPP_ZAPI_MSG = "pip install netapp_lib is required" - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'policy': - xml = self.build_access_policy_info(self.params) - self.xml_out = xml - return xml - - @staticmethod - def build_access_policy_info(policy_details): - xml = netapp_utils.zapi.NaElement('xml') - attributes = {'num-records': 1, - 'attributes-list': {'vscan-on-access-policy-info': {'policy-name': policy_details['policy_name']}}} - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' Unit tests for na_ontap_job_schedule ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.mock_access_policy = { - 'state': 'present', - 'vserver': 'test_vserver', - 'policy_name': 'test_carchi' - } - - def mock_args(self): - return { - 'state': self.mock_access_policy['state'], - 'vserver': self.mock_access_policy['vserver'], - 'policy_name': self.mock_access_policy['policy_name'], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - - def get_policy_mock_object(self, kind=None): - policy_obj = policy_module() - if kind is None: - policy_obj.server = MockONTAPConnection() - else: - policy_obj.server = MockONTAPConnection(kind='policy', data=self.mock_access_policy) - return policy_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - policy_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_nonexistent_policy(self): - set_module_args(self.mock_args()) - result = self.get_policy_mock_object().exists_access_policy() - assert not result - - def test_get_existing_scanner(self): - set_module_args(self.mock_args()) - result = self.get_policy_mock_object('policy').exists_access_policy() - assert result - - def test_successfully_create(self): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_mock_object().apply() - assert exc.value.args[0]['changed'] - - def test_create_idempotency(self): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_mock_object('policy').apply() - assert exc.value.args[0]['changed'] - - def test_successfully_delete(self): - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_mock_object('policy').apply() - assert exc.value.args[0]['changed'] - - def test_delete_idempotency(self): - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_policy_mock_object().apply() - assert not exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_vscan_on_demand_task.py b/test/units/modules/storage/netapp/test_na_ontap_vscan_on_demand_task.py deleted file mode 100644 index 544e0f6699..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_vscan_on_demand_task.py +++ /dev/null @@ -1,167 +0,0 @@ -''' unit tests for Ansible module: na_ontap_vscan_on_demand_task ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_vscan_on_demand_task \ - import NetAppOntapVscanOnDemandTask as onDemand_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'task': - xml = self.build_onDemand_pool_info(self.params) - self.xml_out = xml - return xml - - @staticmethod - def build_onDemand_pool_info(onDemand_details): - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'vscan-on-demand-task-info': { - 'task-name': onDemand_details['task_name'], - 'report-directory': onDemand_details['report_directory'], - 'scan-paths': { - 'string': onDemand_details['scan_paths'] - } - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' Unit tests for na_ontap_job_schedule ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.mock_onDemand = { - 'state': 'present', - 'vserver': 'test_vserver', - 'report_directory': '/', - 'task_name': '/', - 'scan_paths': '/' - } - - def mock_args(self): - return { - 'state': self.mock_onDemand['state'], - 'vserver': self.mock_onDemand['vserver'], - 'report_directory': self.mock_onDemand['report_directory'], - 'task_name': self.mock_onDemand['task_name'], - 'scan_paths': self.mock_onDemand['scan_paths'], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!' - } - - def get_demand_mock_object(self, kind=None): - scanner_obj = onDemand_module() - scanner_obj.asup_log_for_cserver = Mock(return_value=None) - if kind is None: - scanner_obj.server = MockONTAPConnection() - else: - scanner_obj.server = MockONTAPConnection(kind='task', data=self.mock_onDemand) - return scanner_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - onDemand_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_nonexistent_demand_task(self): - set_module_args(self.mock_args()) - result = self.get_demand_mock_object().get_demand_task() - assert not result - - def test_get_existing_demand_task(self): - set_module_args(self.mock_args()) - result = self.get_demand_mock_object('task').get_demand_task() - assert result - - def test_successfully_create(self): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_demand_mock_object().apply() - assert exc.value.args[0]['changed'] - - def test_create_idempotency(self): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_demand_mock_object('task').apply() - assert not exc.value.args[0]['changed'] - - def test_successfully_delete(self): - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_demand_mock_object('task').apply() - assert exc.value.args[0]['changed'] - - def test_delete_idempotency(self): - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_demand_mock_object().apply() - assert not exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_vscan_scanner_pool.py b/test/units/modules/storage/netapp/test_na_ontap_vscan_scanner_pool.py deleted file mode 100644 index 3609e91ef8..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_vscan_scanner_pool.py +++ /dev/null @@ -1,179 +0,0 @@ -# (c) 2018, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit tests for Ansible module: na_ontap_vscan_scanner_pool ''' - -from __future__ import print_function -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_vscan_scanner_pool \ - import NetAppOntapVscanScannerPool as scanner_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.kind = kind - self.params = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.kind == 'scanner': - xml = self.build_scanner_pool_info(self.params) - self.xml_out = xml - return xml - - @staticmethod - def build_scanner_pool_info(sanner_details): - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'vscan-scanner-pool-info': { - 'scanner-pool': sanner_details['scanner_pool'], - 'scanner-policy': sanner_details['scanner_policy'] - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' Unit tests for na_ontap_job_schedule ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.mock_scanner = { - 'state': 'present', - 'scanner_pool': 'test_pool', - 'vserver': 'test_vserver', - 'hostnames': ['host1', 'host2'], - 'privileged_users': ['domain\\admin', 'domain\\carchi8py'], - 'scanner_policy': 'primary' - } - - def mock_args(self): - return { - 'state': self.mock_scanner['state'], - 'scanner_pool': self.mock_scanner['scanner_pool'], - 'vserver': self.mock_scanner['vserver'], - 'hostnames': self.mock_scanner['hostnames'], - 'privileged_users': self.mock_scanner['privileged_users'], - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'scanner_policy': self.mock_scanner['scanner_policy'] - } - - def get_scanner_mock_object(self, kind=None): - scanner_obj = scanner_module() - scanner_obj.asup_log_for_cserver = Mock(return_value=None) - if kind is None: - scanner_obj.server = MockONTAPConnection() - else: - scanner_obj.server = MockONTAPConnection(kind='scanner', data=self.mock_scanner) - return scanner_obj - - def test_module_fail_when_required_args_missing(self): - ''' required arguments are reported as errors ''' - with pytest.raises(AnsibleFailJson) as exc: - set_module_args({}) - scanner_module() - print('Info: %s' % exc.value.args[0]['msg']) - - def test_get_nonexistent_scanner(self): - ''' Test if get_scanner_pool returns None for non-existent job ''' - set_module_args(self.mock_args()) - result = self.get_scanner_mock_object().get_scanner_pool() - assert not result - - def test_get_existing_scanner(self): - ''' Test if get_scanner_pool returns None for non-existent job ''' - set_module_args(self.mock_args()) - result = self.get_scanner_mock_object('scanner').get_scanner_pool() - assert result - - def test_successfully_create(self): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_scanner_mock_object().apply() - assert exc.value.args[0]['changed'] - - def test_create_idempotency(self): - set_module_args(self.mock_args()) - with pytest.raises(AnsibleExitJson) as exc: - self.get_scanner_mock_object('scanner').apply() - assert not exc.value.args[0]['changed'] - - def test_apply_policy(self): - data = self.mock_args() - data['scanner_policy'] = 'secondary' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_scanner_mock_object('scanner').apply() - assert exc.value.args[0]['changed'] - - def test_successfully_delete(self): - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_scanner_mock_object('scanner').apply() - assert exc.value.args[0]['changed'] - - def test_delete_idempotency(self): - data = self.mock_args() - data['state'] = 'absent' - set_module_args(data) - with pytest.raises(AnsibleExitJson) as exc: - self.get_scanner_mock_object().apply() - assert not exc.value.args[0]['changed'] diff --git a/test/units/modules/storage/netapp/test_na_ontap_vserver_cifs_security.py b/test/units/modules/storage/netapp/test_na_ontap_vserver_cifs_security.py deleted file mode 100644 index d6dd0129fd..0000000000 --- a/test/units/modules/storage/netapp/test_na_ontap_vserver_cifs_security.py +++ /dev/null @@ -1,161 +0,0 @@ -# (c) 2019, NetApp, Inc -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -''' unit test template for ONTAP Ansible module ''' - -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type -import json -import pytest - -from units.compat import unittest -from units.compat.mock import patch, Mock -from ansible.module_utils import basic -from ansible.module_utils._text import to_bytes -import ansible.module_utils.netapp as netapp_utils - -from ansible.modules.storage.netapp.na_ontap_vserver_cifs_security \ - import NetAppONTAPCifsSecurity as cifs_security_module # module under test - -if not netapp_utils.has_netapp_lib(): - pytestmark = pytest.mark.skip('skipping as missing required netapp_lib') - - -def set_module_args(args): - """prepare arguments so that they will be picked up during module creation""" - args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) - basic._ANSIBLE_ARGS = to_bytes(args) # pylint: disable=protected-access - - -class AnsibleExitJson(Exception): - """Exception class to be raised by module.exit_json and caught by the test case""" - pass - - -class AnsibleFailJson(Exception): - """Exception class to be raised by module.fail_json and caught by the test case""" - pass - - -def exit_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over exit_json; package return data into an exception""" - if 'changed' not in kwargs: - kwargs['changed'] = False - raise AnsibleExitJson(kwargs) - - -def fail_json(*args, **kwargs): # pylint: disable=unused-argument - """function to patch over fail_json; package return data into an exception""" - kwargs['failed'] = True - raise AnsibleFailJson(kwargs) - - -class MockONTAPConnection(object): - ''' mock server connection to ONTAP host ''' - - def __init__(self, kind=None, data=None): - ''' save arguments ''' - self.type = kind - self.data = data - self.xml_in = None - self.xml_out = None - - def invoke_successfully(self, xml, enable_tunneling): # pylint: disable=unused-argument - ''' mock invoke_successfully returning xml data ''' - self.xml_in = xml - if self.type == 'cifs_security': - xml = self.build_port_info(self.data) - if self.type == 'error': - error = netapp_utils.zapi.NaApiError('test', 'error') - raise error - self.xml_out = xml - return xml - - @staticmethod - def build_port_info(cifs_security_details): - ''' build xml data for cifs-security ''' - xml = netapp_utils.zapi.NaElement('xml') - attributes = { - 'num-records': 1, - 'attributes-list': { - 'cifs-security': { - 'is_aes_encryption_enabled': cifs_security_details['is_aes_encryption_enabled'], - 'lm_compatibility_level': cifs_security_details['lm_compatibility_level'] - } - } - } - xml.translate_struct(attributes) - return xml - - -class TestMyModule(unittest.TestCase): - ''' a group of related Unit Tests ''' - - def setUp(self): - self.mock_module_helper = patch.multiple(basic.AnsibleModule, - exit_json=exit_json, - fail_json=fail_json) - self.mock_module_helper.start() - self.addCleanup(self.mock_module_helper.stop) - self.mock_cifs_security = { - 'is_aes_encryption_enabled': 'true', - 'lm_compatibility_level': 'krb' - } - - def mock_args(self): - return { - 'is_aes_encryption_enabled': self.mock_cifs_security['is_aes_encryption_enabled'], - 'lm_compatibility_level': self.mock_cifs_security['lm_compatibility_level'], - 'vserver': 'ansible', - 'hostname': 'test', - 'username': 'test_user', - 'password': 'test_pass!', - 'https': 'False' - } - - def get_cifs_security_mock_object(self, kind=None): - """ - Helper method to return an na_ontap_vserver_cifs_security object - :param kind: passes this param to MockONTAPConnection() - :return: na_ontap_vserver_cifs_security object - """ - obj = cifs_security_module() - obj.asup_log_for_cserver = Mock(return_value=None) - obj.server = Mock() - obj.server.invoke_successfully = Mock() - if kind is None: - obj.server = MockONTAPConnection() - else: - obj.server = MockONTAPConnection(kind=kind, data=self.mock_cifs_security) - return obj - - @patch('ansible.modules.storage.netapp.na_ontap_vserver_cifs_security.NetAppONTAPCifsSecurity.cifs_security_get_iter') - def test_successful_modify(self, get_cifs_security): - ''' Test successful modify max throughput ''' - data = self.mock_args() - set_module_args(data) - current = { - 'is_aes_encryption_enabled': False, - 'lm_compatibility_level': 'lm_ntlm_ntlmv2_krb' - } - get_cifs_security.side_effect = [ - current - ] - with pytest.raises(AnsibleExitJson) as exc: - self.get_cifs_security_mock_object('cifs_security').apply() - assert exc.value.args[0]['changed'] - - @patch('ansible.modules.storage.netapp.na_ontap_vserver_cifs_security.NetAppONTAPCifsSecurity.cifs_security_get_iter') - def test_modify_error(self, get_cifs_security): - ''' Test create idempotency ''' - data = self.mock_args() - set_module_args(data) - current = { - 'is_aes_encryption_enabled': False - } - get_cifs_security.side_effect = [ - current - ] - with pytest.raises(AnsibleFailJson) as exc: - self.get_cifs_security_mock_object('error').apply() - assert exc.value.args[0]['msg'] == 'Error modifying cifs security on ansible: NetApp API failed. Reason - test:error' |