1# -*- coding: utf-8 -*- 2 3# 4# Dell EMC OpenManage Ansible Modules 5# Version 3.1.0 6# Copyright (C) 2019-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 json 16 17import pytest 18from ansible.module_utils.six.moves.urllib.error import HTTPError, URLError 19from ansible.module_utils.urls import ConnectionError, SSLValidationError 20from io import StringIO 21from ansible.module_utils._text import to_text 22from ssl import SSLError 23from ansible_collections.dellemc.openmanage.plugins.modules import ome_application_network_proxy 24from ansible_collections.dellemc.openmanage.tests.unit.plugins.modules.common import FakeAnsibleModule, Constants 25 26MODULE_PATH = 'ansible_collections.dellemc.openmanage.plugins.modules.' 27CHECK_MODE_CHANGE_FOUND_MSG = "Changes found to be applied." 28CHECK_MODE_CHANGE_NOT_FOUND_MSG = "No Changes found to be applied." 29 30 31@pytest.fixture 32def ome_connection_mock_for_application_network_proxy(mocker, ome_response_mock): 33 connection_class_mock = mocker.patch(MODULE_PATH + 'ome_application_network_proxy.RestOME') 34 ome_connection_mock_obj = connection_class_mock.return_value.__enter__.return_value 35 ome_connection_mock_obj.invoke_request.return_value = ome_response_mock 36 ome_connection_mock_obj.get_all_report_details.return_value = {"report_list": []} 37 return ome_connection_mock_obj 38 39 40class TestOmeTemplate(FakeAnsibleModule): 41 module = ome_application_network_proxy 42 43 sub_param1 = {"enable_proxy": True, "ip_address": "255.0.0.0", "proxy_port": 443, "proxy_username": "username", 44 "proxy_password": "password", 45 "enable_authentication": True} 46 sub_param2 = {"enable_proxy": False} 47 48 @pytest.mark.parametrize("sub_param", [sub_param1, sub_param2]) 49 def test_ome_application_network_proxy_main_success_case_01(self, mocker, ome_default_args, sub_param, 50 ome_connection_mock_for_application_network_proxy, 51 ome_response_mock): 52 ome_default_args.update(sub_param) 53 mocker.patch(MODULE_PATH + "ome_application_network_proxy.get_payload", return_value={"key": "val"}) 54 mocker.patch(MODULE_PATH + "ome_application_network_proxy.get_updated_payload", return_value={"key": "val"}) 55 ome_response_mock.json_data = {"EnableProxy": True, "IpAddress": "255.0.0.0", "PortNumber": 443, 56 "Username": "username", "Password": "password", "EnableAuthentication": True} 57 result = self.execute_module(ome_default_args) 58 assert result['changed'] is True 59 assert "msg" in result 60 assert "proxy_configuration" in result and result["proxy_configuration"] == {"EnableProxy": True, 61 "IpAddress": "255.0.0.0", 62 "PortNumber": 443, 63 "Username": "username", 64 "Password": "password", 65 "EnableAuthentication": True} 66 assert result["msg"] == "Successfully updated network proxy configuration." 67 68 sub_param1 = {"param": {"enable_proxy": True, "ip_address": "255.0.0.0"}, 69 "msg": 'enable_proxy is True but all of the following are missing: proxy_port'} 70 sub_param2 = {"param": {"enable_proxy": True, "proxy_port": 443}, 71 "msg": 'enable_proxy is True but all of the following are missing: ip_address'} 72 sub_param3 = {"param": {"enable_proxy": True}, 73 "msg": 'enable_proxy is True but all of the following are missing: ip_address, proxy_port'} 74 sub_param4 = {"param": {}, "msg": 'missing required arguments: enable_proxy'} 75 76 @pytest.mark.parametrize("param", [sub_param1, sub_param2, sub_param3, sub_param4]) 77 def test_ome_application_network_proxy_main_failure_case_01(self, mocker, ome_default_args, param, 78 ome_connection_mock_for_application_network_proxy, 79 ome_response_mock): 80 sub_param = param["param"] 81 msg = param["msg"] 82 ome_default_args.update(sub_param) 83 result = self._run_module_with_fail_json(ome_default_args) 84 assert result["msg"] == msg 85 assert "proxy_configuration" not in result 86 assert result["failed"] is True 87 88 sub_param1 = { 89 "param": {"enable_proxy": True, "proxy_port": 443, "ip_address": "255.0.0.0", "enable_authentication": True, 90 "proxy_username": "255.0.0.0"}, 91 "msg": 'enable_authentication is True but all of the following are missing: proxy_password'} 92 sub_param2 = { 93 "param": {"enable_proxy": True, "proxy_port": 443, "ip_address": "255.0.0.0", "enable_authentication": True, 94 "proxy_password": 443}, 95 "msg": 'enable_authentication is True but all of the following are missing: proxy_username'} 96 sub_param3 = { 97 "param": {"enable_proxy": True, "proxy_port": 443, "ip_address": "255.0.0.0", "enable_authentication": True}, 98 "msg": 'enable_authentication is True but all of the following are missing: proxy_username, proxy_password'} 99 100 @pytest.mark.parametrize("param", [sub_param1, sub_param2, sub_param3]) 101 def test_ome_application_network_proxy_main_failure_case_02(self, mocker, ome_default_args, param, 102 ome_connection_mock_for_application_network_proxy, 103 ome_response_mock): 104 sub_param = param["param"] 105 msg = param["msg"] 106 ome_default_args.update(sub_param) 107 result = self._run_module_with_fail_json(ome_default_args) 108 assert result["msg"] == msg 109 assert "proxy_configuration" not in result 110 assert result["failed"] is True 111 112 @pytest.mark.parametrize("exc_type", 113 [IOError, ValueError, SSLError, TypeError, ConnectionError, HTTPError, URLError]) 114 def test_ome_application_network_proxy_main_success_failure_case3(self, exc_type, mocker, ome_default_args, 115 ome_connection_mock_for_application_network_proxy, 116 ome_response_mock): 117 ome_default_args.update({"enable_proxy": False}) 118 json_str = to_text(json.dumps({"info": "error_details"})) 119 if exc_type == URLError: 120 mocker.patch(MODULE_PATH + 'ome_application_network_proxy.get_payload', 121 side_effect=exc_type("TEST")) 122 result = self._run_module(ome_default_args) 123 assert result["unreachable"] is True 124 elif exc_type not in [HTTPError, SSLValidationError]: 125 mocker.patch(MODULE_PATH + 'ome_application_network_proxy.get_payload', 126 side_effect=exc_type("exception message")) 127 result = self._run_module_with_fail_json(ome_default_args) 128 assert result['failed'] is True 129 else: 130 mocker.patch(MODULE_PATH + 'ome_application_network_proxy.get_payload', 131 side_effect=exc_type('http://testhost.com', 400, 132 'http error message', 133 {"accept-type": "application/json"}, 134 StringIO(json_str))) 135 result = self._run_module_with_fail_json(ome_default_args) 136 assert result['failed'] is True 137 assert 'proxy_configuration' not in result 138 assert 'msg' in result 139 140 def test_remove_unwanted_keys(self, ome_default_args): 141 removable_keys = list(ome_default_args.keys()) 142 new_param = { 143 "ip_address": "IpAddress", 144 "proxy_port": "PortNumber", 145 "enable_proxy": "EnableProxy", 146 "proxy_username": "Username", 147 "proxy_password": "Password", 148 "enable_authentication": "EnableAuthentication" 149 } 150 ome_default_args.update(new_param) 151 self.module.remove_unwanted_keys(removable_keys, ome_default_args) 152 assert len(set(new_param.keys()) - set(ome_default_args.keys())) == 0 153 154 def test_remove_unwanted_keys_case2(self): 155 """when key not exists should not throw error""" 156 current_setting = {"@odata.context": "context", "@odata.type": "data_type", "@odata.id": "@odata.id"} 157 removable_keys = ["@odata.context", "@odata.type", "@odata.id", "Password"] 158 self.module.remove_unwanted_keys(removable_keys, current_setting) 159 assert len(current_setting) == 0 160 161 def test_get_payload(self, ome_default_args): 162 new_param = { 163 "ip_address": "192.168.0.2", 164 "proxy_port": 443, 165 "enable_proxy": True, 166 "proxy_username": "username", 167 "proxy_password": "password", 168 "enable_authentication": False, 169 "port": 443 170 } 171 ome_default_args.update(new_param) 172 f_module = self.get_module_mock(params=ome_default_args) 173 payload = self.module.get_payload(f_module) 174 assert ome_default_args == {"ip_address": "192.168.0.2", 175 "proxy_port": 443, 176 "enable_proxy": True, 177 "proxy_username": "username", 178 "proxy_password": "password", 179 "enable_authentication": False, 180 "hostname": "192.168.0.1", 181 "username": "username", 182 "password": "password", 183 "port": 443} 184 assert payload == {"EnableProxy": True, "IpAddress": "192.168.0.2", "PortNumber": 443, "Username": "username", 185 "Password": "password", "EnableAuthentication": False} 186 187 def test_get_updated_payload_success_case(self, mocker, ome_default_args, ome_connection_mock_for_application_network_proxy, 188 ome_response_mock): 189 current_setting = {"@odata.context": "/api/$metadata#Network.ProxyConfiguration", 190 "@odata.type": "#Network.ProxyConfiguration", 191 "@odata.id": "/api/ApplicationService/Network/ProxyConfiguration", "IpAddress": "255.0.0.0", 192 "PortNumber": 443, "EnableAuthentication": False, "EnableProxy": True, 193 "Username": "username1", "Password": "password1"} 194 payload = {"EnableAuthentication": True, "IpAddress": "192.168.0.1", "PortNumber": 443, 'EnableProxy': True, 195 'Username': 'username2', "Password": "password2"} 196 f_module = self.get_module_mock(params=ome_default_args) 197 ome_response_mock.json_data = current_setting 198 mocker.patch(MODULE_PATH + "ome_application_network_proxy.validate_check_mode_for_network_proxy", 199 return_value=None) 200 setting = self.module.get_updated_payload(ome_connection_mock_for_application_network_proxy, f_module, payload) 201 assert setting == payload 202 203 def test_get_updated_payload_enable_auth_disable_success_case(self, mocker, ome_default_args, 204 ome_connection_mock_for_application_network_proxy, 205 ome_response_mock): 206 """when EnableAuthentication is False setting will not have Password and UserName even if its passed""" 207 ome_default_args.update( 208 {"enable_authentication": False, "proxy_username": 'username2', "proxy_password": "password2"}) 209 current_setting = {"@odata.context": "/api/$metadata#Network.ProxyConfiguration", 210 "@odata.type": "#Network.ProxyConfiguration", 211 "@odata.id": "/api/ApplicationService/Network/ProxyConfiguration", "IpAddress": "255.0.0.0", 212 "PortNumber": 443, "EnableAuthentication": True, "EnableProxy": True, 213 "Username": "username1", "Password": "password1"} 214 payload = {"EnableAuthentication": False, "IpAddress": "192.168.0.1", "PortNumber": 443, 'EnableProxy': True, 215 'Username': 'username2', "Password": "password2"} 216 f_module = self.get_module_mock(params=ome_default_args) 217 ome_response_mock.json_data = current_setting 218 mocker.patch(MODULE_PATH + "ome_application_network_proxy.validate_check_mode_for_network_proxy", 219 return_value=None) 220 setting = self.module.get_updated_payload(ome_connection_mock_for_application_network_proxy, f_module, payload) 221 assert setting == {"EnableAuthentication": False, "IpAddress": "192.168.0.1", "PortNumber": 443, 222 'EnableProxy': True} 223 224 def test_get_updated_payload_when_same_setting_failure_case1(self, mocker, ome_default_args, 225 ome_connection_mock_for_application_network_proxy, 226 ome_response_mock): 227 current_setting = {"@odata.context": "/api/$metadata#Network.ProxyConfiguration", 228 "@odata.type": "#Network.ProxyConfiguration", 229 "@odata.id": "/api/ApplicationService/Network/ProxyConfiguration", "IpAddress": "255.0.0.0", 230 "PortNumber": 443, "EnableAuthentication": False, "EnableProxy": True, 231 "Username": "username", "Password": "password"} 232 payload = {"IpAddress": "255.0.0.0", "PortNumber": 443, "EnableAuthentication": False, "EnableProxy": True, 233 "Username": "username", "Password": "password"} 234 f_module = self.get_module_mock(params=ome_default_args) 235 ome_response_mock.json_data = current_setting 236 error_message = "No changes made to proxy configuration as entered values are the same as current " \ 237 "configuration values." 238 mocker.patch(MODULE_PATH + "ome_application_network_proxy.validate_check_mode_for_network_proxy", 239 return_value=None) 240 with pytest.raises(Exception, match=error_message) as err: 241 self.module.get_updated_payload(ome_connection_mock_for_application_network_proxy, f_module, payload) 242 243 def test_get_updated_payload_when_same_setting_failure_case2(self, mocker, ome_default_args, 244 ome_connection_mock_for_application_network_proxy, 245 ome_response_mock): 246 """Password are ignored for difference check in payload""" 247 current_setting = {"@odata.context": "/api/$metadata#Network.ProxyConfiguration", 248 "@odata.type": "#Network.ProxyConfiguration", 249 "@odata.id": "/api/ApplicationService/Network/ProxyConfiguration", "IpAddress": "255.0.0.0", 250 "PortNumber": 443, "EnableAuthentication": False, "EnableProxy": True, 251 "Username": "username", "Password": "password1"} 252 payload = {"IpAddress": "255.0.0.0", "PortNumber": 443, "EnableAuthentication": False, "EnableProxy": True, 253 "Username": "username", "Password": "password2"} 254 f_module = self.get_module_mock(params=ome_default_args) 255 ome_response_mock.json_data = current_setting 256 error_message = "No changes made to proxy configuration as entered values are the same as current " \ 257 "configuration values." 258 mocker.patch(MODULE_PATH + "ome_application_network_proxy.validate_check_mode_for_network_proxy", 259 return_value=None) 260 with pytest.raises(Exception, match=error_message) as err: 261 self.module.get_updated_payload(ome_connection_mock_for_application_network_proxy, f_module, payload) 262 263 def test_get_updated_payload_when_no_diff_failure_case(self, mocker, ome_default_args, 264 ome_connection_mock_for_application_network_proxy, 265 ome_response_mock): 266 current_setting = {"@odata.context": "/api/$metadata#Network.ProxyConfiguration", 267 "@odata.type": "#Network.ProxyConfiguration", 268 "@odata.id": "/api/ApplicationService/Network/ProxyConfiguration", "IpAddress": "255.0.0.0", 269 "PortNumber": 443, "EnableAuthentication": False, "EnableProxy": True, 270 "Username": "username", "Password": "password"} 271 payload = {} 272 f_module = self.get_module_mock(params=ome_default_args) 273 ome_response_mock.json_data = current_setting 274 error_message = "Unable to configure the proxy because proxy configuration settings are not provided." 275 mocker.patch(MODULE_PATH + "ome_application_network_proxy.validate_check_mode_for_network_proxy", 276 return_value=None) 277 with pytest.raises(Exception, match=error_message) as err: 278 self.module.get_updated_payload(ome_connection_mock_for_application_network_proxy, f_module, payload) 279 280 def test_validate_check_mode_for_network_proxy_case01(self, ome_default_args): 281 f_module = self.get_module_mock(params={}, check_mode=True) 282 with pytest.raises(Exception, match=CHECK_MODE_CHANGE_FOUND_MSG): 283 self.module.validate_check_mode_for_network_proxy(True, f_module) 284 285 def test_validate_check_mode_for_network_proxy_case02(self, ome_default_args): 286 f_module = self.get_module_mock(params={}, check_mode=True) 287 with pytest.raises(Exception, match=CHECK_MODE_CHANGE_NOT_FOUND_MSG): 288 self.module.validate_check_mode_for_network_proxy(False, f_module) 289 290 def test_validate_check_mode_for_network_proxy_case03(self, ome_default_args): 291 f_module = self.get_module_mock(params={}, check_mode=False) 292 self.module.validate_check_mode_for_network_proxy(True, f_module) 293 294 def test_validate_check_mode_for_network_proxy_case04(self, ome_default_args): 295 f_module = self.get_module_mock(params={}, check_mode=False) 296 self.module.validate_check_mode_for_network_proxy(False, f_module) 297