summaryrefslogtreecommitdiffstats
path: root/ansible_collections/netapp/aws/tests/unit
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
commit975f66f2eebe9dadba04f275774d4ab83f74cf25 (patch)
tree89bd26a93aaae6a25749145b7e4bca4a1e75b2be /ansible_collections/netapp/aws/tests/unit
parentInitial commit. (diff)
downloadansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.tar.xz
ansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.zip
Adding upstream version 7.7.0+dfsg.upstream/7.7.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/netapp/aws/tests/unit')
-rw-r--r--ansible_collections/netapp/aws/tests/unit/compat/__init__.py0
-rw-r--r--ansible_collections/netapp/aws/tests/unit/compat/builtins.py33
-rw-r--r--ansible_collections/netapp/aws/tests/unit/compat/mock.py122
-rw-r--r--ansible_collections/netapp/aws/tests/unit/compat/unittest.py44
-rw-r--r--ansible_collections/netapp/aws/tests/unit/plugins/module_utils/test_netapp.py195
-rw-r--r--ansible_collections/netapp/aws/tests/unit/plugins/modules/test_aws_netapp_cvs_active_directory.py117
-rw-r--r--ansible_collections/netapp/aws/tests/unit/plugins/modules/test_aws_netapp_cvs_filesystems.py155
-rw-r--r--ansible_collections/netapp/aws/tests/unit/plugins/modules/test_aws_netapp_cvs_pool.py258
-rw-r--r--ansible_collections/netapp/aws/tests/unit/plugins/modules/test_aws_netapp_cvs_snapshots.py147
-rw-r--r--ansible_collections/netapp/aws/tests/unit/requirements.txt1
10 files changed, 1072 insertions, 0 deletions
diff --git a/ansible_collections/netapp/aws/tests/unit/compat/__init__.py b/ansible_collections/netapp/aws/tests/unit/compat/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/netapp/aws/tests/unit/compat/__init__.py
diff --git a/ansible_collections/netapp/aws/tests/unit/compat/builtins.py b/ansible_collections/netapp/aws/tests/unit/compat/builtins.py
new file mode 100644
index 000000000..f60ee6782
--- /dev/null
+++ b/ansible_collections/netapp/aws/tests/unit/compat/builtins.py
@@ -0,0 +1,33 @@
+# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+#
+# Compat for python2.7
+#
+
+# One unittest needs to import builtins via __import__() so we need to have
+# the string that represents it
+try:
+ import __builtin__
+except ImportError:
+ BUILTINS = 'builtins'
+else:
+ BUILTINS = '__builtin__'
diff --git a/ansible_collections/netapp/aws/tests/unit/compat/mock.py b/ansible_collections/netapp/aws/tests/unit/compat/mock.py
new file mode 100644
index 000000000..0972cd2e8
--- /dev/null
+++ b/ansible_collections/netapp/aws/tests/unit/compat/mock.py
@@ -0,0 +1,122 @@
+# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+'''
+Compat module for Python3.x's unittest.mock module
+'''
+import sys
+
+# Python 2.7
+
+# Note: Could use the pypi mock library on python3.x as well as python2.x. It
+# is the same as the python3 stdlib mock library
+
+try:
+ # Allow wildcard import because we really do want to import all of mock's
+ # symbols into this compat shim
+ # pylint: disable=wildcard-import,unused-wildcard-import
+ from unittest.mock import *
+except ImportError:
+ # Python 2
+ # pylint: disable=wildcard-import,unused-wildcard-import
+ try:
+ from mock import *
+ except ImportError:
+ print('You need the mock library installed on python2.x to run tests')
+
+
+# Prior to 3.4.4, mock_open cannot handle binary read_data
+if sys.version_info >= (3,) and sys.version_info < (3, 4, 4):
+ file_spec = None
+
+ def _iterate_read_data(read_data):
+ # Helper for mock_open:
+ # Retrieve lines from read_data via a generator so that separate calls to
+ # readline, read, and readlines are properly interleaved
+ sep = b'\n' if isinstance(read_data, bytes) else '\n'
+ data_as_list = [l + sep for l in read_data.split(sep)]
+
+ if data_as_list[-1] == sep:
+ # If the last line ended in a newline, the list comprehension will have an
+ # extra entry that's just a newline. Remove this.
+ data_as_list = data_as_list[:-1]
+ else:
+ # If there wasn't an extra newline by itself, then the file being
+ # emulated doesn't have a newline to end the last line remove the
+ # newline that our naive format() added
+ data_as_list[-1] = data_as_list[-1][:-1]
+
+ for line in data_as_list:
+ yield line
+
+ def mock_open(mock=None, read_data=''):
+ """
+ A helper function to create a mock to replace the use of `open`. It works
+ for `open` called directly or used as a context manager.
+
+ The `mock` argument is the mock object to configure. If `None` (the
+ default) then a `MagicMock` will be created for you, with the API limited
+ to methods or attributes available on standard file handles.
+
+ `read_data` is a string for the `read` methoddline`, and `readlines` of the
+ file handle to return. This is an empty string by default.
+ """
+ def _readlines_side_effect(*args, **kwargs):
+ if handle.readlines.return_value is not None:
+ return handle.readlines.return_value
+ return list(_data)
+
+ def _read_side_effect(*args, **kwargs):
+ if handle.read.return_value is not None:
+ return handle.read.return_value
+ return type(read_data)().join(_data)
+
+ def _readline_side_effect():
+ if handle.readline.return_value is not None:
+ while True:
+ yield handle.readline.return_value
+ for line in _data:
+ yield line
+
+ global file_spec
+ if file_spec is None:
+ import _io
+ file_spec = list(set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO))))
+
+ if mock is None:
+ mock = MagicMock(name='open', spec=open)
+
+ handle = MagicMock(spec=file_spec)
+ handle.__enter__.return_value = handle
+
+ _data = _iterate_read_data(read_data)
+
+ handle.write.return_value = None
+ handle.read.return_value = None
+ handle.readline.return_value = None
+ handle.readlines.return_value = None
+
+ handle.read.side_effect = _read_side_effect
+ handle.readline.side_effect = _readline_side_effect()
+ handle.readlines.side_effect = _readlines_side_effect
+
+ mock.return_value = handle
+ return mock
diff --git a/ansible_collections/netapp/aws/tests/unit/compat/unittest.py b/ansible_collections/netapp/aws/tests/unit/compat/unittest.py
new file mode 100644
index 000000000..73a20cf8c
--- /dev/null
+++ b/ansible_collections/netapp/aws/tests/unit/compat/unittest.py
@@ -0,0 +1,44 @@
+# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+'''
+Compat module for Python2.7's unittest module
+'''
+
+import sys
+
+import pytest
+
+# Allow wildcard import because we really do want to import all of
+# unittests's symbols into this compat shim
+# pylint: disable=wildcard-import,unused-wildcard-import
+if sys.version_info < (2, 7):
+ try:
+ # Need unittest2 on python2.6
+ from unittest2 import *
+ except ImportError:
+ print('You need unittest2 installed on python2.6.x to run tests')
+
+ class TestCase:
+ """ skip everything """
+ pytestmark = pytest.mark.skip('Skipping Unit Tests on 2.6 as unittest2 may not be available')
+else:
+ from unittest import *
diff --git a/ansible_collections/netapp/aws/tests/unit/plugins/module_utils/test_netapp.py b/ansible_collections/netapp/aws/tests/unit/plugins/module_utils/test_netapp.py
new file mode 100644
index 000000000..2fb3b7ba0
--- /dev/null
+++ b/ansible_collections/netapp/aws/tests/unit/plugins/module_utils/test_netapp.py
@@ -0,0 +1,195 @@
+# Copyright (c) 2018 NetApp
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+''' unit tests for module_utils netapp.py '''
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import json
+import os.path
+import sys
+import tempfile
+
+import pytest
+
+from ansible.module_utils import basic
+from ansible.module_utils._text import to_bytes
+from ansible_collections.netapp.aws.tests.unit.compat.mock import patch
+
+import ansible_collections.netapp.aws.plugins.module_utils.netapp as netapp_utils
+
+
+if not netapp_utils.HAS_REQUESTS and sys.version_info < (2, 7):
+ pytestmark = pytest.mark.skip('Skipping Unit Tests on 2.6 as requests is not be available')
+
+
+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 AnsibleFailJson(Exception):
+ """Exception class to be raised by module.fail_json and caught by the test case"""
+
+
+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)
+
+
+SRR = {
+ 'empty_good': (dict(), None),
+ 'get_data': (dict(records=['data1', 'data2']), None),
+ 'end_of_sequence': (None, "Unexpected call to send_request"),
+ 'generic_error': (None, "Expected error"),
+}
+
+
+def mock_args(feature_flags=None):
+ args = {
+ 'api_key': 'api_key',
+ 'api_url': 'api_url',
+ 'secret_key': 'secret_key!',
+ }
+ if feature_flags is not None:
+ args.update({'feature_flags': feature_flags})
+ return args
+
+
+def create_module(args):
+ argument_spec = netapp_utils.aws_cvs_host_argument_spec()
+ set_module_args(args)
+ module = basic.AnsibleModule(argument_spec)
+ return module
+
+
+def create_restapi_object(args):
+ module = create_module(args)
+ module.fail_json = fail_json
+ rest_api = netapp_utils.AwsCvsRestAPI(module)
+ return rest_api
+
+
+class mockResponse:
+ def __init__(self, json_data, status_code, raise_action=None):
+ self.json_data = json_data
+ self.status_code = status_code
+ self.content = json_data
+ self.raise_action = raise_action
+
+ def raise_for_status(self):
+ pass
+
+ def json(self):
+ if self.raise_action == 'bad_json':
+ raise ValueError(self.raise_action)
+ return self.json_data
+
+
+@patch('ansible_collections.netapp.aws.plugins.module_utils.netapp.AwsCvsRestAPI.send_request')
+def test_empty_get(mock_request):
+ ''' get with no data '''
+ mock_request.side_effect = [
+ SRR['empty_good'],
+ SRR['end_of_sequence'],
+ ]
+ rest_api = create_restapi_object(mock_args())
+ message, error = rest_api.get('api', None)
+ assert not error
+ assert len(message) == 0
+
+
+@patch('ansible_collections.netapp.aws.plugins.module_utils.netapp.AwsCvsRestAPI.send_request')
+def test_get_data(mock_request):
+ ''' get with data '''
+ mock_request.side_effect = [
+ SRR['get_data'],
+ SRR['end_of_sequence'],
+ ]
+ rest_api = create_restapi_object(mock_args())
+ message, error = rest_api.get('api', None)
+ assert not error
+ print('get:', message)
+ assert message['records'] == SRR['get_data'][0]['records']
+
+
+def test_has_feature_success_default_0():
+ ''' existing feature_flag with default of False'''
+ flag = 'trace_apis'
+ module = create_module(mock_args())
+ value = netapp_utils.has_feature(module, flag)
+ assert not value
+
+
+def test_has_feature_success_default_1():
+ ''' existing feature_flag with default of True'''
+ flag = 'strict_json_check'
+ module = create_module(mock_args())
+ value = netapp_utils.has_feature(module, flag)
+ assert value
+
+
+def test_has_feature_success_user_true():
+ ''' existing feature_flag with value set to True '''
+ flag = 'user_deprecation_warning'
+ args = dict(mock_args({flag: True}))
+ module = create_module(args)
+ value = netapp_utils.has_feature(module, flag)
+ assert value
+
+
+def test_has_feature_success_user_false():
+ ''' existing feature_flag with value set to False '''
+ flag = 'user_deprecation_warning'
+ args = dict(mock_args({flag: False}))
+ print(args)
+ module = create_module(args)
+ value = netapp_utils.has_feature(module, flag)
+ assert not value
+
+
+def test_has_feature_invalid_key():
+ ''' existing feature_flag with unknown key '''
+ flag = 'deprecation_warning_bad_key'
+ module = create_module(mock_args())
+ # replace ANsible fail method with ours
+ module.fail_json = fail_json
+ with pytest.raises(AnsibleFailJson) as exc:
+ netapp_utils.has_feature(module, flag)
+ msg = 'Internal error: unexpected feature flag: %s' % flag
+ assert exc.value.args[0]['msg'] == msg
+
+
+@patch('requests.request')
+def test_empty_get_sent(mock_request):
+ ''' get with no data '''
+ mock_request.return_value = mockResponse(json_data=dict(_links='me'), status_code=200)
+ rest_api = create_restapi_object(mock_args())
+ message, error = rest_api.get('api', None)
+ assert not error
+ # only one key (_links)
+ assert len(message) == 1
+
+
+@patch('requests.request')
+def test_empty_get_sent_bad_json(mock_request):
+ ''' get with no data '''
+ mock_request.return_value = mockResponse(json_data='anything', status_code=200, raise_action='bad_json')
+ rest_api = create_restapi_object(mock_args())
+ message, error = rest_api.get('api', None)
+ assert error
+ assert 'Expecting json, got: anything' in error
+ print('errors:', rest_api.errors)
+ print('debug:', rest_api.debug_logs)
+
+
+@patch('requests.request')
+def test_empty_get_sent_bad_but_empty_json(mock_request):
+ ''' get with no data '''
+ mock_request.return_value = mockResponse(json_data='', status_code=200, raise_action='bad_json')
+ rest_api = create_restapi_object(mock_args())
+ message, error = rest_api.get('api', None)
+ assert error is None
+ assert message is None
diff --git a/ansible_collections/netapp/aws/tests/unit/plugins/modules/test_aws_netapp_cvs_active_directory.py b/ansible_collections/netapp/aws/tests/unit/plugins/modules/test_aws_netapp_cvs_active_directory.py
new file mode 100644
index 000000000..98755b939
--- /dev/null
+++ b/ansible_collections/netapp/aws/tests/unit/plugins/modules/test_aws_netapp_cvs_active_directory.py
@@ -0,0 +1,117 @@
+# (c) 2019, 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: '''
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+import json
+import pytest
+import sys
+
+from ansible.module_utils import basic
+from ansible.module_utils._text import to_bytes
+from ansible_collections.netapp.aws.tests.unit.compat import unittest
+from ansible_collections.netapp.aws.tests.unit.compat.mock import patch
+import ansible_collections.netapp.aws.plugins.module_utils.netapp as netapp_utils
+
+from ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_active_directory \
+ import AwsCvsNetappActiveDir as ad_module
+
+
+if not netapp_utils.HAS_REQUESTS and sys.version_info < (2, 7):
+ pytestmark = pytest.mark.skip('Skipping Unit Tests on 2.6 as requests is not be available')
+
+
+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"""
+
+
+class AnsibleFailJson(Exception):
+ """Exception class to be raised by module.fail_json and caught by the test case"""
+
+
+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 set_default_args_fail_check(self):
+ return dict({
+ 'state': 'present',
+ 'DNS': '101.102.103.123',
+ 'domain': 'mydomain.com',
+ 'password': 'netapp1!',
+ 'username': 'myuser',
+ 'api_url': 'myapiurl.com',
+ 'secret_key': 'mysecretkey',
+ 'api_key': 'myapikey'
+ })
+
+ def set_default_args_pass_check(self):
+ return dict({
+ 'state': 'present',
+ 'DNS': '101.102.103.123',
+ 'domain': 'mydomain.com',
+ 'password': 'netapp1!',
+ 'region': 'us-east-1',
+ 'netBIOS': 'testing',
+ 'username': 'myuser',
+ 'api_url': 'myapiurl.com',
+ 'secret_key': 'mysecretkey',
+ 'api_key': 'myapikey'
+ })
+
+ 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.set_default_args_fail_check())
+ ad_module()
+ print('Info: %s' % exc.value.args[0]['msg'])
+
+ def test_module_fail_when_required_args_present(self):
+ ''' required arguments are reported as errors '''
+ with pytest.raises(AnsibleExitJson) as exc:
+ set_module_args(self.set_default_args_pass_check())
+ ad_module()
+ exit_json(changed=True, msg="TestCase Fail when required ars are present")
+ assert exc.value.args[0]['changed']
+
+ @patch('ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_active_directory.AwsCvsNetappActiveDir.get_activedirectory_id')
+ @patch('ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_active_directory.AwsCvsNetappActiveDir.get_activedirectory')
+ @patch('ansible_collections.netapp.aws.plugins.module_utils.netapp.AwsCvsRestAPI.post')
+ def test_create_aws_netapp_cvs_activedir(self, get_post_api, get_aws_api, get_ad_id):
+ set_module_args(self.set_default_args_pass_check())
+ my_obj = ad_module()
+
+ get_aws_api.return_value = None
+ get_post_api.return_value = None, None
+ get_ad_id.return_value = "123"
+ with pytest.raises(AnsibleExitJson) as exc:
+ my_obj.apply()
+ print('Info: test_create_aws_netapp_cvs_active_directory: %s' % repr(exc.value))
+ assert exc.value.args[0]['changed']
diff --git a/ansible_collections/netapp/aws/tests/unit/plugins/modules/test_aws_netapp_cvs_filesystems.py b/ansible_collections/netapp/aws/tests/unit/plugins/modules/test_aws_netapp_cvs_filesystems.py
new file mode 100644
index 000000000..b5a4bad84
--- /dev/null
+++ b/ansible_collections/netapp/aws/tests/unit/plugins/modules/test_aws_netapp_cvs_filesystems.py
@@ -0,0 +1,155 @@
+# (c) 2019, NetApp, Inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+''' unit tests AWS CVS FileSystems Ansible module: aws_netapp_cvs_filesystems'''
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import json
+import pytest
+import sys
+
+from ansible.module_utils import basic
+from ansible.module_utils._text import to_bytes
+from ansible_collections.netapp.aws.tests.unit.compat import unittest
+from ansible_collections.netapp.aws.tests.unit.compat.mock import patch
+import ansible_collections.netapp.aws.plugins.module_utils.netapp as netapp_utils
+
+from ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_filesystems \
+ import AwsCvsNetappFileSystem as fileSystem_module
+
+
+if not netapp_utils.HAS_REQUESTS and sys.version_info < (2, 7):
+ pytestmark = pytest.mark.skip('Skipping Unit Tests on 2.6 as requests is not be available')
+
+
+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"""
+
+
+class AnsibleFailJson(Exception):
+ """Exception class to be raised by module.fail_json and caught by the test case"""
+
+
+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 set_default_args_fail_check(self):
+ return dict({
+ 'creationToken': 'TestFilesystem',
+ 'region': 'us-east-1',
+ 'quotaInBytes': 3424,
+ 'serviceLevel': 'standard',
+ 'api_url': 'hostname.com',
+ 'api_key': 'myapikey',
+ 'secret_key': 'mysecretkey'
+ })
+
+ def set_default_args_pass_check(self):
+ return dict({
+ 'state': 'present',
+ 'creationToken': 'TestFilesystem',
+ 'region': 'us-east-1',
+ 'quotaInBytes': 3424,
+ 'serviceLevel': 'standard',
+ 'api_url': 'hostname.com',
+ 'api_key': 'myapikey',
+ 'secret_key': 'mysecretkey'
+ })
+
+ def set_args_create_aws_netapp_cvs_filesystems(self):
+ return dict({
+ 'state': 'present',
+ 'creationToken': 'TestFilesystem',
+ 'region': 'us-east-1',
+ 'quotaInBytes': 3424,
+ 'serviceLevel': 'standard',
+ 'api_url': 'hostname.com',
+ 'api_key': 'myapikey',
+ 'secret_key': 'mysecretkey'
+ })
+
+ def set_args_delete_aws_netapp_cvs_filesystems(self):
+ return dict({
+ 'state': 'absent',
+ 'creationToken': 'TestFilesystem',
+ 'region': 'us-east-1',
+ 'api_url': 'hostname.com',
+ 'api_key': 'myapikey',
+ 'secret_key': 'mysecretkey'
+ })
+
+ 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.set_default_args_fail_check())
+ fileSystem_module()
+ print('Info: test_module_fail_when_required_args_missing: %s' % exc.value.args[0]['msg'])
+
+ def test_module_fail_when_required_args_present(self):
+ ''' required arguments are reported as errors '''
+ with pytest.raises(AnsibleExitJson) as exc:
+ set_module_args(self.set_default_args_pass_check())
+ fileSystem_module()
+ exit_json(changed=True, msg="Induced arguments check")
+ print('Info: test_module_fail_when_required_args_present: %s' % exc.value.args[0]['msg'])
+ assert exc.value.args[0]['changed']
+
+ @patch('ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_filesystems.AwsCvsNetappFileSystem.get_filesystem_id')
+ @patch('ansible_collections.netapp.aws.plugins.module_utils.netapp.AwsCvsRestAPI.get_state')
+ @patch('ansible_collections.netapp.aws.plugins.module_utils.netapp.AwsCvsRestAPI.post')
+ def test_create_aws_netapp_cvs_snapshots_pass(self, get_post_api, get_state_api, get_filesystem_id):
+ set_module_args(self.set_args_create_aws_netapp_cvs_filesystems())
+ my_obj = fileSystem_module()
+ get_filesystem_id.return_value = None
+ get_state_api.return_value = 'done'
+ response = {'jobs': [{'jobId': 'dummy'}]}
+ get_post_api.return_value = response, None
+ with pytest.raises(AnsibleExitJson) as exc:
+ my_obj.apply()
+ print('Info: test_create_aws_netapp_cvs_filesystem_pass: %s' % repr(exc.value.args[0]))
+ assert exc.value.args[0]['changed']
+
+ @patch('ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_filesystems.AwsCvsNetappFileSystem.get_filesystem_id')
+ @patch('ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_filesystems.AwsCvsNetappFileSystem.get_filesystem')
+ @patch('ansible_collections.netapp.aws.plugins.module_utils.netapp.AwsCvsRestAPI.get_state')
+ @patch('ansible_collections.netapp.aws.plugins.module_utils.netapp.AwsCvsRestAPI.delete')
+ def test_delete_aws_netapp_cvs_snapshots_pass(self, get_post_api, get_state_api, get_filesystem, get_filesystem_id):
+ set_module_args(self.set_args_delete_aws_netapp_cvs_filesystems())
+ my_obj = fileSystem_module()
+ get_filesystem_id.return_value = '432-432-532423-4232'
+ get_filesystem.return_value = 'dummy'
+ get_state_api.return_value = 'done'
+ response = {'jobs': [{'jobId': 'dummy'}]}
+ get_post_api.return_value = response, None
+ with pytest.raises(AnsibleExitJson) as exc:
+ my_obj.apply()
+ print('Info: test_create_aws_netapp_cvs_filesyste_pass: %s' % repr(exc.value.args[0]))
+ assert exc.value.args[0]['changed']
diff --git a/ansible_collections/netapp/aws/tests/unit/plugins/modules/test_aws_netapp_cvs_pool.py b/ansible_collections/netapp/aws/tests/unit/plugins/modules/test_aws_netapp_cvs_pool.py
new file mode 100644
index 000000000..26e822de7
--- /dev/null
+++ b/ansible_collections/netapp/aws/tests/unit/plugins/modules/test_aws_netapp_cvs_pool.py
@@ -0,0 +1,258 @@
+# (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 AWS Cloud Volumes Services - Manage Pools '''
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+import json
+import pytest
+import sys
+
+from ansible.module_utils import basic
+from ansible.module_utils._text import to_bytes
+from ansible_collections.netapp.aws.tests.unit.compat import unittest
+from ansible_collections.netapp.aws.tests.unit.compat.mock import patch
+import ansible_collections.netapp.aws.plugins.module_utils.netapp as netapp_utils
+
+from ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_pool \
+ import NetAppAWSCVS as pool_module
+
+
+if not netapp_utils.HAS_REQUESTS and sys.version_info < (2, 7):
+ pytestmark = pytest.mark.skip('Skipping Unit Tests on 2.6 as requests is not be available')
+
+
+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"""
+
+
+class AnsibleFailJson(Exception):
+ """Exception class to be raised by module.fail_json and caught by the test case"""
+
+
+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 set_default_args_fail_check(self):
+ return dict({
+ 'from_name': 'TestPoolAA',
+ 'name': 'TestPoolAA_new',
+ 'serviceLevel': 'standard',
+ 'sizeInBytes': 4000000000000,
+ 'vendorID': 'ansiblePoolTestVendorA',
+ 'region': 'us-east-1',
+ 'api_url': 'hostname.invalid',
+ 'api_key': 'myapikey',
+ 'secret_key': 'mysecretkey'
+ })
+
+ def set_default_args_pass_check(self):
+ return dict({
+ 'state': 'present',
+ 'from_name': 'TestPoolAA',
+ 'name': 'TestPoolAA_new',
+ 'serviceLevel': 'standard',
+ 'sizeInBytes': 4000000000000,
+ 'vendorID': 'ansiblePoolTestVendorA',
+ 'region': 'us-east-1',
+ 'api_url': 'hostname.invalid',
+ 'api_key': 'myapikey',
+ 'secret_key': 'mysecretkey'
+ })
+
+ def set_args_create_aws_netapp_cvs_pool(self):
+ return dict({
+ 'state': 'present',
+ 'name': 'TestPoolAA',
+ 'serviceLevel': 'standard',
+ 'sizeInBytes': 4000000000000,
+ 'vendorID': 'ansiblePoolTestVendorA',
+ 'region': 'us-east-1',
+ 'api_url': 'hostname.invalid',
+ 'api_key': 'myapikey',
+ 'secret_key': 'mysecretkey'
+ })
+
+ def set_args_update_aws_netapp_cvs_pool(self):
+ return dict({
+ 'state': 'present',
+ 'from_name': 'TestPoolAA',
+ 'name': 'TestPoolAA_new',
+ 'serviceLevel': 'standard',
+ 'sizeInBytes': 4000000000000,
+ 'vendorID': 'ansiblePoolTestVendorA',
+ 'region': 'us-east-1',
+ 'api_url': 'hostname.invalid',
+ 'api_key': 'myapikey',
+ 'secret_key': 'mysecretkey'
+ })
+
+ def set_args_delete_aws_netapp_cvs_pool(self):
+ return dict({
+ 'state': 'absent',
+ 'name': 'TestPoolAA',
+ 'region': 'us-east-1',
+ 'api_url': 'hostname.invalid',
+ 'api_key': 'myapikey',
+ 'secret_key': 'mysecretkey'
+ })
+
+ 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.set_default_args_fail_check())
+ pool_module()
+ print('Info: test_module_fail_when_required_args_missing: %s' % exc.value.args[0]['msg'])
+
+ def test_module_pass_when_required_args_present(self):
+ ''' required arguments are present '''
+ with pytest.raises(AnsibleExitJson) as exc:
+ set_module_args(self.set_default_args_pass_check())
+ pool_module()
+ exit_json(changed=True, msg="Induced arguments check")
+ print('Info: test_module_pass_when_required_args_present: %s' % exc.value.args[0]['msg'])
+ assert exc.value.args[0]['changed']
+
+ @patch('ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_pool.NetAppAWSCVS.get_aws_netapp_cvs_pool')
+ @patch('ansible_collections.netapp.aws.plugins.module_utils.netapp.AwsCvsRestAPI.put')
+ def test_update_aws_netapp_cvs_pool_pass(self, get_put_api, get_aws_api):
+ set_module_args(self.set_args_update_aws_netapp_cvs_pool())
+ my_obj = pool_module()
+ my_pool = {
+ "name": "Dummyname",
+ "poolId": "1f63b3d0-4fd4-b4fe-1ed6-c62f5f20d975",
+ "region": "us-east-1",
+ "serviceLevel": "extreme",
+ "sizeInBytes": 40000000000000000,
+ "state": "available",
+ "vendorID": "Dummy"
+ }
+ get_aws_api.return_value = my_pool
+ get_put_api.return_value = my_pool, None
+ with pytest.raises(AnsibleExitJson) as exc:
+ my_obj.apply()
+ print('Info: test_update_aws_netapp_cvs_pool_pass: %s' % repr(exc.value))
+ assert exc.value.args[0]['changed']
+
+ @patch('ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_pool.NetAppAWSCVS.get_aws_netapp_cvs_pool')
+ @patch('ansible_collections.netapp.aws.plugins.module_utils.netapp.AwsCvsRestAPI.put')
+ def test_update_aws_netapp_cvs_pool_fail(self, get_put_api, get_aws_api):
+ set_module_args(self.set_args_update_aws_netapp_cvs_pool())
+ my_obj = pool_module()
+ my_pool = {
+ "name": "Dummyname",
+ "poolId": "1f63b3d0-4fd4-b4fe-1ed6-c62f5f20d975",
+ "region": "us-east-1",
+ "serviceLevel": "extreme",
+ "sizeInBytes": 40000000000000000,
+ "state": "available",
+ "vendorID": "Dummy"
+ }
+ get_put_api.return_value = my_pool, "Error"
+ get_aws_api.return_value = my_pool
+ with pytest.raises(AnsibleFailJson) as exc:
+ my_obj.apply()
+ print('Info: test_update_aws_netapp_cvs_pool_fail: %s' % repr(exc.value))
+ assert exc.value.args[0]['msg'] is not None
+
+ @patch('ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_pool.NetAppAWSCVS.get_aws_netapp_cvs_pool')
+ @patch('ansible_collections.netapp.aws.plugins.module_utils.netapp.AwsCvsRestAPI.post')
+ def test_create_aws_netapp_cvs_pool_pass(self, get_post_api, get_aws_api):
+ set_module_args(self.set_args_create_aws_netapp_cvs_pool())
+ my_obj = pool_module()
+ get_aws_api.return_value = None
+ get_post_api.return_value = None, None
+ with pytest.raises(AnsibleExitJson) as exc:
+ my_obj.apply()
+ print('Info: test_create_aws_netapp_cvs_pool_pass: %s' % repr(exc.value))
+ assert exc.value.args[0]['changed']
+
+ @patch('ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_pool.NetAppAWSCVS.get_aws_netapp_cvs_pool')
+ @patch('ansible_collections.netapp.aws.plugins.module_utils.netapp.AwsCvsRestAPI.post')
+ def test_create_aws_netapp_cvs_pool_fail(self, get_post_api, get_aws_api):
+ set_module_args(self.set_args_create_aws_netapp_cvs_pool())
+ my_obj = pool_module()
+ my_pool = {
+ "name": "Dummyname",
+ "poolId": "1f63b3d0-4fd4-b4fe-1ed6-c62f5f20d975",
+ "region": "us-east-1",
+ "serviceLevel": "extreme",
+ "sizeInBytes": 40000000000000000,
+ "state": "available",
+ "vendorID": "Dummy"
+ }
+ get_post_api.return_value = my_pool, "Error"
+ get_aws_api.return_value = None
+ with pytest.raises(AnsibleFailJson) as exc:
+ my_obj.apply()
+ print('Info: test_create_aws_netapp_cvs_pool_fail: %s' % repr(exc.value))
+ assert exc.value.args[0]['msg'] is not None
+
+ @patch('ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_pool.NetAppAWSCVS.get_aws_netapp_cvs_pool')
+ @patch('ansible_collections.netapp.aws.plugins.module_utils.netapp.AwsCvsRestAPI.delete')
+ def test_delete_aws_netapp_cvs_pool_pass(self, get_delete_api, get_aws_api):
+ set_module_args(self.set_args_delete_aws_netapp_cvs_pool())
+ my_obj = pool_module()
+ my_pool = {
+ "name": "Dummyname",
+ "poolId": "1f63b3d0-4fd4-b4fe-1ed6-c62f5f20d975",
+ "region": "us-east-1",
+ "serviceLevel": "extreme",
+ "sizeInBytes": 40000000000000000,
+ "state": "available",
+ "vendorID": "Dummy"
+ }
+ get_aws_api.return_value = my_pool
+ get_delete_api.return_value = None, None
+ with pytest.raises(AnsibleExitJson) as exc:
+ my_obj.apply()
+ print('Info: test_delete_aws_netapp_cvs_pool_pass: %s' % repr(exc.value))
+ assert exc.value.args[0]['changed']
+
+ @patch('ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_pool.NetAppAWSCVS.get_aws_netapp_cvs_pool')
+ @patch('ansible_collections.netapp.aws.plugins.module_utils.netapp.AwsCvsRestAPI.delete')
+ def test_delete_aws_netapp_cvs_pool_fail(self, get_delete_api, get_aws_api):
+ set_module_args(self.set_args_delete_aws_netapp_cvs_pool())
+ my_obj = pool_module()
+ my_pool = {
+ "name": "Dummyname",
+ "poolId": "1f63b3d0-4fd4-b4fe-1ed6-c62f5f20d975",
+ "region": "us-east-1",
+ "serviceLevel": "extreme",
+ "sizeInBytes": 40000000000000000,
+ "state": "available",
+ "vendorID": "Dummy"
+ }
+ get_delete_api.return_value = my_pool, "Error"
+ get_aws_api.return_value = my_pool
+ with pytest.raises(AnsibleFailJson) as exc:
+ my_obj.apply()
+ print('Info: test_delete_aws_netapp_cvs_pool_fail: %s' % repr(exc.value))
+ assert exc.value.args[0]['msg'] is not None
diff --git a/ansible_collections/netapp/aws/tests/unit/plugins/modules/test_aws_netapp_cvs_snapshots.py b/ansible_collections/netapp/aws/tests/unit/plugins/modules/test_aws_netapp_cvs_snapshots.py
new file mode 100644
index 000000000..bb825a2ee
--- /dev/null
+++ b/ansible_collections/netapp/aws/tests/unit/plugins/modules/test_aws_netapp_cvs_snapshots.py
@@ -0,0 +1,147 @@
+# (c) 2019, NetApp, Inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+''' unit tests NetApp AWS CVS Snapshots Ansible module: aws_netapp_cvs_snapshots'''
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+import json
+import pytest
+import sys
+
+from ansible.module_utils import basic
+from ansible.module_utils._text import to_bytes
+from ansible_collections.netapp.aws.tests.unit.compat import unittest
+from ansible_collections.netapp.aws.tests.unit.compat.mock import patch
+import ansible_collections.netapp.aws.plugins.module_utils.netapp as netapp_utils
+
+from ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_snapshots \
+ import AwsCvsNetappSnapshot as snapshot_module
+
+
+if not netapp_utils.HAS_REQUESTS and sys.version_info < (2, 7):
+ pytestmark = pytest.mark.skip('Skipping Unit Tests on 2.6 as requests is not be available')
+
+
+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"""
+
+
+class AnsibleFailJson(Exception):
+ """Exception class to be raised by module.fail_json and caught by the test case"""
+
+
+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 set_default_args_fail_check(self):
+ return dict({
+ 'name': 'TestFilesystem',
+ 'fileSystemId': 'standard',
+ 'from_name': 'from_TestFilesystem',
+ 'region': 'us-east-1',
+ 'api_url': 'hostname.com',
+ 'api_key': 'myapikey',
+ 'secret_key': 'mysecretkey'
+ })
+
+ def set_default_args_pass_check(self):
+ return dict({
+ 'state': 'present',
+ 'name': 'testSnapshot',
+ 'fileSystemId': 'standard',
+ 'from_name': 'from_TestFilesystem',
+ 'region': 'us-east-1',
+ 'api_url': 'hostname.com',
+ 'api_key': 'myapikey',
+ 'secret_key': 'mysecretkey'
+ })
+
+ def set_args_create_aws_netapp_cvs_snapshots(self):
+ return dict({
+ 'state': 'present',
+ 'name': 'testSnapshot',
+ 'fileSystemId': '123-4213-432-432',
+ 'region': 'us-east-1',
+ 'api_url': 'hostname.com',
+ 'api_key': 'myapikey',
+ 'secret_key': 'mysecretkey'
+ })
+
+ def set_args_delete_aws_netapp_cvs_snapshots(self):
+ return dict({
+ 'state': 'absent',
+ 'name': 'testSnapshot',
+ 'region': 'us-east-1',
+ 'api_url': 'hostname.com',
+ 'api_key': 'myapikey',
+ 'secret_key': 'mysecretkey'
+ })
+
+ 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.set_default_args_fail_check())
+ snapshot_module()
+ print('Info: test_module_fail_when_required_args_missing: %s' % exc.value.args[0]['msg'])
+
+ def test_module_fail_when_required_args_present(self):
+ ''' required arguments are reported as errors '''
+ with pytest.raises(AnsibleExitJson) as exc:
+ set_module_args(self.set_default_args_pass_check())
+ snapshot_module()
+ exit_json(changed=True, msg="Induced arguments check")
+ print('Info: test_module_fail_when_required_args_present: %s' % exc.value.args[0]['msg'])
+ assert exc.value.args[0]['changed']
+
+ @patch('ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_snapshots.AwsCvsNetappSnapshot.get_snapshot_id')
+ @patch('ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_snapshots.AwsCvsNetappSnapshot.get_filesystem_id')
+ @patch('ansible_collections.netapp.aws.plugins.module_utils.netapp.AwsCvsRestAPI.post')
+ def test_create_aws_netapp_cvs_snapshots_pass(self, get_post_api, get_filesystem_id, get_snapshot_id):
+ set_module_args(self.set_args_create_aws_netapp_cvs_snapshots())
+ my_obj = snapshot_module()
+ get_filesystem_id.return_value = 'fiesystemName'
+ get_snapshot_id.return_value = None
+ get_post_api.return_value = None, None
+ with pytest.raises(AnsibleExitJson) as exc:
+ my_obj.apply()
+ print('Info: test_create_aws_netapp_cvs_snapshots_pass: %s' % repr(exc.value.args[0]))
+ assert exc.value.args[0]['changed']
+
+ @patch('ansible_collections.netapp.aws.plugins.modules.aws_netapp_cvs_snapshots.AwsCvsNetappSnapshot.get_snapshot_id')
+ @patch('ansible_collections.netapp.aws.plugins.module_utils.netapp.AwsCvsRestAPI.delete')
+ def test_delete_aws_netapp_cvs_snapshots_pass(self, get_post_api, get_snapshot_id):
+ set_module_args(self.set_args_delete_aws_netapp_cvs_snapshots())
+ my_obj = snapshot_module()
+ get_snapshot_id.return_value = "1f63b3d0-4fd4-b4fe-1ed6-c62f5f20d975"
+ get_post_api.return_value = None, None
+ with pytest.raises(AnsibleExitJson) as exc:
+ my_obj.apply()
+ print('Info: test_create_aws_netapp_cvs_snapshots_pass: %s' % repr(exc.value.args[0]))
+ assert exc.value.args[0]['changed']
diff --git a/ansible_collections/netapp/aws/tests/unit/requirements.txt b/ansible_collections/netapp/aws/tests/unit/requirements.txt
new file mode 100644
index 000000000..b754473a9
--- /dev/null
+++ b/ansible_collections/netapp/aws/tests/unit/requirements.txt
@@ -0,0 +1 @@
+requests ; python_version >= '2.7'