1# -*- coding: utf-8 -*- 2 3# 4# Dell EMC OpenManage Ansible Modules 5# Version 3.2.0 6# Copyright (C) 2021 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 16import json 17from ansible_collections.dellemc.openmanage.plugins.modules import ome_configuration_compliance_baseline 18from ansible_collections.dellemc.openmanage.tests.unit.plugins.modules.common import FakeAnsibleModule, Constants 19from ansible.module_utils.six.moves.urllib.error import URLError, HTTPError 20from ansible.module_utils.urls import ConnectionError, SSLValidationError 21from ssl import SSLError 22from io import StringIO 23from ansible.module_utils._text import to_text 24 25MODULE_PATH = 'ansible_collections.dellemc.openmanage.plugins.modules.ome_configuration_compliance_baseline.' 26INVALID_DEVICES = "{identifier} details are not available." 27TEMPLATE_ID_ERROR_MSG = "Template with ID '{0}' not found." 28TEMPLATE_NAME_ERROR_MSG = "Template '{0}' not found." 29NAMES_ERROR = "Only delete operations accept multiple baseline names. All the other operations accept only a single " \ 30 "baseline name." 31BASELINE_CHECK_MODE_CHANGE_MSG = "Baseline '{name}' already exists." 32CHECK_MODE_CHANGES_MSG = "Changes found to be applied." 33CHECK_MODE_NO_CHANGES_MSG = "No changes found to be applied." 34BASELINE_CHECK_MODE_NOCHANGE_MSG = "Baseline '{name}' does not exist." 35CREATE_MSG = "Successfully created the configuration compliance baseline." 36DELETE_MSG = "Successfully deleted the configuration compliance baseline(s)." 37TASK_PROGRESS_MSG = "The initiated task for the configuration compliance baseline is in progress." 38CREATE_FAILURE_PROGRESS_MSG = "The initiated task for the configuration compliance baseline has failed" 39INVALID_IDENTIFIER = "Target with {identifier} {invalid_val} not found." 40IDEMPOTENCY_MSG = "The specified configuration compliance baseline details are the same as the existing settings." 41INVALID_COMPLIANCE_IDENTIFIER = "Unable to complete the operation because the entered target {0} {1}" \ 42 " is not associated with the baseline '{2}'." 43INVALID_TIME = "job_wait_timeout {0} is not valid." 44REMEDIATE_MSG = "Successfully completed the remediate operation." 45MODIFY_MSG = "Successfully modified the configuration compliance baseline." 46JOB_FAILURE_PROGRESS_MSG = "The initiated task for the configuration compliance baseline has failed." 47 48device_info = { 49 "value": [ 50 { 51 "Id": Constants.device_id1, 52 "Type": 2000, 53 "Identifier": Constants.service_tag1, 54 "DeviceServiceTag": Constants.service_tag1, 55 "ChassisServiceTag": None, 56 "Model": "PowerEdge MX7000", 57 "PowerState": 17, 58 "DeviceCapabilities": [33, 11], 59 "ManagedState": 3000, 60 "Status": 1000, 61 "ConnectionState": True, 62 "SystemId": 2031, 63 "DeviceName": "MX-MOCK" 64 }, 65 { 66 "Id": Constants.device_id2, 67 "Type": 2000, 68 "Identifier": Constants.service_tag2, 69 "DeviceServiceTag": Constants.service_tag2, 70 "ChassisServiceTag": None, 71 "Model": "PowerEdge MX7000", 72 "PowerState": 17, 73 "ManagedState": 3000, 74 "Status": 1000, 75 "ConnectionState": True, 76 "SystemId": 2031, 77 "DeviceName": "MX-MOCK" 78 } 79 ] 80} 81 82group_info = { 83 "@odata.count": 2, 84 "value": [ 85 { 86 "Id": Constants.device_id1, 87 "Name": "Network Mock", 88 }, 89 { 90 "Id": Constants.device_id2, 91 "Name": "OEM Mock", 92 } 93 ] 94} 95 96baseline_info = { 97 "@odata.count": 1, 98 "value": [ 99 { 100 "@odata.type": "#TemplateService.Baseline", 101 "@odata.id": "/api/TemplateService/Baselines(30)", 102 "Id": 30, 103 "Name": "baseline5", 104 "Description": None, 105 "TemplateId": 102, 106 "TemplateName": "one", 107 "TemplateType": 2, 108 "TaskId": 26606, 109 "PercentageComplete": "100", 110 "TaskStatus": 2070, 111 "LastRun": "2021-03-02 19:29:31.503", 112 "BaselineTargets": [ 113 { 114 "Id": 10074, 115 "Type": { 116 "Id": 1000, 117 "Name": "DEVICE" 118 } 119 } 120 ], 121 "ConfigComplianceSummary": { 122 "ComplianceStatus": "OK", 123 "NumberOfCritical": 0, 124 "NumberOfWarning": 0, 125 "NumberOfNormal": 0, 126 "NumberOfIncomplete": 0 127 }, 128 "DeviceConfigComplianceReports@odata.navigationLink": "/api/TemplateService/Baselines(30)/DeviceConfigComplianceReports" 129 } 130 ] 131} 132 133baseline_output = { 134 "Id": 30, 135 "Name": "baseline5", 136 "Description": None, 137 "TemplateId": 102, 138 "TemplateName": "one", 139 "TemplateType": 2, 140 "TaskId": 26606, 141 "PercentageComplete": "100", 142 "TaskStatus": 2070, 143 "LastRun": "2021-03-02 19:29:31.503", 144 "BaselineTargets": [ 145 { 146 "Id": 10074, 147 "Type": { 148 "Id": 1000, 149 "Name": "DEVICE" 150 } 151 } 152 ], 153 "ConfigComplianceSummary": { 154 "ComplianceStatus": "OK", 155 "NumberOfCritical": 0, 156 "NumberOfWarning": 0, 157 "NumberOfNormal": 0, 158 "NumberOfIncomplete": 0 159 }, 160} 161 162compliance_report = { 163 "@odata.count": 2, 164 "value": [ 165 { 166 "@odata.id": "/api/TemplateService/Baselines(30)/DeviceConfigComplianceReports({0})".format( 167 Constants.device_id1), 168 "Id": Constants.device_id1, 169 "DeviceName": "mock_devicename", 170 "Model": "mock_model", 171 "ServiceTag": Constants.service_tag1, 172 "ComplianceStatus": "COMPLIANT", 173 "DeviceType": 1000, 174 "InventoryTime": "2021-03-10 21:39:16.958627", 175 }, 176 { 177 "@odata.id": "/api/TemplateService/Baselines(30)/DeviceConfigComplianceReports({0})".format( 178 Constants.device_id2), 179 "Id": Constants.device_id2, 180 "DeviceName": "mock_devicename", 181 "Model": "mock_model", 182 "ServiceTag": Constants.service_tag2, 183 "ComplianceStatus": "NONCOMPLIANT", 184 "DeviceType": 1000, 185 "InventoryTime": "2021-03-10 21:39:16.958627", 186 } 187 ] 188} 189 190 191@pytest.fixture 192def ome_connection_mock_for_compliance(mocker, ome_response_mock): 193 connection_class_mock = mocker.patch(MODULE_PATH + 'RestOME') 194 ome_connection_mock_obj = connection_class_mock.return_value.__enter__.return_value 195 ome_connection_mock_obj.invoke_request.return_value = ome_response_mock 196 return ome_connection_mock_obj 197 198 199class TestOmeConfigCompBaseline(FakeAnsibleModule): 200 module = ome_configuration_compliance_baseline 201 202 @pytest.mark.parametrize("params", [{"name": "baseline", "template_name": "iDRAC 13G Enable Low Latency Profile"}, 203 {"name": "baseline", "template_id": 1}]) 204 def test_ome_configuration_get_template_details_case1(self, params, ome_response_mock, 205 ome_connection_mock_for_compliance): 206 f_module = self.get_module_mock(params=params) 207 template_info = { 208 "@odata.count": 1, 209 "value": [{ 210 "Id": 1, 211 "Name": "iDRAC 13G Enable Low Latency Profile", 212 "Description": "Tune workload for High Performance Computing Environment", 213 "SourceDeviceId": 0, 214 "TypeId": 2, 215 "ViewTypeId": 4, 216 }] 217 } 218 ome_response_mock.json_data = template_info 219 template_data = self.module.get_template_details(f_module, ome_connection_mock_for_compliance) 220 assert template_data == template_info["value"][0] 221 222 @pytest.mark.parametrize("params", [{"names": "baseline", "template_name": "iDRAC 13G Enable Low Latency Profile"}, 223 {"names": "baseline", "template_id": 1}]) 224 def test_ome_configuration_get_template_details_case2(self, params, ome_response_mock, 225 ome_connection_mock_for_compliance): 226 """ 227 when invalid template name and ids are provided 228 """ 229 f_module = self.get_module_mock(params=params) 230 template_info = { 231 "@odata.count": 1, 232 "value": [] 233 } 234 ome_response_mock.json_data = template_info 235 with pytest.raises(Exception) as err: 236 self.module.get_template_details(f_module, ome_connection_mock_for_compliance) 237 if "template_id" in params: 238 assert err.value.args[0] == TEMPLATE_ID_ERROR_MSG.format(params['template_id']) 239 else: 240 assert err.value.args[0] == TEMPLATE_NAME_ERROR_MSG.format(params['template_name']) 241 242 def test_validate_identifiers_case01(self): 243 """ 244 No exception thrown when valid device ids are passed 245 """ 246 requested_values = [Constants.device_id1, Constants.device_id2] 247 f_module = self.get_module_mock(params={"device_ids": requested_values}) 248 available_values = dict([(item["Id"], item["Identifier"]) for item in device_info["value"]]) 249 self.module.validate_identifiers(available_values.keys(), requested_values, "device_ids", f_module) 250 251 def test_validate_identifiers_case02(self): 252 """ 253 No exception thrown when valid device se tagsrvice are passed 254 """ 255 requested_values = [Constants.service_tag2, Constants.service_tag1] 256 available_values = dict([(item["Id"], item["Identifier"]) for item in device_info["value"]]) 257 f_module = self.get_module_mock(params={"device_service_tags": requested_values}) 258 self.module.validate_identifiers(available_values.values(), requested_values, "device_service_tags", f_module) 259 260 @pytest.mark.parametrize("val", [[Constants.service_tag1, "abc", "xyz"], ["abc", "xyz"]]) 261 def test_validate_identifiers_case03(self, val): 262 """ 263 Exception should be thrown when invalid service tags are passed 264 """ 265 requested_values = val 266 f_module = self.get_module_mock(params={"device_service_tags": requested_values}) 267 available_values = dict([(item["Id"], item["Identifier"]) for item in device_info["value"]]) 268 with pytest.raises(Exception) as err: 269 self.module.validate_identifiers(available_values.values(), requested_values, "device_service_tags", 270 f_module) 271 assert err.value.args[0].find("Target with device_service_tags") != -1 272 273 def test_get_identifiers_case01(self): 274 """ 275 get the device id from serivice tags 276 """ 277 available_identifiers_map = dict([(item["Id"], item["Identifier"]) for item in device_info["value"]]) 278 requested_values = [Constants.service_tag1] 279 val = self.module.get_identifiers(available_identifiers_map, requested_values) 280 assert val == [Constants.device_id1] 281 282 def test_get_identifiers_case02(self): 283 """ 284 get the group id from group Names 285 """ 286 available_identifiers_map = dict([(item["Id"], item["Name"]) for item in group_info["value"]]) 287 requested_values = ["OEM Mock"] 288 val = self.module.get_identifiers(available_identifiers_map, requested_values) 289 assert val == [Constants.device_id2] 290 291 def test_get_group_ids(self, ome_connection_mock_for_compliance): 292 """ 293 success case 294 """ 295 f_module = self.get_module_mock(params={"device_group_names": ["OEM Mock"], "command": "create", 296 "template_id": 2}) 297 ome_connection_mock_for_compliance.get_all_items_with_pagination.return_value = { 298 "total_count": group_info["@odata.count"], "value": group_info["value"]} 299 value = self.module.get_group_ids(f_module, ome_connection_mock_for_compliance) 300 assert value == [Constants.device_id2] 301 302 def test_get_group_ids_failure_case1(self, ome_connection_mock_for_compliance): 303 """ 304 success case 305 """ 306 f_module = self.get_module_mock(params={"device_group_names": ["OEM Mock Invalid"], "command": "create", 307 "template_id": 2}) 308 ome_connection_mock_for_compliance.get_all_items_with_pagination.return_value = { 309 "total_count": group_info["@odata.count"], 310 "value": group_info["value"] 311 } 312 with pytest.raises(Exception) as err: 313 self.module.get_group_ids(f_module, ome_connection_mock_for_compliance) 314 assert err.value.args[0] == "Target with device_group_names OEM Mock Invalid not found." 315 316 def test_get_group_ids_failure_case2(self, ome_connection_mock_for_compliance): 317 """ 318 success case 319 """ 320 f_module = self.get_module_mock(params={"device_group_names": ["OEM Mock Invalid"], "command": "create", 321 "template_id": 2}) 322 ome_connection_mock_for_compliance.get_all_items_with_pagination.return_value = { 323 "total_count": group_info["@odata.count"], 324 "value": [] 325 } 326 with pytest.raises(Exception) as err: 327 self.module.get_group_ids(f_module, ome_connection_mock_for_compliance) 328 assert err.value.args[0] == INVALID_DEVICES.format(identifier="Group") 329 330 def test_get_device_ids_case01(self, ome_response_mock, ome_connection_mock_for_compliance): 331 f_module = self.get_module_mock( 332 params={"device_ids": [Constants.device_id2, Constants.device_id1], "command": "create", 333 "template_id": 2}) 334 ome_connection_mock_for_compliance.get_all_report_details.return_value = { 335 "resp_obj": ome_response_mock, "report_list": device_info["value"]} 336 value, compatible_map = self.module.get_device_ids(f_module, ome_connection_mock_for_compliance) 337 assert value == [Constants.device_id2, Constants.device_id1] 338 assert compatible_map == {"capable": [Constants.device_id1], "non_capable": [Constants.device_id2]} 339 340 def test_get_device_ids_case2(self, ome_response_mock, ome_connection_mock_for_compliance): 341 f_module = self.get_module_mock(params={"device_service_tags": [Constants.service_tag1], "command": "create", 342 "template_id": 2}) 343 ome_connection_mock_for_compliance.get_all_report_details.return_value = { 344 "resp_obj": ome_response_mock, "report_list": device_info["value"]} 345 value, compatible_map = self.module.get_device_ids(f_module, ome_connection_mock_for_compliance) 346 assert value == [Constants.device_id1] 347 assert compatible_map == {"capable": [Constants.service_tag1], "non_capable": [Constants.service_tag2]} 348 349 def test_get_device_ids_case01_failurecase(self, ome_response_mock, ome_connection_mock_for_compliance): 350 f_module = self.get_module_mock(params={"device_ids": [100], "command": "create", 351 "template_id": 2}) 352 ome_connection_mock_for_compliance.get_all_report_details.return_value = { 353 "resp_obj": ome_response_mock, "report_list": device_info["value"]} 354 with pytest.raises(Exception) as err: 355 self.module.get_device_ids(f_module, ome_connection_mock_for_compliance) 356 assert err.value.args[0] == "Target with device_ids 100 not found." 357 358 def test_get_device_ids_case2_failure_case(self, ome_response_mock, ome_connection_mock_for_compliance): 359 f_module = self.get_module_mock(params={"device_service_tags": ["xyz"], "command": "create", 360 "template_id": 2}) 361 ome_connection_mock_for_compliance.get_all_report_details.return_value = { 362 "resp_obj": ome_response_mock, "report_list": device_info["value"]} 363 with pytest.raises(Exception) as err: 364 self.module.get_device_ids(f_module, ome_connection_mock_for_compliance) 365 assert err.value.args[0] == "Target with device_service_tags xyz not found." 366 367 def test_get_device_ids_failure_case(self, ome_response_mock, ome_connection_mock_for_compliance): 368 f_module = self.get_module_mock(params={"device_ids": [Constants.device_id2], "command": "create", 369 "template_id": 2}) 370 ome_connection_mock_for_compliance.get_all_report_details.return_value = { 371 "resp_obj": ome_response_mock, "report_list": []} 372 with pytest.raises(Exception) as err: 373 self.module.get_device_ids(f_module, ome_connection_mock_for_compliance) 374 assert err.value.args[0] == INVALID_DEVICES.format(identifier="Device") 375 376 def test_create_payload_case1(self, mocker, ome_connection_mock_for_compliance): 377 f_module = self.get_module_mock( 378 params={"device_ids": [Constants.device_id1, Constants.device_id2], "command": "create", 379 "template_id": 2, "names": ["baseline1"]}) 380 mocker.patch(MODULE_PATH + 'get_device_ids', 381 return_value=([Constants.device_id1, Constants.device_id2], {})) 382 mocker.patch(MODULE_PATH + 'validate_capability', 383 return_value=None) 384 mocker.patch(MODULE_PATH + 'get_template_details', 385 return_value={"Id": 2, "Name": "template1"}) 386 payload = self.module.create_payload(f_module, ome_connection_mock_for_compliance) 387 assert payload == { 388 "Name": "baseline1", 389 "TemplateId": 2, 390 "BaselineTargets": [{"Id": Constants.device_id1}, 391 {"Id": Constants.device_id2}] 392 } 393 394 def test_create_payload_case2(self, mocker, ome_connection_mock_for_compliance): 395 f_module = self.get_module_mock( 396 params={"device_service_tags": [Constants.service_tag1, Constants.service_tag2], "command": "create", 397 "template_id": 2, "names": ["baseline1"]}) 398 mocker.patch(MODULE_PATH + 'get_device_ids', 399 return_value=([Constants.device_id1, Constants.device_id2], "map")) 400 mocker.patch(MODULE_PATH + 'validate_capability', 401 return_value=None) 402 mocker.patch(MODULE_PATH + 'get_template_details', 403 return_value={"Id": 2, "Name": "template1"}) 404 payload = self.module.create_payload(f_module, ome_connection_mock_for_compliance) 405 assert payload == { 406 "Name": "baseline1", 407 "TemplateId": 2, 408 "BaselineTargets": [{"Id": Constants.device_id1}, 409 {"Id": Constants.device_id2}] 410 } 411 412 def test_create_payload_case3(self, mocker, ome_connection_mock_for_compliance): 413 f_module = self.get_module_mock(params={"device_group_names": ["xyz"], "command": "create", 414 "template_id": 2, "names": ["baseline1"]}) 415 mocker.patch(MODULE_PATH + 'get_group_ids', 416 return_value=[Constants.device_id1, Constants.device_id2]) 417 mocker.patch(MODULE_PATH + 'get_template_details', 418 return_value={"Id": 2, "Name": "template1"}) 419 payload = self.module.create_payload(f_module, ome_connection_mock_for_compliance) 420 assert payload == { 421 "Name": "baseline1", 422 "TemplateId": 2, 423 "BaselineTargets": [{"Id": Constants.device_id1}, 424 {"Id": Constants.device_id2}] 425 } 426 427 def test_get_baseline_compliance_info(self, ome_connection_mock_for_compliance): 428 ome_connection_mock_for_compliance.get_all_items_with_pagination.return_value = baseline_info 429 val = self.module.get_baseline_compliance_info(ome_connection_mock_for_compliance, "baseline5", "Name") 430 assert val == baseline_output 431 432 def test_get_baseline_compliance_info_case2(self, ome_connection_mock_for_compliance): 433 ome_connection_mock_for_compliance.get_all_items_with_pagination.return_value = baseline_info 434 val = self.module.get_baseline_compliance_info(ome_connection_mock_for_compliance, 30, "Id") 435 assert val == baseline_output 436 437 def test_track_compliance_task_completion_case01(self, mocker, ome_connection_mock_for_compliance): 438 f_module = self.get_module_mock(params={"device_group_names": ["xyz"], "command": "create", 439 "template_id": 2, "names": ["baseline1"], "job_wait": True, 440 "job_wait_timeout": 600}) 441 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 442 return_value=baseline_output) 443 mocker.patch(MODULE_PATH + 'time.sleep', return_value=None) 444 msg, info = self.module.track_compliance_task_completion(ome_connection_mock_for_compliance, 30, f_module) 445 assert msg == CREATE_MSG 446 assert info == baseline_output 447 448 def test_track_compliance_task_completion_case02(self, mocker, ome_connection_mock_for_compliance): 449 baseline_output["PercentageComplete"] = 25 450 mocker.patch(MODULE_PATH + 'time.sleep', return_value=None) 451 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', return_value=baseline_output) 452 f_module = self.get_module_mock(params={"device_group_names": ["xyz"], "command": "create", 453 "template_id": 2, "names": ["baseline1"], "job_wait": True, 454 "job_wait_timeout": 600}) 455 msg, info = self.module.track_compliance_task_completion(ome_connection_mock_for_compliance, 30, f_module) 456 assert msg == TASK_PROGRESS_MSG 457 assert info == baseline_output 458 assert info["PercentageComplete"] == 25 459 460 def test_track_compliance_task_completion_case03(self, mocker, ome_connection_mock_for_compliance): 461 baseline_output["PercentageComplete"] = 25 462 mocker.patch(MODULE_PATH + 'time.sleep', return_value=None) 463 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', return_value=baseline_output) 464 f_module = self.get_module_mock(params={"device_group_names": ["xyz"], "command": "create", 465 "template_id": 2, "names": ["baseline1"], "job_wait": False, 466 "job_wait_timeout": 600}) 467 msg, info = self.module.track_compliance_task_completion(ome_connection_mock_for_compliance, 30, f_module) 468 assert msg == TASK_PROGRESS_MSG 469 assert info == baseline_output 470 assert info["PercentageComplete"] == 25 471 472 @pytest.mark.parametrize('val', [True, False]) 473 def test_validate_create_baseline_idempotency(self, mocker, val, ome_connection_mock_for_compliance): 474 f_module = self.get_module_mock(params={"names": ["baseline5"]}, check_mode=val) 475 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 476 return_value=baseline_output) 477 with pytest.raises(Exception) as err: 478 self.module.validate_create_baseline_idempotency(f_module, 479 ome_connection_mock_for_compliance) 480 assert err.value.args[0] == BASELINE_CHECK_MODE_CHANGE_MSG.format(name=baseline_output["Name"]) 481 482 def test_validate_create_baseline_idempotency_case2(self, mocker, ome_connection_mock_for_compliance): 483 f_module = self.get_module_mock(params={"names": ["baseline5"]}, check_mode=True) 484 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 485 return_value=baseline_output) 486 with pytest.raises(Exception) as err: 487 self.module.validate_create_baseline_idempotency(f_module, 488 ome_connection_mock_for_compliance) 489 assert err.value.args[0] == BASELINE_CHECK_MODE_CHANGE_MSG.format(name="baseline5") 490 491 def test_create_baseline_case01(self, mocker, ome_response_mock, ome_connection_mock_for_compliance): 492 mocker.patch(MODULE_PATH + 'validate_create_baseline_idempotency', 493 return_value=None) 494 mocker.patch(MODULE_PATH + 'create_payload', 495 return_value={}) 496 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 497 return_value=baseline_output) 498 f_module = self.get_module_mock(params={"names": ["baseline5"], "job_wait": False, "job_wait_timeout": 600}, 499 check_mode=False) 500 ome_response_mock.json_data = {"Id": 1} 501 ome_connection_mock_for_compliance.job_tracking.return_value = False, "message" 502 with pytest.raises(Exception) as err: 503 self.module.create_baseline(f_module, ome_connection_mock_for_compliance) 504 assert err.value.args[0] == TASK_PROGRESS_MSG 505 506 @pytest.mark.parametrize("val", 507 [(False, "Job completed successfully."), (False, "other message."), (True, "message2")]) 508 def test_create_baseline_case02(self, val, mocker, ome_response_mock, ome_connection_mock_for_compliance): 509 mocker.patch(MODULE_PATH + 'validate_create_baseline_idempotency', 510 return_value=None) 511 mocker.patch(MODULE_PATH + 'create_payload', 512 return_value={}) 513 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 514 return_value=baseline_output) 515 f_module = self.get_module_mock(params={"job_wait": True, "job_wait_timeout": 600}, check_mode=False) 516 ome_connection_mock_for_compliance.job_tracking.return_value = val[0], val[1] 517 ome_response_mock.json_data = {"Id": 1} 518 with pytest.raises(Exception) as err: 519 self.module.create_baseline(f_module, ome_connection_mock_for_compliance) 520 if val[0] is False and "successfully" in val[1]: 521 assert err.value.args[0] == CREATE_MSG 522 elif val[0] is False and "successfully" not in val[1]: 523 assert err.value.args[0] == val[1] 524 else: 525 assert err.value.args[0] == val[1] 526 527 def test_validate_names(self): 528 f_module = self.get_module_mock(params={"names": ["abc"]}, check_mode=False) 529 self.module.validate_names("create", f_module) 530 531 def test_validate_names_case02(self): 532 f_module = self.get_module_mock(params={"names": ["abc", "xyz"]}, check_mode=False) 533 with pytest.raises(Exception) as err: 534 self.module.validate_names("create", f_module) 535 assert err.value.args[0] == NAMES_ERROR 536 537 @pytest.mark.parametrize("command", ["create"]) 538 def test_compliance_operation(self, mocker, command, ome_connection_mock_for_compliance): 539 f_module = self.get_module_mock(params={"names": ["abc"], "command": "create"}, check_mode=False) 540 mocker.patch(MODULE_PATH + 'validate_job_time', 541 return_value=None) 542 mock_create = mocker.patch(MODULE_PATH + 'create_baseline', 543 return_value=None) 544 self.module.compliance_operation(f_module, ome_connection_mock_for_compliance) 545 assert mock_create.called 546 547 @pytest.mark.parametrize("exc_type", 548 [IOError, ValueError, SSLError, TypeError, ConnectionError, HTTPError, URLError]) 549 def test_ome_compliance_main_exception_failure_case(self, exc_type, mocker, ome_default_args, 550 ome_connection_mock_for_compliance, ome_response_mock): 551 ome_default_args.update({"template_name": "t1", "names": "baseline1"}) 552 ome_response_mock.status_code = 400 553 ome_response_mock.success = False 554 json_str = to_text(json.dumps({"info": "error_details"})) 555 if exc_type == URLError: 556 mocker.patch(MODULE_PATH + 'compliance_operation', side_effect=exc_type("url open error")) 557 result = self._run_module(ome_default_args) 558 assert result["unreachable"] is True 559 elif exc_type not in [HTTPError, SSLValidationError]: 560 mocker.patch(MODULE_PATH + 'compliance_operation', side_effect=exc_type("exception message")) 561 result = self._run_module_with_fail_json(ome_default_args) 562 assert result['failed'] is True 563 else: 564 mocker.patch(MODULE_PATH + 'compliance_operation', 565 side_effect=exc_type('http://testhost.com', 400, 'http error message', 566 {"accept-type": "application/json"}, StringIO(json_str))) 567 result = self._run_module_with_fail_json(ome_default_args) 568 assert result['failed'] is True 569 assert 'msg' in result 570 571 def test_compliance_create_argument_exception_case1(self, ome_default_args): 572 ome_default_args.update({"template_name": "t1"}) 573 result = self._run_module_with_fail_json(ome_default_args) 574 assert result["msg"] == "missing required arguments: names" 575 576 def test_compliance_create_argument_exception_case2(self, ome_default_args): 577 ome_default_args.update({"template_id": 1}) 578 result = self._run_module_with_fail_json(ome_default_args) 579 assert result["msg"] == "missing required arguments: names" 580 581 def test_compliance_create_argument_exception_case3(self, ome_default_args): 582 ome_default_args.update({"names": "baseline1"}) 583 result = self._run_module_with_fail_json(ome_default_args) 584 assert result["msg"] == "command is create but any of the following are missing: template_name, template_id" 585 586 def test_compliance_create_argument_exception_case4(self, ome_default_args): 587 ome_default_args.update({"names": "baseline1", "template_name": "t1", "template_id": 1}) 588 result = self._run_module_with_fail_json(ome_default_args) 589 assert result["msg"] == "parameters are mutually exclusive: template_id|template_name" 590 591 def test_compliance_create_argument_exception_case5(self, ome_default_args): 592 ome_default_args.update({"names": "baseline1", "device_ids": 1, "template_name": "t1", 593 "device_service_tags": "xyz"}) 594 result = self._run_module_with_fail_json(ome_default_args) 595 assert result["msg"] == "parameters are mutually exclusive: device_ids|device_service_tags" 596 597 def test_compliance_create_argument_exception_case6(self, ome_default_args): 598 ome_default_args.update({"names": "baseline1", "template_name": "t1", "device_ids": 1, 599 "device_group_names": "xyz"}) 600 result = self._run_module_with_fail_json(ome_default_args) 601 assert result["msg"] == "parameters are mutually exclusive: device_ids|device_group_names" 602 603 def test_compliance_create_argument_exception_case7(self, ome_default_args): 604 ome_default_args.update({"names": "baseline1", "template_name": "t1", "device_service_tags": "abc", 605 "device_group_names": "xyz"}) 606 result = self._run_module_with_fail_json(ome_default_args) 607 assert result["msg"] == "parameters are mutually exclusive: device_service_tags|device_group_names" 608 609 def test_compliance_create_argument_exception_case8(self, ome_default_args): 610 ome_default_args.update( 611 {"names": "baseline1", "template_name": "t1", "device_ids": 1, "device_service_tags": "xyz", 612 "device_group_names": "abc"}) 613 result = self._run_module_with_fail_json(ome_default_args) 614 assert result["msg"] == "parameters are mutually exclusive: device_ids|device_service_tags, " \ 615 "device_ids|device_group_names, device_service_tags|device_group_names" 616 617 @pytest.mark.parametrize("command", ["delete"]) 618 def test_compliance_operation_delete(self, mocker, command, ome_connection_mock_for_compliance): 619 f_module = self.get_module_mock(params={"names": ["abc"], "command": "delete"}, check_mode=False) 620 mock_delete_compliance = mocker.patch(MODULE_PATH + 'delete_compliance', 621 return_value=None) 622 mocker.patch(MODULE_PATH + 'validate_job_time', 623 return_value=None) 624 self.module.compliance_operation(f_module, ome_connection_mock_for_compliance) 625 assert mock_delete_compliance.called 626 627 def test_delete_idempotency_check_case01(self, mocker, ome_connection_mock_for_compliance): 628 mocker.patch(MODULE_PATH + 'get_identifiers', 629 return_value=[30]) 630 f_module = self.get_module_mock(params={"names": ["baseline5"]}, check_mode=False) 631 ome_connection_mock_for_compliance.get_all_items_with_pagination.return_value = baseline_info 632 val = self.module.delete_idempotency_check(f_module, ome_connection_mock_for_compliance) 633 assert val == [30] 634 635 def test_delete_idempotency_check_case02(self, mocker, ome_connection_mock_for_compliance): 636 mocker.patch(MODULE_PATH + 'get_identifiers', 637 return_value=[30]) 638 f_module = self.get_module_mock(params={"names": ["baseline5"]}, check_mode=True) 639 ome_connection_mock_for_compliance.get_all_items_with_pagination.return_value = baseline_info 640 with pytest.raises(Exception) as err: 641 self.module.delete_idempotency_check(f_module, ome_connection_mock_for_compliance) 642 assert err.value.args[0] == CHECK_MODE_CHANGES_MSG 643 644 def test_delete_idempotency_check_case03(self, mocker, ome_connection_mock_for_compliance): 645 mocker.patch(MODULE_PATH + 'get_identifiers', 646 return_value=[]) 647 f_module = self.get_module_mock(params={"names": ["baseline5"]}, check_mode=True) 648 ome_connection_mock_for_compliance.get_all_items_with_pagination.return_value = baseline_info 649 with pytest.raises(Exception) as err: 650 self.module.delete_idempotency_check(f_module, ome_connection_mock_for_compliance) 651 assert err.value.args[0] == CHECK_MODE_NO_CHANGES_MSG 652 653 def test_delete_compliance_case01(self, mocker, ome_connection_mock_for_compliance, ome_response_mock): 654 mocker.patch(MODULE_PATH + 'delete_idempotency_check', 655 return_value=[30]) 656 f_module = self.get_module_mock(params={"names": ["baseline5"]}, check_mode=False) 657 ome_response_mock.json_data = None 658 ome_response_mock.status_code = 204 659 with pytest.raises(Exception) as err: 660 self.module.delete_compliance(f_module, ome_connection_mock_for_compliance) 661 assert err.value.args[0] == DELETE_MSG 662 663 def test_compliance_operation_modify(self, mocker, ome_connection_mock_for_compliance): 664 f_module = self.get_module_mock(params={"names": ["abc"], "command": "modify"}, check_mode=False) 665 mock_modify = mocker.patch(MODULE_PATH + 'modify_baseline', 666 return_value=None) 667 mocker.patch(MODULE_PATH + 'validate_job_time', 668 return_value=None) 669 self.module.compliance_operation(f_module, ome_connection_mock_for_compliance) 670 assert mock_modify.called 671 672 @pytest.mark.parametrize("val", [(False, "Job completed successfully."), (False, "message1"), (True, "message2")]) 673 def test_modify_baseline_case01(self, val, mocker, ome_response_mock, ome_connection_mock_for_compliance): 674 payload = { 675 "Name": "baseline1", 676 "TemplateId": 2, 677 "BaselineTargets": [{"Id": Constants.device_id1}, 678 {"Id": Constants.device_id2}] 679 } 680 f_module = self.get_module_mock(params={"names": ["abc"], "command": "modify", "job_wait": True, 681 "job_wait_timeout": 600}, check_mode=False) 682 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 683 return_value=baseline_output) 684 mocker.patch(MODULE_PATH + 'create_payload', 685 return_value=payload) 686 mocker.patch(MODULE_PATH + 'idempotency_check_for_command_modify', 687 return_value=None) 688 ome_connection_mock_for_compliance.job_tracking.return_value = val[0], val[1] 689 ome_response_mock.json_data = {"Id": 1} 690 with pytest.raises(Exception) as err: 691 self.module.modify_baseline(f_module, ome_connection_mock_for_compliance) 692 if val[0] is False and "successfully" in val[1]: 693 assert err.value.args[0] == MODIFY_MSG 694 elif val[0] is False and "successfully" not in val[1]: 695 assert err.value.args[0] == val[1] 696 else: 697 assert err.value.args[0] == val[1] 698 699 def test_modify_baseline_case02(self, mocker, ome_response_mock, ome_connection_mock_for_compliance): 700 payload = { 701 "Name": "baseline1", 702 "TemplateId": 2, 703 "BaselineTargets": [{"Id": Constants.device_id1}, 704 {"Id": Constants.device_id2}] 705 } 706 f_module = self.get_module_mock( 707 params={"names": ["abc"], "command": "modify", "job_wait": False, 708 "job_wait_timeout": 600}, check_mode=False) 709 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 710 return_value=baseline_output) 711 mocker.patch(MODULE_PATH + 'create_payload', 712 return_value=payload) 713 mocker.patch(MODULE_PATH + 'idempotency_check_for_command_modify', 714 return_value=None) 715 ome_response_mock.json_data = {"Id": 1} 716 with pytest.raises(Exception) as err: 717 self.module.modify_baseline(f_module, ome_connection_mock_for_compliance) 718 assert err.value.args[0] == TASK_PROGRESS_MSG 719 720 def test_modify_baseline_case03(self, mocker, ome_response_mock, ome_connection_mock_for_compliance): 721 f_module = self.get_module_mock(params={"names": ["abc"], "command": "modify"}, check_mode=False) 722 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 723 return_value={}) 724 with pytest.raises(Exception) as err: 725 self.module.modify_baseline(f_module, ome_connection_mock_for_compliance) 726 assert err.value.args[0] == BASELINE_CHECK_MODE_NOCHANGE_MSG.format(name="abc") 727 728 def test_modify_baseline_case04(self, mocker, ome_response_mock, ome_connection_mock_for_compliance): 729 f_module = self.get_module_mock(params={"names": ["abc"], "command": "modify"}, check_mode=False) 730 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 731 return_value={}) 732 with pytest.raises(Exception) as err: 733 self.module.modify_baseline(f_module, ome_connection_mock_for_compliance) 734 assert err.value.args[0] == BASELINE_CHECK_MODE_NOCHANGE_MSG.format(name="abc") 735 736 def test_idempotency_check_for_command_modify_case1(self, mocker): 737 f_module = self.get_module_mock(params={"names": ["abc"], "command": "modify"}, check_mode=True) 738 mocker.patch(MODULE_PATH + 'compare_payloads', 739 return_value="diff") 740 with pytest.raises(Exception) as err: 741 self.module.idempotency_check_for_command_modify("current_payload", "expected_payload", f_module) 742 assert err.value.args[0] == CHECK_MODE_CHANGES_MSG 743 744 def test_idempotency_check_for_command_modify_case2(self, mocker): 745 f_module = self.get_module_mock(params={"names": ["abc"], "command": "modify"}, check_mode=True) 746 mocker.patch(MODULE_PATH + 'compare_payloads', 747 return_value=None) 748 with pytest.raises(Exception) as err: 749 self.module.idempotency_check_for_command_modify("current_payload", "expected_payload", f_module) 750 assert err.value.args[0] == CHECK_MODE_NO_CHANGES_MSG 751 752 def test_idempotency_check_for_command_modify_case3(self, mocker): 753 f_module = self.get_module_mock(params={"names": ["abc"], "command": "modify"}, check_mode=False) 754 mocker.patch(MODULE_PATH + 'compare_payloads', 755 return_value={}) 756 with pytest.raises(Exception) as err: 757 self.module.idempotency_check_for_command_modify("current_payload", "expected_payload", f_module) 758 assert err.value.args[0] == IDEMPOTENCY_MSG 759 760 @pytest.mark.parametrize("modify_payload", [{"Id": 29, "Name": "baselin9", "TemplateId": 102}, 761 {"Id": 29, "Name": "baselin8", "TemplateId": 103}, 762 {"Id": 29, "Name": "baselin8", "TemplateId": 102, 763 "BaselineTargets": [{"Id": 10074}]}, 764 {"Id": 29, "Name": "baselin8", "TemplateId": 102, 765 "BaselineTargets": [{"Id": 10079}]}, 766 {"Id": 29, "Name": "baselin8", "TemplateId": 102, 767 "BaselineTargets": [{"Id": 10075}, 768 {"Id": 10074}]} 769 ]) 770 def test_compliance_compare_payloads_diff_case_01(self, modify_payload): 771 current_payload = { 772 "Id": 29, 773 "Name": "baselin8", 774 "Description": "desc", 775 "TemplateId": 102, 776 "BaselineTargets": [ 777 { 778 "Id": 10075 779 } 780 ] 781 } 782 val = self.module.compare_payloads(modify_payload, current_payload) 783 assert val is True 784 785 @pytest.mark.parametrize("current_payload", [{"Id": 29, "Name": "baselin8", "Description": "desc1"}, 786 {"Id": 29, "Name": "baselin9", "TemplateId": 102}, 787 {"Id": 29, "Name": "baselin8", "TemplateId": 103}, 788 {"Id": 29, "Name": "baselin8", "TemplateId": 102, 789 "BaselineTargets": [{"Id": 10074}]}, 790 {"Id": 29, "Name": "baselin8", "TemplateId": 102, 791 "BaselineTargets": [{"Id": 10079}]}]) 792 def test_compliance_compare_payloads_diff_case_02(self, current_payload): 793 modify_payload = { 794 "Id": 29, 795 "Name": "baselin8", 796 "Description": "desc", 797 "TemplateId": 102, 798 "BaselineTargets": [ 799 { 800 "Id": 10075 801 } 802 ] 803 } 804 val = self.module.compare_payloads(modify_payload, current_payload) 805 assert val is True 806 807 @pytest.mark.parametrize("modify_payload", [{"Id": 29, "Name": "baselin8", "TemplateId": 102}, 808 {"Id": 29, "Name": "baselin8", "Description": "desc"}, 809 {"Id": 29, "Name": "baselin8", 810 "BaselineTargets": [{"Id": 10075}]}]) 811 def test_compliance_compare_payloads_no_diff_case_03(self, modify_payload): 812 current_payload = { 813 "Id": 29, 814 "Name": "baselin8", 815 "Description": "desc", 816 "TemplateId": 102, 817 "BaselineTargets": [ 818 { 819 "Id": 10075 820 } 821 ] 822 } 823 val = self.module.compare_payloads(modify_payload, current_payload) 824 assert val is False 825 826 def test_get_ome_version(self, ome_response_mock, ome_connection_mock_for_compliance): 827 ome_response_mock.json_data = { 828 "Name": "OM Enterprise", 829 "Description": "OpenManage Enterprise", 830 "Vendor": "Dell, Inc.", 831 "ProductType": 1, 832 "Version": "3.4.1", 833 "BuildNumber": "24", 834 "OperationJobId": 0 835 } 836 version = self.module.get_ome_version(ome_connection_mock_for_compliance) 837 assert version == "3.4.1" 838 839 def validate_validate_remediate_idempotency_with_device_ids(self, mocker, ome_connection_mock_for_compliance): 840 f_module = self.get_module_mock( 841 params={"device_ids": [Constants.device_id2, Constants.device_id1], "command": "remediate", 842 "names": ["baseline1"]}) 843 mocker.patch(MODULE_PATH + 'get_device_ids', 844 return_value=([Constants.device_id2, Constants.device_id1], "map")) 845 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 846 return_value=baseline_output) 847 ome_connection_mock_for_compliance.get_all_items_with_pagination.return_value = { 848 "total_count": compliance_report["@odata.count"], "value": compliance_report["value"]} 849 noncomplaint_devices, baseline_info = self.module.validate_remediate_idempotency(f_module, 850 ome_connection_mock_for_compliance) 851 assert noncomplaint_devices == [Constants.device_id2] 852 assert baseline_info == baseline_output 853 854 def validate_validate_remediate_idempotency_with_service_tags(self, mocker, ome_connection_mock_for_compliance): 855 f_module = self.get_module_mock( 856 params={"device_ids": [Constants.service_tag1, Constants.service_tag2], "command": "remediate", 857 "names": ["baseline1"]}) 858 mocker.patch(MODULE_PATH + 'get_device_ids', 859 return_value=([Constants.device_id2, Constants.device_id1], "map")) 860 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 861 return_value=baseline_output) 862 ome_connection_mock_for_compliance.get_all_items_with_pagination.return_value = { 863 "total_count": compliance_report["@odata.count"], "value": compliance_report["value"]} 864 noncomplaint_devices, baseline_info = self.module.validate_remediate_idempotency(f_module, 865 ome_connection_mock_for_compliance) 866 assert noncomplaint_devices == [Constants.device_id2] 867 assert baseline_info == baseline_output 868 869 def validate_validate_remediate_idempotency_without_devices(self, mocker, ome_connection_mock_for_compliance): 870 f_module = self.get_module_mock( 871 params={"command": "remediate", "names": ["baseline1"]}) 872 mocker.patch(MODULE_PATH + 'get_device_ids', 873 return_value=([Constants.device_id2, Constants.device_id1], "map")) 874 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 875 return_value=baseline_output) 876 ome_connection_mock_for_compliance.get_all_items_with_pagination.return_value = { 877 "total_count": compliance_report["@odata.count"], "value": compliance_report["value"]} 878 noncomplaint_devices, baseline_info = self.module.validate_remediate_idempotency(f_module, 879 ome_connection_mock_for_compliance) 880 assert noncomplaint_devices == [Constants.device_id2] 881 assert baseline_info == baseline_output 882 883 def validate_validate_remediate_idempotency_wen_all_complaint(self, mocker, ome_connection_mock_for_compliance): 884 f_module = self.get_module_mock( 885 params={"command": "remediate", "names": ["baseline1"]}) 886 mocker.patch(MODULE_PATH + 'get_device_ids', 887 return_value=([Constants.device_id2, Constants.device_id1], "map")) 888 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 889 return_value=baseline_output) 890 report = { 891 "@odata.count": 2, 892 "value": [ 893 { 894 "Id": Constants.device_id1, 895 "ServiceTag": Constants.service_tag1, 896 "ComplianceStatus": "COMPLIANT" 897 }, 898 { 899 "Id": Constants.device_id2, 900 "ServiceTag": Constants.service_tag2, 901 "ComplianceStatus": "COMPLIANT" 902 } 903 ] 904 } 905 ome_connection_mock_for_compliance.get_all_items_with_pagination.return_value = { 906 "total_count": report["@odata.count"], "value": report["value"]} 907 with pytest.raises(Exception) as err: 908 self.module.validate_remediate_idempotency(f_module, ome_connection_mock_for_compliance) 909 assert err.value.args[0] == CHECK_MODE_NO_CHANGES_MSG 910 911 def validate_validate_remediate_idempotency_without_devices_check_mode(self, mocker, 912 ome_connection_mock_for_compliance): 913 f_module = self.get_module_mock( 914 params={"command": "remediate", "names": ["baseline1"]}, check_mode=True) 915 mocker.patch(MODULE_PATH + 'get_device_ids', 916 return_value=([Constants.device_id2, Constants.device_id1], "map")) 917 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 918 return_value=baseline_output) 919 ome_connection_mock_for_compliance.get_all_items_with_pagination.return_value = { 920 "total_count": compliance_report["@odata.count"], "value": compliance_report["value"]} 921 with pytest.raises(Exception) as err: 922 self.module.validate_remediate_idempotency(f_module, ome_connection_mock_for_compliance) 923 assert err.value.args[0] == CHECK_MODE_CHANGES_MSG 924 925 @pytest.mark.parametrize("val", ["3.4.1", "3.4.5", "3.4.0", "3.4", "3.3", "3.3.0", "3.0.0", "2.1"]) 926 def test_create_remediate_payload_case01_for_old_releases(self, val, mocker, ome_connection_mock_for_compliance): 927 mocker.patch(MODULE_PATH + 'get_ome_version', 928 return_value=val) 929 payload = self.module.create_remediate_payload([Constants.device_id1], baseline_output, 930 ome_connection_mock_for_compliance) 931 assert "TargetIds" in payload 932 933 @pytest.mark.parametrize("val", ["3.5.1", "3.5.5", "3.5.0", "3.5"]) 934 def test_create_remediate_payload_case01_for_new_releases(self, val, mocker, ome_connection_mock_for_compliance): 935 mocker.patch(MODULE_PATH + 'get_ome_version', 936 return_value=val) 937 payload = self.module.create_remediate_payload([Constants.device_id1], baseline_output, 938 ome_connection_mock_for_compliance) 939 assert "DeviceIds" in payload 940 941 def test_remediate_baseline_case1(self, mocker, ome_connection_mock_for_compliance, ome_response_mock): 942 f_module = self.get_module_mock( 943 params={"command": "remediate", "names": ["baseline1"], "job_wait": True, "job_wait_timeout": 600}, 944 check_mode=True) 945 mocker.patch(MODULE_PATH + 'validate_remediate_idempotency', 946 return_value=([Constants.device_id1], baseline_output)) 947 mocker.patch(MODULE_PATH + 'create_remediate_payload', 948 return_value="payload") 949 ome_response_mock.json_data = 1234 950 ome_connection_mock_for_compliance.job_tracking.return_value = True, "job fail message" 951 with pytest.raises(Exception) as err: 952 self.module.remediate_baseline(f_module, ome_connection_mock_for_compliance) 953 assert err.value.args[0] == "job fail message" 954 955 def test_remediate_baseline_case2(self, mocker, ome_connection_mock_for_compliance, ome_response_mock): 956 f_module = self.get_module_mock( 957 params={"command": "remediate", "names": ["baseline1"], "job_wait": True, "job_wait_timeout": 600}, 958 check_mode=True) 959 mocker.patch(MODULE_PATH + 'validate_remediate_idempotency', 960 return_value=([Constants.device_id1], baseline_output)) 961 mocker.patch(MODULE_PATH + 'create_remediate_payload', 962 return_value="payload") 963 ome_response_mock.json_data = 1234 964 ome_connection_mock_for_compliance.job_tracking.return_value = False, "Job completed successfully." 965 with pytest.raises(Exception) as err: 966 self.module.remediate_baseline(f_module, ome_connection_mock_for_compliance) 967 assert err.value.args[0] == REMEDIATE_MSG 968 969 def test_remediate_baseline_case3(self, mocker, ome_connection_mock_for_compliance, ome_response_mock): 970 f_module = self.get_module_mock( 971 params={"command": "remediate", "names": ["baseline1"], "job_wait": False, "job_wait_timeout": 600}, 972 check_mode=True) 973 mocker.patch(MODULE_PATH + 'validate_remediate_idempotency', 974 return_value=([Constants.device_id1], baseline_output)) 975 mocker.patch(MODULE_PATH + 'create_remediate_payload', 976 return_value="payload") 977 ome_response_mock.json_data = 1234 978 with pytest.raises(Exception) as err: 979 self.module.remediate_baseline(f_module, ome_connection_mock_for_compliance) 980 assert err.value.args[0] == TASK_PROGRESS_MSG 981 982 @pytest.mark.parametrize("inparams", [{"command": "create", "names": ["baseline1"], 983 "job_wait": True, "job_wait_timeout": 0}, 984 {"command": "modify", "names": ["baseline1"], "job_wait": True, 985 "job_wait_timeout": 0}]) 986 def test_validate_job_time(self, inparams): 987 command = inparams['command'] 988 f_module = self.get_module_mock( 989 params=inparams) 990 with pytest.raises(Exception) as err: 991 self.module.validate_job_time(command, f_module) 992 assert err.value.args[0] == INVALID_TIME.format(inparams["job_wait_timeout"]) 993 994 @pytest.mark.parametrize("command", ["remediate"]) 995 def test_compliance_remediate_operation(self, mocker, command, ome_connection_mock_for_compliance): 996 f_module = self.get_module_mock(params={"names": ["abc"], "command": "remediate"}, check_mode=False) 997 mocker.patch(MODULE_PATH + 'validate_job_time', 998 return_value=None) 999 mock_remediate = mocker.patch(MODULE_PATH + 'remediate_baseline', 1000 return_value=None) 1001 self.module.compliance_operation(f_module, ome_connection_mock_for_compliance) 1002 assert mock_remediate.called 1003 1004 @pytest.mark.parametrize("inparams", [{"command": "modify", "names": ["baseline1"], "job_wait": True, 1005 "job_wait_timeout": 1}, 1006 {"command": "modify", "names": ["baseline1"], "job_wait": False, 1007 "job_wait_timeout": 1}, 1008 {"command": "delete", "names": ["baseline1"], "job_wait": True, 1009 "job_wait_timeout": 1}, 1010 ]) 1011 def test_validate_job_time_no_err_case(self, inparams): 1012 command = inparams['command'] 1013 f_module = self.get_module_mock( 1014 params=inparams) 1015 self.module.validate_job_time(command, f_module) 1016 1017 def test_remediate_baseline_case4(self, mocker, ome_connection_mock_for_compliance, ome_response_mock): 1018 f_module = self.get_module_mock( 1019 params={"command": "remediate", "names": ["baseline1"], "job_wait": True, "job_wait_timeout": 600}, 1020 check_mode=True) 1021 mocker.patch(MODULE_PATH + 'validate_remediate_idempotency', 1022 return_value=([Constants.device_id1], baseline_output)) 1023 mocker.patch(MODULE_PATH + 'create_remediate_payload', 1024 return_value="payload") 1025 ome_response_mock.json_data = 1234 1026 ome_connection_mock_for_compliance.job_tracking.return_value = False, "Job is running." 1027 with pytest.raises(Exception) as err: 1028 self.module.remediate_baseline(f_module, ome_connection_mock_for_compliance) 1029 assert err.value.args[0] == "Job is running." 1030 1031 def test_modify_baseline_case05(self, mocker, ome_response_mock, ome_connection_mock_for_compliance): 1032 payload = { 1033 "Name": "baseline1", 1034 "TemplateId": 2 1035 } 1036 f_module = self.get_module_mock(params={"names": ["abc"], "command": "modify", "job_wait": False, 1037 "job_wait_timeout": 600}, check_mode=False) 1038 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 1039 return_value=baseline_output) 1040 mocker.patch(MODULE_PATH + 'create_payload', 1041 return_value=payload) 1042 mocker.patch(MODULE_PATH + 'idempotency_check_for_command_modify', 1043 return_value=None) 1044 ome_response_mock.json_data = {"Id": 1} 1045 with pytest.raises(Exception) as err: 1046 self.module.modify_baseline(f_module, ome_connection_mock_for_compliance) 1047 assert err.value.args[0] == TASK_PROGRESS_MSG 1048 1049 def test_validate_create_baseline_idempotency_case3(self, mocker, ome_connection_mock_for_compliance): 1050 f_module = self.get_module_mock(params={"names": ["baseline5"]}, check_mode=True) 1051 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 1052 return_value={}) 1053 with pytest.raises(Exception) as err: 1054 self.module.validate_create_baseline_idempotency(f_module, 1055 ome_connection_mock_for_compliance) 1056 assert err.value.args[0] == CHECK_MODE_CHANGES_MSG 1057 1058 def test_validate_capability_no_err_case01(self): 1059 capability_map = {"capable": [Constants.device_id1], "non_capable": [Constants.device_id2], } 1060 f_module = self.get_module_mock(params={"device_ids": [Constants.device_id1]}, check_mode=True) 1061 self.module.validate_capability(f_module, capability_map) 1062 1063 def test_validate_capability_no_err_case02(self): 1064 capability_map = {"capable": [Constants.service_tag1], "non_capable": [Constants.service_tag2]} 1065 f_module = self.get_module_mock(params={"device_service_tags": [Constants.service_tag1]}, check_mode=True) 1066 self.module.validate_capability(f_module, capability_map) 1067 1068 def test_validate_capability_err_case01(self): 1069 NO_CAPABLE_DEVICES = "Target device_service_tags contains devices which cannot be used for a baseline " \ 1070 "compliance operation." 1071 capability_map = {"capable": [Constants.service_tag2], "non_capable": [Constants.service_tag1]} 1072 f_module = self.get_module_mock(params={"device_service_tags": [Constants.service_tag1]}, check_mode=True) 1073 with pytest.raises(Exception) as err: 1074 self.module.validate_capability(f_module, capability_map) 1075 assert err.value.args[0] == NO_CAPABLE_DEVICES 1076 1077 def test_validate_remediate_idempotency_case01(self, mocker, ome_connection_mock_for_compliance): 1078 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 1079 return_value={}) 1080 f_module = self.get_module_mock(params={"names": ["name1"]}, check_mode=True) 1081 with pytest.raises(Exception) as err: 1082 self.module.validate_remediate_idempotency(f_module, ome_connection_mock_for_compliance) 1083 assert err.value.args[0] == BASELINE_CHECK_MODE_NOCHANGE_MSG.format(name="name1") 1084 1085 def test_validate_remediate_idempotency_case02(self, mocker, ome_connection_mock_for_compliance): 1086 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 1087 return_value=baseline_output) 1088 compliance_status = [ 1089 { 1090 "Id": Constants.device_id1, 1091 "DeviceName": "XX.XXX.X.XXX", 1092 "IpAddresses": [ 1093 "XX.XXX.X.XXX" 1094 ], 1095 "Model": "PowerEdge MX840c", 1096 "ServiceTag": Constants.service_tag1, 1097 "ComplianceStatus": 1, 1098 "DeviceType": 1000, 1099 "InventoryTime": "2020-10-05 18:28:09.842072" 1100 } 1101 ] 1102 f_module = self.get_module_mock(params={"names": ["name1"], "device_ids": [Constants.device_id1]}, 1103 check_mode=True) 1104 capability_map = {"capable": [Constants.service_tag1], "non_capable": [Constants.service_tag2]} 1105 mocker.patch(MODULE_PATH + 'get_device_ids', 1106 return_value=([Constants.device_id2, Constants.device_id1], capability_map)) 1107 ome_connection_mock_for_compliance.get_all_items_with_pagination.return_value = { 1108 "total_count": 1, "value": compliance_status} 1109 with pytest.raises(Exception) as err: 1110 self.module.validate_remediate_idempotency(f_module, ome_connection_mock_for_compliance) 1111 assert err.value.args[0] == CHECK_MODE_NO_CHANGES_MSG 1112 1113 def test_validate_remediate_idempotency_case03(self, mocker, ome_connection_mock_for_compliance): 1114 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 1115 return_value=baseline_output) 1116 compliance_status = [ 1117 { 1118 "Id": Constants.device_id1, 1119 "DeviceName": "XX.XXX.X.XXX", 1120 "IpAddresses": [ 1121 "XX.XXX.X.XXX" 1122 ], 1123 "Model": "PowerEdge MX840c", 1124 "ServiceTag": Constants.service_tag1, 1125 "ComplianceStatus": 2, 1126 "DeviceType": 1000, 1127 "InventoryTime": "2020-10-05 18:28:09.842072" 1128 } 1129 ] 1130 f_module = self.get_module_mock(params={"names": ["name1"], "device_ids": [Constants.device_id1]}, 1131 check_mode=True) 1132 capability_map = {"capable": [Constants.service_tag1], "non_capable": [Constants.service_tag2]} 1133 mocker.patch(MODULE_PATH + 'get_device_ids', 1134 return_value=([Constants.device_id2, Constants.device_id1], capability_map)) 1135 ome_connection_mock_for_compliance.get_all_items_with_pagination.return_value = { 1136 "total_count": 1, "value": compliance_status} 1137 with pytest.raises(Exception) as err: 1138 self.module.validate_remediate_idempotency(f_module, ome_connection_mock_for_compliance) 1139 assert err.value.args[0] == CHECK_MODE_CHANGES_MSG 1140 1141 def test_validate_remediate_idempotency_case04(self, mocker, ome_connection_mock_for_compliance): 1142 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 1143 return_value=baseline_output) 1144 compliance_status = [ 1145 { 1146 "Id": Constants.device_id1, 1147 "DeviceName": "XX.XXX.X.XXX", 1148 "IpAddresses": [ 1149 "XX.XXX.X.XXX" 1150 ], 1151 "Model": "PowerEdge MX840c", 1152 "ServiceTag": Constants.service_tag1, 1153 "ComplianceStatus": 2, 1154 "DeviceType": 1000, 1155 "InventoryTime": "2020-10-05 18:28:09.842072" 1156 } 1157 ] 1158 f_module = self.get_module_mock(params={"names": ["name1"], "device_service_tags": [Constants.service_tag1]}, 1159 check_mode=True) 1160 capability_map = {"capable": [Constants.service_tag1], "non_capable": [Constants.service_tag2]} 1161 mocker.patch(MODULE_PATH + 'get_device_ids', 1162 return_value=([Constants.device_id2, Constants.device_id1], capability_map)) 1163 ome_connection_mock_for_compliance.get_all_items_with_pagination.return_value = { 1164 "total_count": 1, "value": compliance_status} 1165 with pytest.raises(Exception) as err: 1166 self.module.validate_remediate_idempotency(f_module, ome_connection_mock_for_compliance) 1167 assert err.value.args[0] == CHECK_MODE_CHANGES_MSG 1168 1169 def test_validate_remediate_idempotency_case05(self, mocker, ome_connection_mock_for_compliance): 1170 mocker.patch(MODULE_PATH + 'get_baseline_compliance_info', 1171 return_value=baseline_output) 1172 compliance_status = [ 1173 { 1174 "Id": Constants.device_id1, 1175 "DeviceName": "XX.XXX.X.XXX", 1176 "IpAddresses": [ 1177 "XX.XXX.X.XXX" 1178 ], 1179 "Model": "PowerEdge MX840c", 1180 "ServiceTag": Constants.service_tag1, 1181 "ComplianceStatus": 2, 1182 "DeviceType": 1000, 1183 "InventoryTime": "2020-10-05 18:28:09.842072" 1184 } 1185 ] 1186 f_module = self.get_module_mock(params={"names": ["name1"]}, 1187 check_mode=True) 1188 capability_map = {"capable": [Constants.service_tag1], "non_capable": [Constants.service_tag2]} 1189 mocker.patch(MODULE_PATH + 'get_device_ids', 1190 return_value=([Constants.device_id2, Constants.device_id1], capability_map)) 1191 ome_connection_mock_for_compliance.get_all_items_with_pagination.return_value = { 1192 "total_count": 1, "value": compliance_status} 1193 with pytest.raises(Exception) as err: 1194 self.module.validate_remediate_idempotency(f_module, ome_connection_mock_for_compliance) 1195 assert err.value.args[0] == CHECK_MODE_CHANGES_MSG 1196