Initial commits for integration of HPE OneView resources with Ansible (#26026)

* Initial commit for integration of HPE OneView resources with Ansible Core. Adding FC Network and FC Network Fact modules and unit tests, and OneView base class for all OV resources.
This commit is contained in:
Felipe Garcia Bulsoni 2017-08-02 23:54:32 -03:00 committed by Toshio Kuratomi
commit b060d0ccba
8 changed files with 964 additions and 0 deletions

View file

@ -0,0 +1,137 @@
# -*- coding: utf-8 -*-
#
# Copyright (2016-2017) Hewlett Packard Enterprise Development LP
#
# This program 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.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
import yaml
from mock import Mock, patch
from oneview_module_loader import ONEVIEW_MODULE_UTILS_PATH
from hpOneView.oneview_client import OneViewClient
class OneViewBaseTestCase(object):
mock_ov_client_from_json_file = None
testing_class = None
mock_ansible_module = None
mock_ov_client = None
testing_module = None
EXAMPLES = None
def configure_mocks(self, test_case, testing_class):
"""
Preload mocked OneViewClient instance and AnsibleModule
Args:
test_case (object): class instance (self) that are inheriting from OneViewBaseTestCase
testing_class (object): class being tested
"""
self.testing_class = testing_class
# Define OneView Client Mock (FILE)
patcher_json_file = patch.object(OneViewClient, 'from_json_file')
test_case.addCleanup(patcher_json_file.stop)
self.mock_ov_client_from_json_file = patcher_json_file.start()
# Define OneView Client Mock
self.mock_ov_client = self.mock_ov_client_from_json_file.return_value
# Define Ansible Module Mock
patcher_ansible = patch(ONEVIEW_MODULE_UTILS_PATH + '.AnsibleModule')
test_case.addCleanup(patcher_ansible.stop)
mock_ansible_module = patcher_ansible.start()
self.mock_ansible_module = Mock()
mock_ansible_module.return_value = self.mock_ansible_module
self.__set_module_examples()
def test_main_function_should_call_run_method(self):
self.mock_ansible_module.params = {'config': 'config.json'}
main_func = getattr(self.testing_module, 'main')
with patch.object(self.testing_class, "run") as mock_run:
main_func()
mock_run.assert_called_once()
def __set_module_examples(self):
# Load scenarios from module examples (Also checks if it is a valid yaml)
ansible = __import__('ansible')
testing_module = self.testing_class.__module__.split('.')[-1]
self.testing_module = getattr(ansible.modules.remote_management.hpe, testing_module)
try:
# Load scenarios from module examples (Also checks if it is a valid yaml)
self.EXAMPLES = yaml.load(self.testing_module.EXAMPLES, yaml.SafeLoader)
except yaml.scanner.ScannerError:
message = "Something went wrong while parsing yaml from {}.EXAMPLES".format(self.testing_class.__module__)
raise Exception(message)
class FactsParamsTestCase(OneViewBaseTestCase):
"""
FactsParamsTestCase has common test for classes that support pass additional
parameters when retrieving all resources.
"""
def configure_client_mock(self, resorce_client):
"""
Args:
resorce_client: Resource client that is being called
"""
self.resource_client = resorce_client
def __validations(self):
if not self.testing_class:
raise Exception("Mocks are not configured, you must call 'configure_mocks' before running this test.")
if not self.resource_client:
raise Exception(
"Mock for the client not configured, you must call 'configure_client_mock' before running this test.")
def test_should_get_all_using_filters(self):
self.__validations()
self.resource_client.get_all.return_value = []
params_get_all_with_filters = dict(
config='config.json',
name=None,
params={
'start': 1,
'count': 3,
'sort': 'name:descending',
'filter': 'purpose=General',
'query': 'imported eq true'
})
self.mock_ansible_module.params = params_get_all_with_filters
self.testing_class().run()
self.resource_client.get_all.assert_called_once_with(start=1, count=3, sort='name:descending',
filter='purpose=General',
query='imported eq true')
def test_should_get_all_without_params(self):
self.__validations()
self.resource_client.get_all.return_value = []
params_get_all_with_filters = dict(
config='config.json',
name=None
)
self.mock_ansible_module.params = params_get_all_with_filters
self.testing_class().run()
self.resource_client.get_all.assert_called_once_with()

View file

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
# Copyright (2016-2017) Hewlett Packard Enterprise Development LP
#
# This program 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.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
import sys
from ansible.compat.tests.mock import patch, Mock
sys.modules['hpOneView'] = Mock()
sys.modules['hpOneView.oneview_client'] = Mock()
sys.modules['hpOneView.exceptions'] = Mock()
sys.modules['future'] = Mock()
sys.modules['__future__'] = Mock()
ONEVIEW_MODULE_UTILS_PATH = 'ansible.module_utils.oneview'
from ansible.module_utils.oneview import (HPOneViewException,
HPOneViewTaskError,
OneViewModuleBase)
from ansible.modules.remote_management.hpe.oneview_fc_network import FcNetworkModule

View file

@ -0,0 +1,174 @@
# -*- coding: utf-8 -*-
#
# Copyright (2016-2017) Hewlett Packard Enterprise Development LP
#
# This program 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.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
from ansible.compat.tests import unittest
from oneview_module_loader import FcNetworkModule
from hpe_test_utils import OneViewBaseTestCase
FAKE_MSG_ERROR = 'Fake message error'
DEFAULT_FC_NETWORK_TEMPLATE = dict(
name='New FC Network 2',
autoLoginRedistribution=True,
fabricType='FabricAttach'
)
PARAMS_FOR_PRESENT = dict(
config='config.json',
state='present',
data=dict(name=DEFAULT_FC_NETWORK_TEMPLATE['name'])
)
PARAMS_WITH_CHANGES = dict(
config='config.json',
state='present',
data=dict(name=DEFAULT_FC_NETWORK_TEMPLATE['name'],
newName="New Name",
fabricType='DirectAttach')
)
PARAMS_FOR_ABSENT = dict(
config='config.json',
state='absent',
data=dict(name=DEFAULT_FC_NETWORK_TEMPLATE['name'])
)
class FcNetworkModuleSpec(unittest.TestCase,
OneViewBaseTestCase):
"""
OneViewBaseTestCase provides the mocks used in this test case
"""
def setUp(self):
self.configure_mocks(self, FcNetworkModule)
self.resource = self.mock_ov_client.fc_networks
def test_should_create_new_fc_network(self):
self.resource.get_by.return_value = []
self.resource.create.return_value = DEFAULT_FC_NETWORK_TEMPLATE
self.mock_ansible_module.params = PARAMS_FOR_PRESENT
FcNetworkModule().run()
self.mock_ansible_module.exit_json.assert_called_once_with(
changed=True,
msg=FcNetworkModule.MSG_CREATED,
ansible_facts=dict(fc_network=DEFAULT_FC_NETWORK_TEMPLATE)
)
def test_should_not_update_when_data_is_equals(self):
self.resource.get_by.return_value = [DEFAULT_FC_NETWORK_TEMPLATE]
self.mock_ansible_module.params = PARAMS_FOR_PRESENT
FcNetworkModule().run()
self.mock_ansible_module.exit_json.assert_called_once_with(
changed=False,
msg=FcNetworkModule.MSG_ALREADY_PRESENT,
ansible_facts=dict(fc_network=DEFAULT_FC_NETWORK_TEMPLATE)
)
def test_update_when_data_has_modified_attributes(self):
data_merged = DEFAULT_FC_NETWORK_TEMPLATE.copy()
data_merged['fabricType'] = 'DirectAttach'
self.resource.get_by.return_value = [DEFAULT_FC_NETWORK_TEMPLATE]
self.resource.update.return_value = data_merged
self.mock_ansible_module.params = PARAMS_WITH_CHANGES
FcNetworkModule().run()
self.mock_ansible_module.exit_json.assert_called_once_with(
changed=True,
msg=FcNetworkModule.MSG_UPDATED,
ansible_facts=dict(fc_network=data_merged)
)
def test_should_remove_fc_network(self):
self.resource.get_by.return_value = [DEFAULT_FC_NETWORK_TEMPLATE]
self.mock_ansible_module.params = PARAMS_FOR_ABSENT
FcNetworkModule().run()
self.mock_ansible_module.exit_json.assert_called_once_with(
changed=True,
msg=FcNetworkModule.MSG_DELETED
)
def test_should_do_nothing_when_fc_network_not_exist(self):
self.resource.get_by.return_value = []
self.mock_ansible_module.params = PARAMS_FOR_ABSENT
FcNetworkModule().run()
self.mock_ansible_module.exit_json.assert_called_once_with(
changed=False,
msg=FcNetworkModule.MSG_ALREADY_ABSENT
)
def test_update_scopes_when_different(self):
params_to_scope = PARAMS_FOR_PRESENT.copy()
params_to_scope['data']['scopeUris'] = ['test']
self.mock_ansible_module.params = params_to_scope
resource_data = DEFAULT_FC_NETWORK_TEMPLATE.copy()
resource_data['scopeUris'] = ['fake']
resource_data['uri'] = 'rest/fc/fake'
self.resource.get_by.return_value = [resource_data]
patch_return = resource_data.copy()
patch_return['scopeUris'] = ['test']
self.resource.patch.return_value = patch_return
FcNetworkModule().run()
self.resource.patch.assert_called_once_with('rest/fc/fake',
operation='replace',
path='/scopeUris',
value=['test'])
self.mock_ansible_module.exit_json.assert_called_once_with(
changed=True,
ansible_facts=dict(fc_network=patch_return),
msg=FcNetworkModule.MSG_UPDATED
)
def test_should_do_nothing_when_scopes_are_the_same(self):
params_to_scope = PARAMS_FOR_PRESENT.copy()
params_to_scope['data']['scopeUris'] = ['test']
self.mock_ansible_module.params = params_to_scope
resource_data = DEFAULT_FC_NETWORK_TEMPLATE.copy()
resource_data['scopeUris'] = ['test']
self.resource.get_by.return_value = [resource_data]
FcNetworkModule().run()
self.resource.patch.not_been_called()
self.mock_ansible_module.exit_json.assert_called_once_with(
changed=False,
ansible_facts=dict(fc_network=resource_data),
msg=FcNetworkModule.MSG_ALREADY_PRESENT
)