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