summaryrefslogtreecommitdiffstats
path: root/ansible_collections/netapp/um_info
diff options
context:
space:
mode:
Diffstat (limited to 'ansible_collections/netapp/um_info')
-rw-r--r--ansible_collections/netapp/um_info/.github/workflows/main.yml4
-rw-r--r--ansible_collections/netapp/um_info/FILES.json57
-rw-r--r--ansible_collections/netapp/um_info/MANIFEST.json4
-rw-r--r--ansible_collections/netapp/um_info/README.md3
-rw-r--r--ansible_collections/netapp/um_info/meta/execution-environment.yml3
-rw-r--r--ansible_collections/netapp/um_info/meta/runtime.yml2
-rw-r--r--ansible_collections/netapp/um_info/metadata-29PbAy.json14
-rw-r--r--ansible_collections/netapp/um_info/plugins/module_utils/netapp.py2
-rw-r--r--ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_aggregates.py159
-rw-r--r--ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_clusters.py159
-rw-r--r--ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_nodes.py158
-rw-r--r--ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_svms.py158
-rw-r--r--ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_volumes.py158
13 files changed, 871 insertions, 10 deletions
diff --git a/ansible_collections/netapp/um_info/.github/workflows/main.yml b/ansible_collections/netapp/um_info/.github/workflows/main.yml
index fbcf92002..9294078a2 100644
--- a/ansible_collections/netapp/um_info/.github/workflows/main.yml
+++ b/ansible_collections/netapp/um_info/.github/workflows/main.yml
@@ -17,6 +17,7 @@ jobs:
- stable-2.10
- stable-2.11
- stable-2.12
+ - stable-2.13
- devel
steps:
@@ -26,7 +27,8 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
with:
- python-version: 3.8
+ # Ansible 2.14 requires 3.9 as a minimum
+ python-version: 3.9
- name: Install ansible (${{ matrix.ansible }})
run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check
diff --git a/ansible_collections/netapp/um_info/FILES.json b/ansible_collections/netapp/um_info/FILES.json
index 0d45bda4d..769a883a4 100644
--- a/ansible_collections/netapp/um_info/FILES.json
+++ b/ansible_collections/netapp/um_info/FILES.json
@@ -46,7 +46,7 @@
"name": "plugins/module_utils/netapp.py",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "821070453abf1ec684677f43878fdd4ceb66bb30e40aeeb16b35aa71c0294249",
+ "chksum_sha256": "a255d934e0f25750f739d26bc124f7542db92b11385d5a3f350409ed6ae3fc2f",
"format": 1
},
{
@@ -232,6 +232,27 @@
"format": 1
},
{
+ "name": "tests/unit/plugins/modules/test_na_um_list_svms.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7933824403b197ec756f540be054a5e2c75b5a3a28cf60280cd11493f4c4b235",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/plugins/modules/test_na_um_list_aggregates.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ba3687cb122aa7452f21052b5a6f26448df8356e92e4b78c20cce55c66ea3026",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/plugins/modules/test_na_um_list_clusters.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "11f9aa85947d440b6a647a2cc6be1cf16d93d69b08ed288a33fa8168836d2521",
+ "format": 1
+ },
+ {
"name": "tests/unit/plugins/modules/test_na_um_nodes_info.py",
"ftype": "file",
"chksum_type": "sha256",
@@ -246,6 +267,13 @@
"format": 1
},
{
+ "name": "tests/unit/plugins/modules/test_na_um_list_volumes.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b8a2d4ca0f304a588de4d642da415362f3b15b2926fa12a90117b58b9f71d6d9",
+ "format": 1
+ },
+ {
"name": "tests/unit/plugins/modules/test_na_um_svms_info.py",
"ftype": "file",
"chksum_type": "sha256",
@@ -253,6 +281,13 @@
"format": 1
},
{
+ "name": "tests/unit/plugins/modules/test_na_um_list_nodes.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "cf4ded8134d30ed7b82769252addf2094d07b6bf3ec81e7aba0615b290558cfb",
+ "format": 1
+ },
+ {
"name": "meta",
"ftype": "dir",
"chksum_type": null,
@@ -260,10 +295,17 @@
"format": 1
},
{
+ "name": "meta/execution-environment.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "db75f5fcae43fd2db36d3c9a004748dd1ec4165a6e2ebb36ada6943a8b440f4a",
+ "format": 1
+ },
+ {
"name": "meta/runtime.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "88d46a475f366fffbd8ec430a85972ed1aa180268564bd88434cceaaaf13712c",
+ "chksum_sha256": "2fe9f7286aadaf2d0c4dbd2a0f118f155f564496bbc1bc742478ef7e8ece8269",
"format": 1
},
{
@@ -347,7 +389,7 @@
"name": "README.md",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "ae574e5d7e3e4d82a855ed53b06c34a26134d7a9d50e023bf2408b51e0f8a679",
+ "chksum_sha256": "69664a93902d708863a70abc626b771889dce8cd6682efc449bb01a0efcc9dca",
"format": 1
},
{
@@ -358,6 +400,13 @@
"format": 1
},
{
+ "name": "metadata-29PbAy.json",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "424c5b110233e003275aaa5d6886c892f39c23b72a69bbf72e9a3172933691a6",
+ "format": 1
+ },
+ {
"name": ".github",
"ftype": "dir",
"chksum_type": null,
@@ -382,7 +431,7 @@
"name": ".github/workflows/main.yml",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "fa99709b97a6f722ae1a51afaf32ad66aa2d1306b708b8b9c8d723be715ca4c4",
+ "chksum_sha256": "e7781e9cc514eb5cb80bbee9a821af8661cbd39542ddfe6aa59e811afbabdf13",
"format": 1
},
{
diff --git a/ansible_collections/netapp/um_info/MANIFEST.json b/ansible_collections/netapp/um_info/MANIFEST.json
index 40b3df1ae..5683ca1df 100644
--- a/ansible_collections/netapp/um_info/MANIFEST.json
+++ b/ansible_collections/netapp/um_info/MANIFEST.json
@@ -2,7 +2,7 @@
"collection_info": {
"namespace": "netapp",
"name": "um_info",
- "version": "21.8.0",
+ "version": "21.8.1",
"authors": [
"NetApp Ansible Team <ng-ansibleteam@netapp.com>"
],
@@ -27,7 +27,7 @@
"name": "FILES.json",
"ftype": "file",
"chksum_type": "sha256",
- "chksum_sha256": "cb6c57414d2dfe99a63f715ea33254ca1d6cd458b50fa0cbae778ea41b14ef2c",
+ "chksum_sha256": "e33360247a1805f8191170f1cba1aa27a57e3abac652d447b398169adb14a626",
"format": 1
},
"format": 1
diff --git a/ansible_collections/netapp/um_info/README.md b/ansible_collections/netapp/um_info/README.md
index 193bbab59..c1ad29008 100644
--- a/ansible_collections/netapp/um_info/README.md
+++ b/ansible_collections/netapp/um_info/README.md
@@ -1,6 +1,7 @@
[![Documentation](https://img.shields.io/badge/docs-brightgreen.svg)](https://docs.ansible.com/ansible/devel/collections/netapp/um_info/index.html)
![example workflow](https://github.com/ansible-collections/netapp.um_info/actions/workflows/main.yml/badge.svg)
[![codecov](https://codecov.io/gh/ansible-collections/netapp.um_info/branch/main/graph/badge.svg?token=weBYkksxSi)](https://codecov.io/gh/ansible-collections/netapp.um_info)
+[![Discord](https://img.shields.io/discord/855068651522490400)](https://discord.gg/NetApp)
=============================================================
@@ -30,7 +31,7 @@ https://docs.ansible.com/ansible/devel/collections/netapp/um_info/
This collection follows the [Ansible project's Code of Conduct](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html).
# Need help
-Join our Slack Channel at [Netapp.io](http://netapp.io/slack)
+Join our [Discord](https://discord.gg/NetApp)
# Release Notes
diff --git a/ansible_collections/netapp/um_info/meta/execution-environment.yml b/ansible_collections/netapp/um_info/meta/execution-environment.yml
new file mode 100644
index 000000000..315d71a13
--- /dev/null
+++ b/ansible_collections/netapp/um_info/meta/execution-environment.yml
@@ -0,0 +1,3 @@
+version: 1
+dependencies:
+ python: ../requirements.txt
diff --git a/ansible_collections/netapp/um_info/meta/runtime.yml b/ansible_collections/netapp/um_info/meta/runtime.yml
index 04c66ffeb..cc45f44f7 100644
--- a/ansible_collections/netapp/um_info/meta/runtime.yml
+++ b/ansible_collections/netapp/um_info/meta/runtime.yml
@@ -1,5 +1,5 @@
---
-requires_ansible: ">=2.9.10"
+requires_ansible: ">=2.13"
action_groups:
netapp_um_info:
- na_um_aggregates_info
diff --git a/ansible_collections/netapp/um_info/metadata-29PbAy.json b/ansible_collections/netapp/um_info/metadata-29PbAy.json
new file mode 100644
index 000000000..7ccf48221
--- /dev/null
+++ b/ansible_collections/netapp/um_info/metadata-29PbAy.json
@@ -0,0 +1,14 @@
+{
+ "change_description": {
+ "changed_paths": [],
+ "command": "",
+ "deleted_paths": [],
+ "focused_command_targets": {},
+ "no_integration_paths": [],
+ "regular_command_targets": {}
+ },
+ "changes": {},
+ "ci_provider": "",
+ "cloud_config": null,
+ "instance_config": null
+}
diff --git a/ansible_collections/netapp/um_info/plugins/module_utils/netapp.py b/ansible_collections/netapp/um_info/plugins/module_utils/netapp.py
index ba58f56e8..15a113ae4 100644
--- a/ansible_collections/netapp/um_info/plugins/module_utils/netapp.py
+++ b/ansible_collections/netapp/um_info/plugins/module_utils/netapp.py
@@ -43,7 +43,7 @@ try:
except ImportError:
ansible_version = 'unknown'
-COLLECTION_VERSION = "21.8.0"
+COLLECTION_VERSION = "21.8.1"
try:
import requests
diff --git a/ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_aggregates.py b/ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_aggregates.py
new file mode 100644
index 000000000..9d2479484
--- /dev/null
+++ b/ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_aggregates.py
@@ -0,0 +1,159 @@
+# (c) 2020, 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_um_aggregates_info """
+
+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.um_info.tests.unit.compat import unittest
+from ansible_collections.netapp.um_info.tests.unit.compat.mock import patch, Mock
+import ansible_collections.netapp.um_info.plugins.module_utils.netapp as netapp_utils
+
+from ansible_collections.netapp.um_info.plugins.modules.na_um_aggregates_info\
+ import NetAppUMAggregate as my_module # module under test
+
+
+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')
+
+
+# REST API canned responses when mocking send_request
+SRR = {
+ # common responses
+ 'empty_not_so_good': ({}, None),
+ 'end_of_sequence': (None, "Unexpected call to send_request"),
+ 'generic_error': (None, "Expected error"),
+ 'get_next': (dict(_links=dict(self='me', next=dict(href='next_records'))), None),
+ 'get_data': (dict(_links=dict(self='me'), records=['data1', 'data2'], total_records=2), None),
+ 'get_data_missing_field': (dict(_links=dict(self='me'), records=['data1', 'data2']), None),
+ # module specific responses
+ 'get_aggregates': {'name': 'ansible'}
+}
+
+
+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 MockUMConnection(object):
+ ''' mock server connection to Unified Manager host '''
+
+ def __init__(self):
+ ''' pass init '''
+
+
+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 = MockUMConnection()
+ # 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'
+ else:
+ hostname = 'hostname'
+ username = 'username'
+ password = 'password'
+ return dict({
+ 'hostname': hostname,
+ 'username': username,
+ 'password': 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'])
+
+ @patch('ansible_collections.netapp.um_info.plugins.modules.na_um_aggregates_info.NetAppUMAggregate.get_aggregates')
+ def test_ensure_list_aggregates_get_called(self, get_aggregates):
+ ''' fetching details of aggregates '''
+ set_module_args(self.set_default_args())
+ my_obj = my_module()
+ my_obj.server = self.server
+ my_obj.get_aggregates = Mock(return_value=SRR['get_aggregates'])
+ with pytest.raises(AnsibleExitJson) as exc:
+ my_obj.apply()
+ assert exc.value.args[0]['changed']
+ # to reset na_helper from remembering the previous 'changed' value
+
+ @patch('ansible_collections.netapp.um_info.plugins.modules.na_um_aggregates_info.NetAppUMAggregate.get_aggregates')
+ def test_ensure_get_called_existing(self, get_aggregates):
+ ''' test for existing aggregates'''
+ set_module_args(self.set_default_args())
+ my_obj = my_module()
+ my_obj.get_aggregates = Mock(return_value=SRR['get_aggregates'])
+ assert my_obj.get_aggregates() is not None
+
+ @patch('ansible_collections.netapp.um_info.plugins.module_utils.netapp.UMRestAPI.send_request')
+ def test_get_next(self, mock_request):
+ ''' test for existing aggregates'''
+ set_module_args(self.set_default_args())
+ mock_request.side_effect = [
+ SRR['get_next'],
+ SRR['get_data'],
+ SRR['end_of_sequence'],
+ ]
+ my_obj = my_module()
+ assert my_obj.get_aggregates() is not None
+
+ @patch('ansible_collections.netapp.um_info.plugins.module_utils.netapp.UMRestAPI.send_request')
+ def test_negative_get_next(self, mock_request):
+ ''' test for existing aggregates'''
+ set_module_args(self.set_default_args())
+ mock_request.side_effect = [
+ SRR['get_next'],
+ SRR['get_data_missing_field'],
+ SRR['end_of_sequence'],
+ ]
+ my_obj = my_module()
+ with pytest.raises(AnsibleFailJson) as exc:
+ my_obj.get_aggregates() is not None
+ print(exc.value.args[0])
+ msg = 'unexpected response from datacenter/storage/aggregates?order_by=performance_capacity.used'
+ assert msg in exc.value.args[0]['msg']
+ msg = "expecting key: 'total_records'"
+ assert msg in exc.value.args[0]['msg']
diff --git a/ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_clusters.py b/ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_clusters.py
new file mode 100644
index 000000000..c4939adb8
--- /dev/null
+++ b/ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_clusters.py
@@ -0,0 +1,159 @@
+# (c) 2020, 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_um_clusters_info """
+
+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.um_info.tests.unit.compat import unittest
+from ansible_collections.netapp.um_info.tests.unit.compat.mock import patch, Mock
+import ansible_collections.netapp.um_info.plugins.module_utils.netapp as netapp_utils
+
+from ansible_collections.netapp.um_info.plugins.modules.na_um_clusters_info\
+ import NetAppUMCluster as my_module # module under test
+
+
+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')
+
+
+# REST API canned responses when mocking send_request
+SRR = {
+ # common responses
+ 'empty_good': ({}, None),
+ 'end_of_sequence': (None, "Unexpected call to send_request"),
+ 'generic_error': (None, "Expected error"),
+ 'get_next': (dict(_links=dict(self='me', next=dict(href='next_records'))), None),
+ 'get_data': (dict(_links=dict(self='me'), records=['data1', 'data2'], total_records=2), None),
+ 'get_data_missing_field': (dict(_links=dict(self='me'), records=['data1', 'data2']), None),
+ # module specific responses
+ 'get_cluster': {'name': 'ansible'}
+}
+
+
+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 MockUMConnection(object):
+ ''' mock server connection to Unified Manager host '''
+
+ def __init__(self):
+ ''' pass init '''
+
+
+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 = MockUMConnection()
+ # 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'
+ else:
+ hostname = 'hostname'
+ username = 'username'
+ password = 'password'
+ return dict({
+ 'hostname': hostname,
+ 'username': username,
+ 'password': 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'])
+
+ @patch('ansible_collections.netapp.um_info.plugins.modules.na_um_clusters_info.NetAppUMCluster.get_clusters')
+ def test_ensure_list_cluster_get_called(self, get_cluster):
+ ''' fetching details of cluster '''
+ set_module_args(self.set_default_args())
+ my_obj = my_module()
+ my_obj.server = self.server
+ my_obj.get_cluster = Mock(return_value=SRR['get_cluster'])
+ with pytest.raises(AnsibleExitJson) as exc:
+ my_obj.apply()
+ assert exc.value.args[0]['changed']
+ # to reset na_helper from remembering the previous 'changed' value
+
+ @patch('ansible_collections.netapp.um_info.plugins.modules.na_um_clusters_info.NetAppUMCluster.get_clusters')
+ def test_ensure_get_called_existing(self, get_cluster):
+ ''' test for existing cluster'''
+ set_module_args(self.set_default_args())
+ my_obj = my_module()
+ my_obj.get_cluster = Mock(return_value=SRR['get_cluster'])
+ assert my_obj.get_cluster() is not None
+
+ @patch('ansible_collections.netapp.um_info.plugins.module_utils.netapp.UMRestAPI.send_request')
+ def test_get_next(self, mock_request):
+ ''' test for existing clusters'''
+ set_module_args(self.set_default_args())
+ mock_request.side_effect = [
+ SRR['get_next'],
+ SRR['get_data'],
+ SRR['end_of_sequence'],
+ ]
+ my_obj = my_module()
+ assert my_obj.get_clusters() is not None
+
+ @patch('ansible_collections.netapp.um_info.plugins.module_utils.netapp.UMRestAPI.send_request')
+ def test_negative_get_next(self, mock_request):
+ ''' test for existing clusters'''
+ set_module_args(self.set_default_args())
+ mock_request.side_effect = [
+ SRR['get_next'],
+ SRR['get_data_missing_field'],
+ SRR['end_of_sequence'],
+ ]
+ my_obj = my_module()
+ with pytest.raises(AnsibleFailJson) as exc:
+ my_obj.get_clusters() is not None
+ print(exc.value.args[0])
+ msg = 'unexpected response from datacenter/cluster/clusters'
+ assert msg in exc.value.args[0]['msg']
+ msg = "expecting key: 'total_records'"
+ assert msg in exc.value.args[0]['msg']
diff --git a/ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_nodes.py b/ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_nodes.py
new file mode 100644
index 000000000..e5769d1f1
--- /dev/null
+++ b/ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_nodes.py
@@ -0,0 +1,158 @@
+# (c) 2020, 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_um_nodes_info """
+
+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.um_info.tests.unit.compat import unittest
+from ansible_collections.netapp.um_info.tests.unit.compat.mock import patch, Mock
+import ansible_collections.netapp.um_info.plugins.module_utils.netapp as netapp_utils
+
+from ansible_collections.netapp.um_info.plugins.modules.na_um_nodes_info\
+ import NetAppUMNode as my_module # module under test
+
+
+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')
+
+
+# REST API canned responses when mocking send_request
+SRR = {
+ # common responses
+ 'empty_good': ({}, None),
+ 'end_of_sequence': (None, "Unexpected call to send_request"),
+ 'generic_error': (None, "Expected error"),
+ 'get_next': (dict(_links=dict(self='me', next=dict(href='next_records'))), None),
+ 'get_data': (dict(_links=dict(self='me'), records=['data1', 'data2'], total_records=2), None),
+ 'get_data_missing_field': (dict(_links=dict(self='me'), records=['data1', 'data2']), None),
+ # module specific responses
+ 'get_nodes': {'name': 'ansible'}
+}
+
+
+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 MockUMConnection(object):
+ ''' mock server connection to Unified Manager host '''
+
+ def __init__(self):
+ ''' pass init '''
+
+
+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 = MockUMConnection()
+ # 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'
+ else:
+ hostname = 'hostname'
+ username = 'username'
+ password = 'password'
+ return dict({
+ 'hostname': hostname,
+ 'username': username,
+ 'password': 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'])
+
+ @patch('ansible_collections.netapp.um_info.plugins.modules.na_um_nodes_info.NetAppUMNode.get_nodes')
+ def test_ensure_list_nodes_get_called(self, get_nodes):
+ ''' fetching details of nodes '''
+ set_module_args(self.set_default_args())
+ my_obj = my_module()
+ my_obj.server = self.server
+ my_obj.get_nodes = Mock(return_value=SRR['get_nodes'])
+ with pytest.raises(AnsibleExitJson) as exc:
+ my_obj.apply()
+ assert exc.value.args[0]['changed']
+
+ @patch('ansible_collections.netapp.um_info.plugins.modules.na_um_nodes_info.NetAppUMNode.get_nodes')
+ def test_ensure_get_called_existing(self, get_nodes):
+ ''' test for existing nodes'''
+ set_module_args(self.set_default_args())
+ my_obj = my_module()
+ my_obj.get_nodes = Mock(return_value=SRR['get_nodes'])
+ assert my_obj.get_nodes() is not None
+
+ @patch('ansible_collections.netapp.um_info.plugins.module_utils.netapp.UMRestAPI.send_request')
+ def test_get_next(self, mock_request):
+ ''' test for existing nodes'''
+ set_module_args(self.set_default_args())
+ mock_request.side_effect = [
+ SRR['get_next'],
+ SRR['get_data'],
+ SRR['end_of_sequence'],
+ ]
+ my_obj = my_module()
+ assert my_obj.get_nodes() is not None
+
+ @patch('ansible_collections.netapp.um_info.plugins.module_utils.netapp.UMRestAPI.send_request')
+ def test_negative_get_next(self, mock_request):
+ ''' test for existing nodes'''
+ set_module_args(self.set_default_args())
+ mock_request.side_effect = [
+ SRR['get_next'],
+ SRR['get_data_missing_field'],
+ SRR['end_of_sequence'],
+ ]
+ my_obj = my_module()
+ with pytest.raises(AnsibleFailJson) as exc:
+ my_obj.get_nodes() is not None
+ print(exc.value.args[0])
+ msg = 'unexpected response from datacenter/cluster/nodes'
+ assert msg in exc.value.args[0]['msg']
+ msg = "expecting key: 'total_records'"
+ assert msg in exc.value.args[0]['msg']
diff --git a/ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_svms.py b/ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_svms.py
new file mode 100644
index 000000000..2eafd508f
--- /dev/null
+++ b/ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_svms.py
@@ -0,0 +1,158 @@
+# (c) 2020, 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_um_svms_info """
+
+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.um_info.tests.unit.compat import unittest
+from ansible_collections.netapp.um_info.tests.unit.compat.mock import patch, Mock
+import ansible_collections.netapp.um_info.plugins.module_utils.netapp as netapp_utils
+
+from ansible_collections.netapp.um_info.plugins.modules.na_um_svms_info\
+ import NetAppUMSVM as my_module # module under test
+
+
+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')
+
+
+# REST API canned responses when mocking send_request
+SRR = {
+ # common responses
+ 'empty_good': ({}, None),
+ 'end_of_sequence': (None, "Unexpected call to send_request"),
+ 'generic_error': (None, "Expected error"),
+ 'get_next': (dict(_links=dict(self='me', next=dict(href='next_records'))), None),
+ 'get_data': (dict(_links=dict(self='me'), records=['data1', 'data2'], total_records=2), None),
+ 'get_data_missing_field': (dict(_links=dict(self='me'), records=['data1', 'data2']), None),
+ # module specific responses
+ 'get_svms': {'name': 'ansible'}
+}
+
+
+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 MockUMConnection(object):
+ ''' mock server connection to Unified Manager host '''
+
+ def __init__(self):
+ ''' pass init '''
+
+
+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 = MockUMConnection()
+ # 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'
+ else:
+ hostname = 'hostname'
+ username = 'username'
+ password = 'password'
+ return dict({
+ 'hostname': hostname,
+ 'username': username,
+ 'password': 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'])
+
+ @patch('ansible_collections.netapp.um_info.plugins.modules.na_um_svms_info.NetAppUMSVM.get_svms')
+ def test_ensure_list_svms_get_called(self, get_svms):
+ ''' fetching details of svms '''
+ set_module_args(self.set_default_args())
+ my_obj = my_module()
+ my_obj.server = self.server
+ my_obj.get_svms = Mock(return_value=SRR['get_svms'])
+ with pytest.raises(AnsibleExitJson) as exc:
+ my_obj.apply()
+ assert exc.value.args[0]['changed']
+
+ @patch('ansible_collections.netapp.um_info.plugins.modules.na_um_svms_info.NetAppUMSVM.get_svms')
+ def test_ensure_get_called_existing(self, get_svms):
+ ''' test for existing svms'''
+ set_module_args(self.set_default_args())
+ my_obj = my_module()
+ my_obj.get_svms = Mock(return_value=SRR['get_svms'])
+ assert my_obj.get_svms() is not None
+
+ @patch('ansible_collections.netapp.um_info.plugins.module_utils.netapp.UMRestAPI.send_request')
+ def test_get_next(self, mock_request):
+ ''' test for existing svms'''
+ set_module_args(self.set_default_args())
+ mock_request.side_effect = [
+ SRR['get_next'],
+ SRR['get_data'],
+ SRR['end_of_sequence'],
+ ]
+ my_obj = my_module()
+ assert my_obj.get_svms() is not None
+
+ @patch('ansible_collections.netapp.um_info.plugins.module_utils.netapp.UMRestAPI.send_request')
+ def test_negative_get_next(self, mock_request):
+ ''' test for existing svms'''
+ set_module_args(self.set_default_args())
+ mock_request.side_effect = [
+ SRR['get_next'],
+ SRR['get_data_missing_field'],
+ SRR['end_of_sequence'],
+ ]
+ my_obj = my_module()
+ with pytest.raises(AnsibleFailJson) as exc:
+ my_obj.get_svms() is not None
+ print(exc.value.args[0])
+ msg = 'unexpected response from datacenter/svm/svms'
+ assert msg in exc.value.args[0]['msg']
+ msg = "expecting key: 'total_records'"
+ assert msg in exc.value.args[0]['msg']
diff --git a/ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_volumes.py b/ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_volumes.py
new file mode 100644
index 000000000..4c8a267fb
--- /dev/null
+++ b/ansible_collections/netapp/um_info/tests/unit/plugins/modules/test_na_um_list_volumes.py
@@ -0,0 +1,158 @@
+# (c) 2020, 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_um_volumes_info """
+
+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.um_info.tests.unit.compat import unittest
+from ansible_collections.netapp.um_info.tests.unit.compat.mock import patch, Mock
+import ansible_collections.netapp.um_info.plugins.module_utils.netapp as netapp_utils
+
+from ansible_collections.netapp.um_info.plugins.modules.na_um_volumes_info\
+ import NetAppUMVolume as my_module # module under test
+
+
+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')
+
+
+# REST API canned responses when mocking send_request
+SRR = {
+ # common responses
+ 'empty_good': ({}, None),
+ 'end_of_sequence': (None, "Unexpected call to send_request"),
+ 'generic_error': (None, "Expected error"),
+ 'get_next': (dict(_links=dict(self='me', next=dict(href='next_records'))), None),
+ 'get_data': (dict(_links=dict(self='me'), records=['data1', 'data2'], total_records=2), None),
+ 'get_data_missing_field': (dict(_links=dict(self='me'), records=['data1', 'data2']), None),
+ # module specific responses
+ 'get_volumes': {'name': 'ansible'}
+}
+
+
+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 MockUMConnection(object):
+ ''' mock server connection to Unified Manager host '''
+
+ def __init__(self):
+ ''' pass init '''
+
+
+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 = MockUMConnection()
+ # 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'
+ else:
+ hostname = 'hostname'
+ username = 'username'
+ password = 'password'
+ return dict({
+ 'hostname': hostname,
+ 'username': username,
+ 'password': 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'])
+
+ @patch('ansible_collections.netapp.um_info.plugins.modules.na_um_volumes_info.NetAppUMVolume.get_volumes')
+ def test_ensure_list_volumes_get_called(self, get_volumes):
+ ''' fetching details of volumes '''
+ set_module_args(self.set_default_args())
+ my_obj = my_module()
+ my_obj.server = self.server
+ my_obj.get_volumes = Mock(return_value=SRR['get_volumes'])
+ with pytest.raises(AnsibleExitJson) as exc:
+ my_obj.apply()
+ assert exc.value.args[0]['changed']
+
+ @patch('ansible_collections.netapp.um_info.plugins.modules.na_um_volumes_info.NetAppUMVolume.get_volumes')
+ def test_ensure_get_called_existing(self, get_volumes):
+ ''' test for existing volumes'''
+ set_module_args(self.set_default_args())
+ my_obj = my_module()
+ my_obj.get_volumes = Mock(return_value=SRR['get_volumes'])
+ assert my_obj.get_volumes() is not None
+
+ @patch('ansible_collections.netapp.um_info.plugins.module_utils.netapp.UMRestAPI.send_request')
+ def test_get_next(self, mock_request):
+ ''' test for existing volumes'''
+ set_module_args(self.set_default_args())
+ mock_request.side_effect = [
+ SRR['get_next'],
+ SRR['get_data'],
+ SRR['end_of_sequence'],
+ ]
+ my_obj = my_module()
+ assert my_obj.get_volumes() is not None
+
+ @patch('ansible_collections.netapp.um_info.plugins.module_utils.netapp.UMRestAPI.send_request')
+ def test_negative_get_next(self, mock_request):
+ ''' test for existing volumes'''
+ set_module_args(self.set_default_args())
+ mock_request.side_effect = [
+ SRR['get_next'],
+ SRR['get_data_missing_field'],
+ SRR['end_of_sequence'],
+ ]
+ my_obj = my_module()
+ with pytest.raises(AnsibleFailJson) as exc:
+ my_obj.get_volumes() is not None
+ print(exc.value.args[0])
+ msg = 'unexpected response from datacenter/storage/volumes'
+ assert msg in exc.value.args[0]['msg']
+ msg = "expecting key: 'total_records'"
+ assert msg in exc.value.args[0]['msg']