mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-05-06 13:22:48 +00:00
Resolve issues in NetApp E-Series Host module (#39748)
* Resolve issues in NetApp E-Series Host module The E-Series host module had some bugs relating to the update/creation of host definitions when iSCSI initiators when included in the configuration. This patch resolves this and other minor issues with correctly detecting updates. There were also several minor issues found that were causing issues with truly idepotent updates/changes to the host definition. This patch also provides some unit tests and integration tests to help catch future issues in these areas. fixes #28272 * Improve NetApp E-Series Host module testing The NetApp E-Series Host module integration test lacked feature test verification to verify the changes made to the storage array. The NetApp E-Series rest api was used to verify host create, update, and remove changes made to the NetApp E-Series storage arrays.
This commit is contained in:
committed by
John R Barker
parent
3122860f22
commit
ad91793428
0
test/units/modules/storage/__init__.py
Normal file
0
test/units/modules/storage/__init__.py
Normal file
0
test/units/modules/storage/netapp/__init__.py
Normal file
0
test/units/modules/storage/netapp/__init__.py
Normal file
190
test/units/modules/storage/netapp/test_netapp_e_host.py
Normal file
190
test/units/modules/storage/netapp/test_netapp_e_host.py
Normal file
@@ -0,0 +1,190 @@
|
||||
# (c) 2018, NetApp Inc.
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from mock import MagicMock
|
||||
|
||||
from ansible.module_utils import basic, netapp
|
||||
from ansible.modules.storage.netapp import netapp_e_host
|
||||
from ansible.modules.storage.netapp.netapp_e_host import Host
|
||||
from units.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase, set_module_args
|
||||
|
||||
__metaclass__ = type
|
||||
import unittest
|
||||
import mock
|
||||
import pytest
|
||||
import json
|
||||
from ansible.compat.tests.mock import patch
|
||||
from ansible.module_utils._text import to_bytes
|
||||
|
||||
|
||||
class HostTest(ModuleTestCase):
|
||||
REQUIRED_PARAMS = {
|
||||
'api_username': 'rw',
|
||||
'api_password': 'password',
|
||||
'api_url': 'http://localhost',
|
||||
'ssid': '1',
|
||||
'name': '1',
|
||||
}
|
||||
HOST = {
|
||||
'name': '1',
|
||||
'label': '1',
|
||||
'id': '0' * 30,
|
||||
'clusterRef': 40 * '0',
|
||||
'hostTypeIndex': 28,
|
||||
'hostSidePorts': [],
|
||||
'initiators': [],
|
||||
'ports': [],
|
||||
}
|
||||
HOST_ALT = {
|
||||
'name': '2',
|
||||
'label': '2',
|
||||
'id': '1' * 30,
|
||||
'clusterRef': '1',
|
||||
'hostSidePorts': [],
|
||||
'initiators': [],
|
||||
'ports': [],
|
||||
}
|
||||
REQ_FUNC = 'ansible.modules.storage.netapp.netapp_e_host.request'
|
||||
|
||||
def _set_args(self, args):
|
||||
module_args = self.REQUIRED_PARAMS.copy()
|
||||
module_args.update(args)
|
||||
set_module_args(module_args)
|
||||
|
||||
def test_delete_host(self):
|
||||
"""Validate removing a host object"""
|
||||
self._set_args({
|
||||
'state': 'absent'
|
||||
})
|
||||
host = Host()
|
||||
with self.assertRaises(AnsibleExitJson) as result:
|
||||
# We expect 2 calls to the API, the first to retrieve the host objects defined,
|
||||
# the second to remove the host definition.
|
||||
with mock.patch(self.REQ_FUNC, side_effect=[(200, [self.HOST]), (204, {})]) as request:
|
||||
host.apply()
|
||||
self.assertEquals(request.call_count, 2)
|
||||
# We expect the module to make changes
|
||||
self.assertEquals(result.exception.args[0]['changed'], True)
|
||||
|
||||
def test_delete_host_no_changes(self):
|
||||
"""Ensure that removing a host that doesn't exist works correctly."""
|
||||
self._set_args({
|
||||
'state': 'absent'
|
||||
})
|
||||
host = Host()
|
||||
with self.assertRaises(AnsibleExitJson) as result:
|
||||
# We expect a single call to the API: retrieve the defined hosts.
|
||||
with mock.patch(self.REQ_FUNC, return_value=(200, [])):
|
||||
host.apply()
|
||||
# We should not mark changed=True
|
||||
self.assertEquals(result.exception.args[0]['changed'], False)
|
||||
|
||||
def test_host_exists(self):
|
||||
"""Test host_exists method"""
|
||||
self._set_args({
|
||||
'state': 'absent'
|
||||
})
|
||||
host = Host()
|
||||
with mock.patch(self.REQ_FUNC, return_value=(200, [self.HOST])) as request:
|
||||
host_exists = host.host_exists
|
||||
self.assertTrue(host_exists, msg="This host should exist!")
|
||||
|
||||
def test_host_exists_negative(self):
|
||||
"""Test host_exists method with no matching hosts to return"""
|
||||
self._set_args({
|
||||
'state': 'absent'
|
||||
})
|
||||
host = Host()
|
||||
with mock.patch(self.REQ_FUNC, return_value=(200, [self.HOST_ALT])) as request:
|
||||
host_exists = host.host_exists
|
||||
self.assertFalse(host_exists, msg="This host should exist!")
|
||||
|
||||
def test_host_exists_fail(self):
|
||||
"""Ensure we do not dump a stack trace if we fail to make the request"""
|
||||
self._set_args({
|
||||
'state': 'absent'
|
||||
})
|
||||
host = Host()
|
||||
with self.assertRaises(AnsibleFailJson):
|
||||
with mock.patch(self.REQ_FUNC, side_effect=Exception("http_error")) as request:
|
||||
host_exists = host.host_exists
|
||||
|
||||
def test_needs_update_host_type(self):
|
||||
"""Ensure a changed host_type triggers an update"""
|
||||
self._set_args({
|
||||
'state': 'present',
|
||||
'host_type': 27
|
||||
})
|
||||
host = Host()
|
||||
host.host_obj = self.HOST
|
||||
with mock.patch(self.REQ_FUNC, return_value=(200, [self.HOST])) as request:
|
||||
needs_update = host.needs_update
|
||||
self.assertTrue(needs_update, msg="An update to the host should be required!")
|
||||
|
||||
def test_needs_update_cluster(self):
|
||||
"""Ensure a changed group_id triggers an update"""
|
||||
self._set_args({
|
||||
'state': 'present',
|
||||
'host_type': self.HOST['hostTypeIndex'],
|
||||
'group': '1',
|
||||
})
|
||||
host = Host()
|
||||
host.host_obj = self.HOST
|
||||
with mock.patch(self.REQ_FUNC, return_value=(200, [self.HOST])) as request:
|
||||
needs_update = host.needs_update
|
||||
self.assertTrue(needs_update, msg="An update to the host should be required!")
|
||||
|
||||
def test_needs_update_no_change(self):
|
||||
"""Ensure no changes do not trigger an update"""
|
||||
self._set_args({
|
||||
'state': 'present',
|
||||
'host_type': self.HOST['hostTypeIndex'],
|
||||
})
|
||||
host = Host()
|
||||
host.host_obj = self.HOST
|
||||
with mock.patch(self.REQ_FUNC, return_value=(200, [self.HOST])) as request:
|
||||
needs_update = host.needs_update
|
||||
self.assertFalse(needs_update, msg="An update to the host should be required!")
|
||||
|
||||
def test_needs_update_ports(self):
|
||||
"""Ensure added ports trigger an update"""
|
||||
self._set_args({
|
||||
'state': 'present',
|
||||
'host_type': self.HOST['hostTypeIndex'],
|
||||
'ports': [{'label': 'abc', 'type': 'iscsi', 'port': '0'}],
|
||||
})
|
||||
host = Host()
|
||||
host.host_obj = self.HOST
|
||||
with mock.patch.object(host, 'all_hosts', [self.HOST]):
|
||||
needs_update = host.needs_update
|
||||
self.assertTrue(needs_update, msg="An update to the host should be required!")
|
||||
|
||||
def test_needs_update_changed_ports(self):
|
||||
"""Ensure changed ports trigger an update"""
|
||||
self._set_args({
|
||||
'state': 'present',
|
||||
'host_type': self.HOST['hostTypeIndex'],
|
||||
'ports': [{'label': 'abc', 'type': 'iscsi', 'port': '0'}],
|
||||
})
|
||||
host = Host()
|
||||
host.host_obj = self.HOST.copy()
|
||||
host.host_obj['hostSidePorts'] = [{'label': 'xyz', 'type': 'iscsi', 'port': '0', 'address': 'iqn:0'}]
|
||||
|
||||
with mock.patch.object(host, 'all_hosts', [self.HOST]):
|
||||
needs_update = host.needs_update
|
||||
self.assertTrue(needs_update, msg="An update to the host should be required!")
|
||||
|
||||
def test_needs_update_changed_negative(self):
|
||||
"""Ensure a ports update with no changes does not trigger an update"""
|
||||
self._set_args({
|
||||
'state': 'present',
|
||||
'host_type': self.HOST['hostTypeIndex'],
|
||||
'ports': [{'label': 'abc', 'type': 'iscsi', 'port': '0'}],
|
||||
})
|
||||
host = Host()
|
||||
host.host_obj = self.HOST.copy()
|
||||
host.host_obj['hostSidePorts'] = [{'label': 'xyz', 'type': 'iscsi', 'port': '0', 'address': 'iqn:0'}]
|
||||
|
||||
with mock.patch.object(host, 'all_hosts', [self.HOST]):
|
||||
needs_update = host.needs_update
|
||||
self.assertTrue(needs_update, msg="An update to the host should be required!")
|
||||
Reference in New Issue
Block a user