1# -*- coding: utf-8 -*- 2 3# 4# Dell EMC OpenManage Ansible Modules 5# Version 2.1.3 6# Copyright (C) 2019-2020 Dell Inc. or its subsidiaries. All Rights Reserved. 7 8# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 9# 10 11from __future__ import (absolute_import, division, print_function) 12 13__metaclass__ = type 14 15import pytest 16from ansible.module_utils.six.moves.urllib.error import HTTPError 17from ansible_collections.dellemc.openmanage.plugins.modules import ome_device_info 18from ansible_collections.dellemc.openmanage.tests.unit.plugins.modules.common import FakeAnsibleModule, Constants 19 20resource_basic_inventory = {"basic_inventory": "DeviceService/Devices"} 21resource_detailed_inventory = {"detailed_inventory:": {"device_id": {Constants.device_id1: None}, 22 "device_service_tag": { 23 Constants.device_id2: Constants.service_tag1}}} 24 25MODULE_PATH = 'ansible_collections.dellemc.openmanage.plugins.modules.' 26 27 28class TestOmeDeviceInfo(FakeAnsibleModule): 29 module = ome_device_info 30 31 @pytest.fixture 32 def validate_device_inputs_mock(self, mocker): 33 validate_device_inputs_mock = mocker.patch(MODULE_PATH + 'ome_device_info._validate_inputs') 34 validate_device_inputs_mock.return_value = None 35 36 @pytest.fixture 37 def get_device_resource_parameters_mock(self, mocker): 38 response_class_mock = mocker.patch(MODULE_PATH + 'ome_device_info._get_resource_parameters', 39 return_value=resource_basic_inventory) 40 return response_class_mock 41 42 def test_main_basic_inventory_success_case(self, ome_default_args, module_mock, validate_device_inputs_mock, 43 ome_connection_mock, 44 get_device_resource_parameters_mock, ome_response_mock): 45 ome_response_mock.json_data = {"@odata.context": "/api/$metadata#Collection(DeviceService.Device)", 46 "@odata.count": 1} 47 increment_device_details = {"resp_obj": ome_response_mock, 48 "report_list": [{"DeviceServiceTag": Constants.service_tag1, 49 "Id": Constants.device_id1}]} 50 ome_connection_mock.get_all_report_details.return_value = increment_device_details 51 ome_response_mock.status_code = 200 52 result = self._run_module(ome_default_args) 53 assert result['changed'] is False 54 assert 'device_info' in result 55 assert result["device_info"] == {"@odata.context": "/api/$metadata#Collection(DeviceService.Device)", 56 "@odata.count": 1, 57 "value": [{"DeviceServiceTag": Constants.service_tag1, 58 "Id": Constants.device_id1}]} 59 60 def test_main_basic_inventory_query_param_success_case(self, mocker, ome_default_args, module_mock, 61 validate_device_inputs_mock, ome_connection_mock, 62 get_device_resource_parameters_mock, ome_response_mock): 63 quer_param_mock = mocker.patch(MODULE_PATH + 'ome_device_info._get_query_parameters') 64 quer_param_mock.return_value = {"filter": "Type eq '1000'"} 65 ome_response_mock.json_data = {"value": [{"device_id1": "details", "device_id2": "details"}]} 66 ome_response_mock.status_code = 200 67 result = self._run_module(ome_default_args) 68 assert result['changed'] is False 69 assert 'device_info' in result 70 assert result["device_info"] == {"value": [{"device_id1": "details", "device_id2": "details"}]} 71 72 def test_main_basic_inventory_failure_case(self, ome_default_args, module_mock, validate_device_inputs_mock, 73 ome_connection_mock, 74 get_device_resource_parameters_mock, ome_response_mock): 75 ome_response_mock.status_code = 500 76 ome_response_mock.json_data = {"@odata.context": "/api/$metadata#Collection(DeviceService.Device)", 77 "@odata.count": 0} 78 ome_connection_mock.get_all_report_details.return_value = {"resp_obj": ome_response_mock, "report_list": []} 79 result = self._run_module_with_fail_json(ome_default_args) 80 assert result['msg'] == 'Failed to fetch the device information' 81 82 def test_main_detailed_inventory_success_case(self, ome_default_args, module_mock, validate_device_inputs_mock, 83 ome_connection_mock, 84 get_device_resource_parameters_mock, ome_response_mock): 85 ome_default_args.update( 86 {"fact_subset": "detailed_inventory", "system_query_options": {"device_id": [Constants.device_id1], 87 "device_service_tag": [ 88 Constants.service_tag1]}}) 89 detailed_inventory = {"detailed_inventory:": { 90 "device_id": {Constants.device_id1: "DeviceService/Devices(Constants.device_id1)/InventoryDetails"}, 91 "device_service_tag": {Constants.service_tag1: "DeviceService/Devices(4321)/InventoryDetails"}}} 92 get_device_resource_parameters_mock.return_value = detailed_inventory 93 ome_response_mock.json_data = { 94 "value": [{"device_id": {"1234": "details"}}, {"device_service_tag": {Constants.service_tag1: "details"}}]} 95 ome_response_mock.status_code = 200 96 result = self._run_module(ome_default_args) 97 assert result['changed'] is False 98 assert 'device_info' in result 99 100 def test_main_detailed_inventory_http_error_case(self, ome_default_args, module_mock, validate_device_inputs_mock, 101 ome_connection_mock, 102 get_device_resource_parameters_mock, ome_response_mock): 103 ome_default_args.update( 104 {"fact_subset": "detailed_inventory", "system_query_options": {"device_id": [Constants.device_id1], 105 "device_service_tag": [ 106 Constants.service_tag1]}}) 107 detailed_inventory = {"detailed_inventory:": { 108 "device_id": {Constants.device_id1: "DeviceService/Devices(Constants.device_id1)/InventoryDetails"}, 109 "device_service_tag": {Constants.service_tag1: "DeviceService/Devices(4321)/InventoryDetails"}}} 110 get_device_resource_parameters_mock.return_value = detailed_inventory 111 ome_connection_mock.invoke_request.side_effect = HTTPError('http://testhost.com', 400, '', {}, None) 112 result = self._run_module_with_fail_json(ome_default_args) 113 assert 'device_info' not in result 114 115 def test_main_HTTPError_error_case(self, ome_default_args, module_mock, validate_device_inputs_mock, 116 ome_connection_mock, 117 get_device_resource_parameters_mock, ome_response_mock): 118 ome_connection_mock.invoke_request.side_effect = HTTPError('http://testhost.com', 400, '', {}, None) 119 ome_response_mock.json_data = {"value": [{"device_id1": "details", "device_id2": "details"}]} 120 ome_response_mock.status_code = 400 121 result = self._run_module_with_fail_json(ome_default_args) 122 assert 'device_info' not in result 123 assert result['failed'] is True 124 125 @pytest.mark.parametrize("fact_subset, mutually_exclusive_call", 126 [("basic_inventory", False), ("detailed_inventory", True)]) 127 def test_validate_inputs(self, fact_subset, mutually_exclusive_call, mocker): 128 module_params = {"fact_subset": fact_subset} 129 check_mutually_inclusive_arguments_mock = mocker.patch(MODULE_PATH + 130 'ome_device_info._check_mutually_inclusive_arguments') 131 check_mutually_inclusive_arguments_mock.return_value = None 132 self.module._validate_inputs(module_params) 133 if mutually_exclusive_call: 134 check_mutually_inclusive_arguments_mock.assert_called() 135 else: 136 check_mutually_inclusive_arguments_mock.assert_not_called() 137 check_mutually_inclusive_arguments_mock.reset_mock() 138 139 system_query_options_params = [{"system_query_options": None}, {"system_query_options": {"device_id": None}}, 140 {"system_query_options": {"device_service_tag": None}}] 141 142 @pytest.mark.parametrize("system_query_options_params", system_query_options_params) 143 def test_check_mutually_inclusive_arguments(self, system_query_options_params): 144 module_params = {"fact_subset": "subsystem_health"} 145 required_args = ["device_id", "device_service_tag"] 146 module_params.update(system_query_options_params) 147 with pytest.raises(ValueError) as ex: 148 self.module._check_mutually_inclusive_arguments(module_params["fact_subset"], module_params, 149 ["device_id", "device_service_tag"]) 150 assert "One of the following {0} is required for {1}".format(required_args, 151 module_params["fact_subset"]) == str(ex.value) 152 153 params = [{"fact_subset": "basic_inventory", "system_query_options": {"device_id": [Constants.device_id1]}}, 154 {"fact_subset": "subsystem_health", 155 "system_query_options": {"device_service_tag": [Constants.service_tag1]}}, 156 {"fact_subset": "detailed_inventory", 157 "system_query_options": {"device_id": [Constants.device_id1], "inventory_type": "serverDeviceCards"}}] 158 159 @pytest.mark.parametrize("module_params", params) 160 def test_get_resource_parameters(self, module_params, ome_connection_mock): 161 self.module._get_resource_parameters(module_params, ome_connection_mock) 162 163 @pytest.mark.parametrize("module_params,data", [({"system_query_options": None}, None), 164 ({"system_query_options": {"fileter": None}}, None), 165 ({"system_query_options": {"filter": "abc"}}, "$filter")]) 166 def test_get_query_parameters(self, module_params, data): 167 res = self.module._get_query_parameters(module_params) 168 if data is not None: 169 assert data in res 170 else: 171 assert res is None 172 173 @pytest.mark.parametrize("module_params", params) 174 def test_get_device_identifier_map(self, module_params, ome_connection_mock, mocker): 175 get_device_id_from_service_tags_mock = mocker.patch(MODULE_PATH + 176 'ome_device_info._get_device_id_from_service_tags') 177 get_device_id_from_service_tags_mock.return_value = None 178 res = self.module._get_device_identifier_map(module_params, ome_connection_mock) 179 assert isinstance(res, dict) 180 181 def test_check_duplicate_device_id(self): 182 self.module._check_duplicate_device_id([Constants.device_id1], 183 {Constants.device_id1: Constants.service_tag1}) 184 assert self.module.device_fact_error_report[Constants.service_tag1] == "Duplicate report of device_id: 1234" 185 186 @pytest.mark.parametrize("val,expected_res", [(123, True), ("abc", False)]) 187 def test_is_int(self, val, expected_res): 188 actual_res = self.module.is_int(val) 189 assert actual_res == expected_res 190 191 def test_get_device_id_from_service_tags(self, ome_connection_mock, ome_response_mock, mocker): 192 mocker.patch(MODULE_PATH + 'ome_device_info.update_device_details_with_filtering') 193 ome_response_mock.json_data.update({"@odata.context": "/api/$metadata#Collection(DeviceService.Device)"}) 194 ome_response_mock.json_data.update({"@odata.count": 1}) 195 ome_connection_mock.get_all_report_details.return_value = {"resp_obj": ome_response_mock, "report_list": [ 196 {"DeviceServiceTag": Constants.service_tag1, 197 "Id": Constants.device_id1}]} 198 self.module._get_device_id_from_service_tags([Constants.service_tag1, "INVALID"], ome_connection_mock) 199 200 def test_get_device_id_from_service_tags_error_case(self, ome_connection_mock, ome_response_mock): 201 ome_connection_mock.get_all_report_details.side_effect = HTTPError('http://testhost.com', 400, '', {}, None) 202 with pytest.raises(HTTPError) as ex: 203 self.module._get_device_id_from_service_tags(["INVALID"], ome_connection_mock) 204 205 def test_update_device_details_with_filtering_success_case_01(self, ome_connection_mock, ome_response_mock): 206 non_available_tags = [Constants.service_tag2] 207 service_tag_dict = {Constants.device_id1: Constants.service_tag1} 208 ome_response_mock.json_data = { 209 "value": [{"DeviceServiceTag": Constants.service_tag2, "Id": Constants.device_id2}]} 210 self.module.update_device_details_with_filtering(non_available_tags, service_tag_dict, ome_connection_mock) 211 assert service_tag_dict[Constants.device_id1] == Constants.service_tag1 212 assert service_tag_dict[Constants.device_id2] == Constants.service_tag2 213 assert len(non_available_tags) == 0 214 215 def test_update_device_details_with_filtering_success_case_02(self, ome_connection_mock, ome_response_mock): 216 non_available_tags = ["MX700"] 217 service_tag_dict = {Constants.device_id1: Constants.service_tag1} 218 ome_response_mock.json_data = {"value": [{"DeviceServiceTag": "MX7000", "Id": Constants.device_id2}]} 219 self.module.update_device_details_with_filtering(non_available_tags, service_tag_dict, ome_connection_mock) 220 assert service_tag_dict[Constants.device_id1] == Constants.service_tag1 221 assert Constants.device_id2 not in service_tag_dict 222 assert len(non_available_tags) == 1 223 224 def test_update_device_details_with_filtering_failure_case_01(self, ome_connection_mock, ome_response_mock): 225 error_msg = '400: Bad Request' 226 service_tag_dict = {} 227 non_available_tags = [Constants.service_tag2] 228 ome_connection_mock.invoke_request.side_effect = HTTPError('http://testhost.com', 400, error_msg, {}, None) 229 with pytest.raises(HTTPError, match=error_msg) as ex: 230 self.module.update_device_details_with_filtering(non_available_tags, service_tag_dict, ome_connection_mock) 231 232 def test_main_detailed_inventory_device_fact_error_report_case_01(self, ome_default_args, module_mock, 233 validate_device_inputs_mock, ome_connection_mock, 234 get_device_resource_parameters_mock, 235 ome_response_mock): 236 ome_default_args.update( 237 {"fact_subset": "detailed_inventory", "system_query_options": {"device_id": [Constants.device_id1], 238 "device_service_tag": [ 239 Constants.service_tag1]}}) 240 detailed_inventory = { 241 "detailed_inventory:": { 242 "device_id": { 243 Constants.device_id1: "DeviceService/Devices(Constants.device_id1)/InventoryDetails" 244 }, 245 "device_service_tag": { 246 Constants.service_tag1: "DeviceService/Devices(4321)/InventoryDetails" 247 } 248 } 249 } 250 get_device_resource_parameters_mock.return_value = detailed_inventory 251 ome_response_mock.json_data = {"value": [{"device_id": {Constants.device_id1: "details"}}, 252 {"device_service_tag": {Constants.service_tag1: "details"}}]} 253 ome_response_mock.status_code = 200 254 self.module.device_fact_error_report = { 255 Constants.service_tag1: "Duplicate report of device_id: {0}".format(Constants.device_id1)} 256 result = self._run_module(ome_default_args) 257 assert result['changed'] is False 258 assert 'device_info' in result 259 260 def test_main_detailed_inventory_device_fact_error_report_case_02(self, ome_default_args, module_mock, 261 validate_device_inputs_mock, 262 ome_connection_mock, 263 get_device_resource_parameters_mock, 264 ome_response_mock): 265 ome_default_args.update( 266 {"fact_subset": "detailed_inventory", "system_query_options": {"device_id": [Constants.device_id1], 267 "device_service_tag": [ 268 Constants.service_tag1]}}) 269 detailed_inventory = { 270 "device_service_tag": { 271 Constants.service_tag1: "DeviceService/Devices(4321)/InventoryDetails" 272 } 273 } 274 get_device_resource_parameters_mock.return_value = detailed_inventory 275 ome_response_mock.json_data = {"value": [{"device_id": {Constants.device_id1: "details"}}, 276 {"device_service_tag": {Constants.service_tag1: "details"}}]} 277 ome_response_mock.status_code = 200 278 self.module.device_fact_error_report = { 279 Constants.service_tag1: "Duplicate report of device_id: {0}".format(Constants.device_id1)} 280 result = self._run_module(ome_default_args) 281 assert result['changed'] is False 282 assert 'device_info' in result 283