diff --git a/docs/airlock_gateway_rest_api_lib/airlock_gateway_rest_api_lib.html b/docs/airlock_gateway_rest_api_lib/airlock_gateway_rest_api_lib.html index 9335c01..98c43c0 100644 --- a/docs/airlock_gateway_rest_api_lib/airlock_gateway_rest_api_lib.html +++ b/docs/airlock_gateway_rest_api_lib/airlock_gateway_rest_api_lib.html @@ -318,1101 +318,1106 @@

21multiple Errors will be raised by the underlying library. 22""" 23 - 24import xml.etree.ElementTree as ET - 25from io import BytesIO - 26from typing import Tuple, Union - 27from zipfile import ZipFile - 28import logging - 29import re - 30import zipfile - 31import json - 32import requests - 33import urllib3 - 34from requests import Session, Response - 35 - 36urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) - 37LIBRARY_COMPATIBILITY_VERSION = '8.0' - 38 - 39 - 40class AirlockGatewayRestError(Exception): - 41 ''' - 42 Custom Exception to inform Library users that an unexpected status - 43 has been returbned by the performed REST call. - 44 ''' - 45 def __init__(self, status_code, message): - 46 self.status_code = status_code - 47 self.message = "Status code " + str(status_code) + ": " + message - 48 super().__init__(self.message) - 49 - 50 - 51class GatewaySession: - 52 '''Wrapper class for a REST Session with Airlock Gateway. + 24 + 25import xml.etree.ElementTree as ET + 26from io import BytesIO + 27from typing import Tuple, Union + 28from zipfile import ZipFile + 29import logging + 30import re + 31import zipfile + 32import json + 33import requests + 34import urllib3 + 35from requests import Session, Response + 36 + 37 + 38urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) + 39LIBRARY_COMPATIBILITY_VERSION = '8.0' + 40 + 41 + 42class AirlockGatewayRestError(Exception): + 43 ''' + 44 Custom Exception to inform Library users that an unexpected status + 45 has been returbned by the performed REST call. + 46 ''' + 47 + 48 def __init__(self, status_code, message): + 49 self.status_code = status_code + 50 self.message = "Status code " + str(status_code) + ": " + message + 51 super().__init__(self.message) + 52 53 - 54 Uses the `requests` Python library to perform HTTP. - 55 ''' - 56 def __init__(self, host_name: str, ses: Session, port: int = None): - 57 self.port = port if port else 443 - 58 self.host = f"{host_name}:{port}" if port != 443 else host_name - 59 self.host_name = host_name - 60 self.ses = ses - 61 host = None - 62 host_name = None - 63 port = 443 - 64 ses = None - 65 - 66 def add_headers(self, headers: dict): - 67 ''' - 68 Adds the given `headers` to the REST Session.\n - 69 If one of the given `headers` was already set, it will be - 70 overwritten. - 71 ''' - 72 self.ses.headers.update(headers) - 73 - 74 def get_session(self) -> Session: - 75 ''' - 76 Returns the internal Session object of this object. - 77 ''' - 78 return self.ses - 79 - 80 - 81def get_version(gw_session: GatewaySession) -> Union[str, None]: - 82 ''' - 83 Returns the major and minor realease number (for example 8.0) of the - 84 Airlock Host, or None if the version could not be retrieved.\n - 85 ''' - 86 res = get(gw_session, "/system/status/node", exp_code=200) - 87 return res.json()["data"]["attributes"].get("version") - 88 - 89def _res_expect_handle(res: Response, exp_code: Union[list, int]) -> None: - 90 ''' - 91 Raises a custom exception if the responses' status code - 92 is not in the list of expected status code. - 93 ''' - 94 if exp_code: - 95 if not isinstance(exp_code, list): - 96 exp_code = [exp_code] - 97 if res.status_code not in exp_code: - 98 msg = f"Unexpected status code {res.status_code} was returned" - 99 logging.error(msg) - 100 raise AirlockGatewayRestError(res.status_code, res.text) - 101 - 102 - 103# pylint: disable = R0913 - 104def req_raw(gw_session: GatewaySession, method: str, path: str, - 105 ctype: str = None, data=None, - 106 exp_code: Union[list, int] = None) -> Response: - 107 ''' - 108 Performs a request to the Airlock Host at the specified path - 109 with the given method. Optionally, the Content Type, payload and - 110 expected response status codes can be specified.\n - 111 Returns the response object to the performed request. - 112 ''' - 113 uri = f'https://{gw_session.host}/airlock/rest{path}' - 114 logging.info("Performing a %s request at URI: %s", method, uri) - 115 headers = None - 116 if ctype: - 117 headers = {'Content-Type': ctype} - 118 res = gw_session.ses.request(method, uri, data=data, headers=headers, - 119 verify=False) - 120 _res_expect_handle(res, exp_code) - 121 return res - 122 - 123 - 124def req(gw_session: GatewaySession, method: str, - 125 path: str, body_dict: dict = None, - 126 exp_code: Union[list, int] = None) -> Response: - 127 ''' - 128 Performs a request to the Airlock Host at the specified path - 129 with the given method. Optionally, the JSON payload and - 130 expected response status codes can be specified.\n - 131 Returns the response object to the performed request. - 132 ''' - 133 uri = f'https://{gw_session.host}/airlock/rest{path}' - 134 logging.info("Performing a %s request at URI: %s ", method, uri) - 135 if isinstance(body_dict, dict): - 136 logging.debug("JSON payload of request:") - 137 logging.debug(json.dumps(body_dict, indent=4)) - 138 res = gw_session.ses.request(method, uri, json=body_dict) - 139 _res_expect_handle(res, exp_code) - 140 return res - 141 - 142 - 143def post(gw_session: GatewaySession, path: str, body_dict: dict = None, - 144 exp_code: Union[list, int] = None) -> Response: - 145 ''' - 146 Performs a POST request to the Airlock Host at the specified path. - 147 Optionally, the JSON payload and expected response status codes - 148 can be specified.\n - 149 Returns the Response object to the performed request. - 150 ''' - 151 return req(gw_session, 'POST', path, body_dict, exp_code) - 152 - 153 - 154def patch(gw_session: GatewaySession, path: str, body_dict: dict, - 155 exp_code: Union[list, int] = None) -> Response: - 156 ''' - 157 Performs a PATCH request to the Airlock Host at the specified path. - 158 Optionally, the JSON payload and expected response status codes - 159 can be specified.\n - 160 Returns the Response object to the performed request. - 161 ''' - 162 return req(gw_session, 'PATCH', path, body_dict, exp_code) - 163 - 164 - 165def put(gw_session: GatewaySession, path: str, body_dict: dict, - 166 exp_code: Union[list, int] = None) -> Response: - 167 ''' - 168 Performs a PUT request to the Airlock Host at the specified path. - 169 Optionally, the JSON payload and expected response status codes - 170 can be specified.\n - 171 Returns the Response object to the performed request. - 172 ''' - 173 return req(gw_session, 'PUT', path, body_dict, exp_code) - 174 - 175 - 176def delete(gw_session: GatewaySession, path: str, body_dict: dict = None, - 177 exp_code: Union[list, int] = None) -> Response: - 178 ''' - 179 Performs a DELETE request to the Airlock Host at the specified path. - 180 Optionally, the expected response status codes can be specified.\n - 181 Returns the Response object to the performed request. - 182 ''' - 183 return req(gw_session, 'DELETE', path, body_dict, exp_code) - 184 - 185 - 186def get(gw_session: GatewaySession, path: str, - 187 exp_code: Union[list, int] = None) -> Response: - 188 ''' - 189 Performs a GET request to the Airlock Host at the specified path. - 190 Optionally, the expected response status codes can be specified.\n - 191 Returns the Response object to the performed request. - 192 ''' - 193 return req(gw_session, 'GET', path, None, exp_code) - 194 - 195 - 196def create_session(host: str, api_key: str, port: int = 443) -> GatewaySession: - 197 ''' - 198 Creates a new session with the given host. + 54class GatewaySession: + 55 '''Wrapper class for a REST Session with Airlock Gateway. + 56 + 57 Uses the `requests` Python library to perform HTTP. + 58 ''' + 59 + 60 def __init__(self, host_name: str, ses: Session, port: int = None): + 61 self.port = port if port else 443 + 62 self.host = f"{host_name}:{port}" if port != 443 else host_name + 63 self.host_name = host_name + 64 self.ses = ses + 65 host = None + 66 host_name = None + 67 port = 443 + 68 ses = None + 69 + 70 def add_headers(self, headers: dict): + 71 ''' + 72 Adds the given `headers` to the REST Session.\n + 73 If one of the given `headers` was already set, it will be + 74 overwritten. + 75 ''' + 76 self.ses.headers.update(headers) + 77 + 78 def get_session(self) -> Session: + 79 ''' + 80 Returns the internal Session object of this object. + 81 ''' + 82 return self.ses + 83 + 84 + 85def get_version(gw_session: GatewaySession) -> Union[str, None]: + 86 ''' + 87 Returns the major and minor realease number (for example 8.0) of the + 88 Airlock Host, or None if the version could not be retrieved.\n + 89 ''' + 90 res = get(gw_session, "/system/status/node", exp_code=200) + 91 return res.json()["data"]["attributes"].get("version") + 92 + 93 + 94def _res_expect_handle(res: Response, exp_code: Union[list, int]) -> None: + 95 ''' + 96 Raises a custom exception if the responses' status code + 97 is not in the list of expected status code. + 98 ''' + 99 if exp_code: + 100 if not isinstance(exp_code, list): + 101 exp_code = [exp_code] + 102 if res.status_code not in exp_code: + 103 msg = f"Unexpected status code {res.status_code} was returned" + 104 logging.error(msg) + 105 raise AirlockGatewayRestError(res.status_code, res.text) + 106 + 107 + 108# pylint: disable = R0913 + 109def req_raw(gw_session: GatewaySession, method: str, path: str, + 110 ctype: str = None, data=None, + 111 exp_code: Union[list, int] = None) -> Response: + 112 ''' + 113 Performs a request to the Airlock Host at the specified path + 114 with the given method. Optionally, the Content Type, payload and + 115 expected response status codes can be specified.\n + 116 Returns the response object to the performed request. + 117 ''' + 118 uri = f'https://{gw_session.host}/airlock/rest{path}' + 119 logging.info("Performing a %s request at URI: %s", method, uri) + 120 headers = None + 121 if ctype: + 122 headers = {'Content-Type': ctype} + 123 res = gw_session.ses.request(method, uri, data=data, headers=headers, + 124 verify=False) + 125 _res_expect_handle(res, exp_code) + 126 return res + 127 + 128 + 129def req(gw_session: GatewaySession, method: str, + 130 path: str, body_dict: dict = None, + 131 exp_code: Union[list, int] = None) -> Response: + 132 ''' + 133 Performs a request to the Airlock Host at the specified path + 134 with the given method. Optionally, the JSON payload and + 135 expected response status codes can be specified.\n + 136 Returns the response object to the performed request. + 137 ''' + 138 uri = f'https://{gw_session.host}/airlock/rest{path}' + 139 logging.info("Performing a %s request at URI: %s ", method, uri) + 140 if isinstance(body_dict, dict): + 141 logging.debug("JSON payload of request:") + 142 logging.debug(json.dumps(body_dict, indent=4)) + 143 res = gw_session.ses.request(method, uri, json=body_dict) + 144 _res_expect_handle(res, exp_code) + 145 return res + 146 + 147 + 148def post(gw_session: GatewaySession, path: str, body_dict: dict = None, + 149 exp_code: Union[list, int] = None) -> Response: + 150 ''' + 151 Performs a POST request to the Airlock Host at the specified path. + 152 Optionally, the JSON payload and expected response status codes + 153 can be specified.\n + 154 Returns the Response object to the performed request. + 155 ''' + 156 return req(gw_session, 'POST', path, body_dict, exp_code) + 157 + 158 + 159def patch(gw_session: GatewaySession, path: str, body_dict: dict, + 160 exp_code: Union[list, int] = None) -> Response: + 161 ''' + 162 Performs a PATCH request to the Airlock Host at the specified path. + 163 Optionally, the JSON payload and expected response status codes + 164 can be specified.\n + 165 Returns the Response object to the performed request. + 166 ''' + 167 return req(gw_session, 'PATCH', path, body_dict, exp_code) + 168 + 169 + 170def put(gw_session: GatewaySession, path: str, body_dict: dict, + 171 exp_code: Union[list, int] = None) -> Response: + 172 ''' + 173 Performs a PUT request to the Airlock Host at the specified path. + 174 Optionally, the JSON payload and expected response status codes + 175 can be specified.\n + 176 Returns the Response object to the performed request. + 177 ''' + 178 return req(gw_session, 'PUT', path, body_dict, exp_code) + 179 + 180 + 181def delete(gw_session: GatewaySession, path: str, body_dict: dict = None, + 182 exp_code: Union[list, int] = None) -> Response: + 183 ''' + 184 Performs a DELETE request to the Airlock Host at the specified path. + 185 Optionally, the expected response status codes can be specified.\n + 186 Returns the Response object to the performed request. + 187 ''' + 188 return req(gw_session, 'DELETE', path, body_dict, exp_code) + 189 + 190 + 191def get(gw_session: GatewaySession, path: str, + 192 exp_code: Union[list, int] = None) -> Response: + 193 ''' + 194 Performs a GET request to the Airlock Host at the specified path. + 195 Optionally, the expected response status codes can be specified.\n + 196 Returns the Response object to the performed request. + 197 ''' + 198 return req(gw_session, 'GET', path, None, exp_code) 199 - 200 Returns the generated GatewaySession object, - 201 or None if the Session couldn't be started. - 202 ''' - 203 ses = requests.Session() - 204 ses.verify = False - 205 gw_session = GatewaySession(host, ses, port) - 206 gw_session.add_headers({"Authorization": f"Bearer {api_key}"}) - 207 logging.info("Starting the REST Session with Host %s", host) - 208 res = post(gw_session, "/session/create", exp_code=[200, 404]) - 209 if res.status_code == 200: - 210 version = get_version(gw_session) - 211 if version: - 212 if not version.startswith(LIBRARY_COMPATIBILITY_VERSION): - 213 logging.warning("You are using Airlock version %s while this \ - 214library version is developed for Airlock hosts running version %s. Some Rest \ - 215calls will not work on this Airlock version", version, - 216 LIBRARY_COMPATIBILITY_VERSION) - 217 else: - 218 logging.warning('The Airlock version could not be determined, \ - 219this library version might be incompatible with this Airlock Host') - 220 return gw_session - 221 return None - 222 - 223 - 224def create_session_from_cookie(host: str, jsessionid: str) -> GatewaySession: - 225 ''' - 226 Retrieves an existing Gateway Session from the JSESSIONID Cookie.\n - 227 Returns the generated GatewaySession object. - 228 ''' - 229 ses = requests.Session() - 230 ses.verify = False - 231 cookie = requests.cookies.create_cookie("JSESSIONID", jsessionid) - 232 ses.cookies.set_cookie(cookie) - 233 return GatewaySession(host, ses) - 234 - 235 - 236def _get_cookies(gw_session: GatewaySession) -> dict: - 237 ''' - 238 Returns a dictionary object mapping all Cookie names in a GatewaySession - 239 to their value. - 240 ''' - 241 return {x.name: x for x in gw_session.ses.cookies} - 242 - 243 - 244def get_jsession_id(gw_session: GatewaySession) -> str: - 245 ''' - 246 Returns the value of the JSESSIONID Cookie, - 247 or None if no such Cookie was found. - 248 ''' - 249 cookie = _get_cookies(gw_session).get('JSESSIONID') - 250 return cookie.value if cookie else None - 251 - 252 - 253def terminate_session(gw_session: GatewaySession) -> None: - 254 ''' - 255 Terminates the Gateway Session. - 256 ''' - 257 post(gw_session, "/session/terminate", exp_code=200) - 258 - 259 - 260def get_configs(gw_session: GatewaySession) -> list: - 261 ''' - 262 Returns a list containing all configurations on the - 263 Airlock Host as dictionary objects. - 264 ''' - 265 res = get(gw_session, "/configuration/configurations", exp_code=200) - 266 return res.json()["data"] - 267 - 268 - 269def validate(gw_session: GatewaySession) -> Tuple[bool, list]: - 270 ''' - 271 Returns True and an empty list if the configuration is valid, - 272 False and a list of error messages if it isn't. - 273 ''' - 274 path = "/configuration/validator-messages?filter=meta.severity==ERROR" - 275 res = get(gw_session, path, exp_code=200) - 276 rdata = res.json() - 277 if len(rdata["data"]) > 0: - 278 msgs = [e["attributes"]["detail"] for e in rdata["data"]] - 279 logging.info("Validation failed with the following error\ - 280 message(s):\n %s", str(msgs)) - 281 return False, msgs - 282 return True, [] - 283 - 284 - 285def activate(gw_session: GatewaySession, comment: str = None) -> bool: - 286 ''' - 287 Activates the currently loaded configuration on Airlock Host and - 288 optionally adds a comment to the activation.\n - 289 Returns True if the configuration was activated successfully and False - 290 otherwise - 291 ''' - 292 data = None - 293 if comment: - 294 options = {"ignoreOutdatedConfiguration": True, - 295 "failoverActivation": False} - 296 data = {"comment": comment, "options": options} - 297 if not validate(gw_session)[0]: - 298 logging.info("Configuration could not be activated as it isn't valid") - 299 return False - 300 path = "/configuration/configurations/activate" - 301 post(gw_session, path, data, 200) - 302 return True - 303 - 304 - 305def save_config(gw_session: GatewaySession, comment: str = None) -> str: - 306 ''' - 307 Saves the current configuration with an optional - 308 `comment` without activating it.\n - 309 Returns the ID of the newly saved configuration or None if - 310 the configuration could not be saved. - 311 ''' - 312 data = None - 313 if comment: - 314 data = {"comment": comment} - 315 path = "/configuration/configurations/save" - 316 res = post(gw_session, path, data, [200, 400]) - 317 if res.status_code == 400: - 318 logging.warning("Configuration could not be saved\ - 319 as no configuration was loaded!") - 320 return None - 321 return res.json()['data']['id'] - 322 - 323 - 324def update_license(gw_session: GatewaySession, lic_str: str) -> None: - 325 ''' - 326 Updates the license on the Airlock Host. - 327 ''' - 328 res = get(gw_session, '/configuration/license') - 329 logging.debug("Current license: \n %s", json.dumps(res.json(), indent=4)) - 330 - 331 lic_patch_data = { - 332 "data": { - 333 "type": "license", - 334 "attributes": { - 335 "license": lic_str - 336 } - 337 } - 338 } - 339 patch(gw_session, "/configuration/license", lic_patch_data, 200) - 340 - 341 - 342def get_virtualhosts(gw_session: GatewaySession) -> list: - 343 ''' - 344 Returns a list of dictionary objects describing all - 345 virtual hosts on the Airlock Host. - 346 ''' - 347 res = get(gw_session, '/configuration/virtual-hosts', exp_code=200) - 348 return res.json().get('data') - 349 - 350 - 351def gen_standard_virtual_host_data(vh_name: str, ipv4_addr: str, - 352 interface: str, - 353 certificate: dict) -> dict: - 354 ''' - 355 Generates and returns the data object necessary to upload a new virtual - 356 host to the Airlock Host. This object can then for example be passed - 357 to the `add_virtual_host()` function to add a new virtual host. \n - 358 The virtual host data will have standard values for every attribute that - 359 can not be given to this function as an argument. - 360 ''' - 361 host_data = { - 362 "data": { - 363 "type": "virtual-host", - 364 "attributes": { - 365 "name": vh_name, - 366 "hostName": vh_name, - 367 "serverAdmin": "admin@" + vh_name, - 368 "showMaintenancePage": False, - 369 "strictlyMatchFullyQualifiedDomainName": False, - 370 "keepAliveTimeout": 10, - 371 "networkInterface": { - 372 "externalLogicalInterfaceName": interface, - 373 "ipV4Address": ipv4_addr, - 374 "ipV6Address": "", - 375 "http": { - 376 "enabled": True, - 377 "port": 80, - 378 "httpsRedirectEnforced": True - 379 }, - 380 "https": { + 200 + 201def create_session(host: str, api_key: str, port: int = 443) -> GatewaySession: + 202 ''' + 203 Creates a new session with the given host. + 204 + 205 Returns the generated GatewaySession object, + 206 or None if the Session couldn't be started. + 207 ''' + 208 ses = requests.Session() + 209 ses.verify = False + 210 gw_session = GatewaySession(host, ses, port) + 211 gw_session.add_headers({"Authorization": f"Bearer {api_key}"}) + 212 logging.info("Starting the REST Session with Host %s", host) + 213 res = post(gw_session, "/session/create", exp_code=[200, 404]) + 214 if res.status_code == 200: + 215 version = get_version(gw_session) + 216 if version: + 217 if not version.startswith(LIBRARY_COMPATIBILITY_VERSION): + 218 logging.warning("You are using Airlock version %s while this \ + 219library version is developed for Airlock hosts running version %s. Some Rest \ + 220calls will not work on this Airlock version", version, + 221 LIBRARY_COMPATIBILITY_VERSION) + 222 else: + 223 logging.warning('The Airlock version could not be determined, \ + 224this library version might be incompatible with this Airlock Host') + 225 return gw_session + 226 return None + 227 + 228 + 229def create_session_from_cookie(host: str, jsessionid: str) -> GatewaySession: + 230 ''' + 231 Retrieves an existing Gateway Session from the JSESSIONID Cookie.\n + 232 Returns the generated GatewaySession object. + 233 ''' + 234 ses = requests.Session() + 235 ses.verify = False + 236 cookie = requests.cookies.create_cookie("JSESSIONID", jsessionid) + 237 ses.cookies.set_cookie(cookie) + 238 return GatewaySession(host, ses) + 239 + 240 + 241def _get_cookies(gw_session: GatewaySession) -> dict: + 242 ''' + 243 Returns a dictionary object mapping all Cookie names in a GatewaySession + 244 to their value. + 245 ''' + 246 return {x.name: x for x in gw_session.ses.cookies} + 247 + 248 + 249def get_jsession_id(gw_session: GatewaySession) -> str: + 250 ''' + 251 Returns the value of the JSESSIONID Cookie, + 252 or None if no such Cookie was found. + 253 ''' + 254 cookie = _get_cookies(gw_session).get('JSESSIONID') + 255 return cookie.value if cookie else None + 256 + 257 + 258def terminate_session(gw_session: GatewaySession) -> None: + 259 ''' + 260 Terminates the Gateway Session. + 261 ''' + 262 post(gw_session, "/session/terminate", exp_code=200) + 263 + 264 + 265def get_configs(gw_session: GatewaySession) -> list: + 266 ''' + 267 Returns a list containing all configurations on the + 268 Airlock Host as dictionary objects. + 269 ''' + 270 res = get(gw_session, "/configuration/configurations", exp_code=200) + 271 return res.json()["data"] + 272 + 273 + 274def validate(gw_session: GatewaySession) -> Tuple[bool, list]: + 275 ''' + 276 Returns True and an empty list if the configuration is valid, + 277 False and a list of error messages if it isn't. + 278 ''' + 279 path = "/configuration/validator-messages?filter=meta.severity==ERROR" + 280 res = get(gw_session, path, exp_code=200) + 281 rdata = res.json() + 282 if len(rdata["data"]) > 0: + 283 msgs = [e["attributes"]["detail"] for e in rdata["data"]] + 284 logging.info("Validation failed with the following error\ + 285 message(s):\n %s", str(msgs)) + 286 return False, msgs + 287 return True, [] + 288 + 289 + 290def activate(gw_session: GatewaySession, comment: str = None) -> bool: + 291 ''' + 292 Activates the currently loaded configuration on Airlock Host and + 293 optionally adds a comment to the activation.\n + 294 Returns True if the configuration was activated successfully and False + 295 otherwise + 296 ''' + 297 data = None + 298 if comment: + 299 options = {"ignoreOutdatedConfiguration": True, + 300 "failoverActivation": False} + 301 data = {"comment": comment, "options": options} + 302 if not validate(gw_session)[0]: + 303 logging.info("Configuration could not be activated as it isn't valid") + 304 return False + 305 path = "/configuration/configurations/activate" + 306 post(gw_session, path, data, 200) + 307 return True + 308 + 309 + 310def save_config(gw_session: GatewaySession, comment: str = None) -> str: + 311 ''' + 312 Saves the current configuration with an optional + 313 `comment` without activating it.\n + 314 Returns the ID of the newly saved configuration or None if + 315 the configuration could not be saved. + 316 ''' + 317 data = None + 318 if comment: + 319 data = {"comment": comment} + 320 path = "/configuration/configurations/save" + 321 res = post(gw_session, path, data, [200, 400]) + 322 if res.status_code == 400: + 323 logging.warning("Configuration could not be saved\ + 324 as no configuration was loaded!") + 325 return None + 326 return res.json()['data']['id'] + 327 + 328 + 329def update_license(gw_session: GatewaySession, lic_str: str) -> None: + 330 ''' + 331 Updates the license on the Airlock Host. + 332 ''' + 333 res = get(gw_session, '/configuration/license') + 334 logging.debug("Current license: \n %s", json.dumps(res.json(), indent=4)) + 335 + 336 lic_patch_data = { + 337 "data": { + 338 "type": "license", + 339 "attributes": { + 340 "license": lic_str + 341 } + 342 } + 343 } + 344 patch(gw_session, "/configuration/license", lic_patch_data, 200) + 345 + 346 + 347def get_virtualhosts(gw_session: GatewaySession) -> list: + 348 ''' + 349 Returns a list of dictionary objects describing all + 350 virtual hosts on the Airlock Host. + 351 ''' + 352 res = get(gw_session, '/configuration/virtual-hosts', exp_code=200) + 353 return res.json().get('data') + 354 + 355 + 356def gen_standard_virtual_host_data(vh_name: str, ipv4_addr: str, + 357 interface: str, + 358 certificate: dict) -> dict: + 359 ''' + 360 Generates and returns the data object necessary to upload a new virtual + 361 host to the Airlock Host. This object can then for example be passed + 362 to the `add_virtual_host()` function to add a new virtual host. \n + 363 The virtual host data will have standard values for every attribute that + 364 can not be given to this function as an argument. + 365 ''' + 366 host_data = { + 367 "data": { + 368 "type": "virtual-host", + 369 "attributes": { + 370 "name": vh_name, + 371 "hostName": vh_name, + 372 "serverAdmin": "admin@" + vh_name, + 373 "showMaintenancePage": False, + 374 "strictlyMatchFullyQualifiedDomainName": False, + 375 "keepAliveTimeout": 10, + 376 "networkInterface": { + 377 "externalLogicalInterfaceName": interface, + 378 "ipV4Address": ipv4_addr, + 379 "ipV6Address": "", + 380 "http": { 381 "enabled": True, - 382 "port": 443, - 383 "http2Allowed": True - 384 } - 385 }, - 386 "tls": certificate, - 387 } - 388 } - 389 } - 390 return host_data - 391 - 392 - 393def add_virtual_host(gw_session: GatewaySession, data: dict) -> str: - 394 ''' - 395 Adds a new virtual host to the Airlock Host. The `data` parameter - 396 has to fully specify a valid virtual host configuration.\n - 397 For standard virtual hosts configuration use - 398 `add_standard_virtual_host()` instead.\n - 399 Returns the ID of the added virtual host. - 400 ''' - 401 res = post(gw_session, "/configuration/virtual-hosts", data, 201) - 402 return res.json()['data']['id'] - 403 - 404 - 405def get_virtual_host_by_id(gw_session: GatewaySession, vh_id: str) -> dict: - 406 ''' - 407 Returns a dictionary object representing the virtual host with - 408 the given `vh_id` or None if no such virtual host was found - 409 ''' - 410 path = f'/configuration/virtual-hosts/{vh_id}' - 411 res = get(gw_session, path, exp_code=[200, 404]) - 412 - 413 if res.status_code == 404: - 414 return None - 415 return res.json().get('data') - 416 + 382 "port": 80, + 383 "httpsRedirectEnforced": True + 384 }, + 385 "https": { + 386 "enabled": True, + 387 "port": 443, + 388 "http2Allowed": True + 389 } + 390 }, + 391 "tls": certificate, + 392 } + 393 } + 394 } + 395 return host_data + 396 + 397 + 398def add_virtual_host(gw_session: GatewaySession, data: dict) -> str: + 399 ''' + 400 Adds a new virtual host to the Airlock Host. The `data` parameter + 401 has to fully specify a valid virtual host configuration.\n + 402 For standard virtual hosts configuration use + 403 `add_standard_virtual_host()` instead.\n + 404 Returns the ID of the added virtual host. + 405 ''' + 406 res = post(gw_session, "/configuration/virtual-hosts", data, 201) + 407 return res.json()['data']['id'] + 408 + 409 + 410def get_virtual_host_by_id(gw_session: GatewaySession, vh_id: str) -> dict: + 411 ''' + 412 Returns a dictionary object representing the virtual host with + 413 the given `vh_id` or None if no such virtual host was found + 414 ''' + 415 path = f'/configuration/virtual-hosts/{vh_id}' + 416 res = get(gw_session, path, exp_code=[200, 404]) 417 - 418def update_virtual_host_by_id(gw_session: GatewaySession, vh_id: str, - 419 attributes: dict) -> bool: - 420 ''' - 421 Updates the virtual host with ID `vh_id` with the given `attributes`, - 422 for example name, showMaintenancePage etc.\n - 423 Returns True if the update was successful and False if no virtual - 424 host with ID `vh_id` was found. - 425 ''' - 426 host_data = { - 427 "data": { - 428 "type": "virtual-host", - 429 "id": vh_id, - 430 "attributes": attributes - 431 } - 432 } - 433 path = f"/configuration/virtual-hosts/{vh_id}" - 434 res = patch(gw_session, path, host_data, [200, 404]) - 435 return res.status_code == 200 - 436 - 437 - 438def delete_virtual_host_by_id(gw_session: GatewaySession, vh_id: str) -> bool: - 439 ''' - 440 Deletes the Virtual Host with the selected ID.\n - 441 Returns True if deletion was successful and False otherwise. - 442 ''' - 443 path = f"/configuration/virtual-hosts/{vh_id}" - 444 res = delete(gw_session, path, exp_code=[204, 404]) - 445 return res.status_code == 204 - 446 - 447 - 448def get_all_mappings(gw_session: GatewaySession) -> list: - 449 ''' - 450 Returns a list of dictionary object describing - 451 all mappings on the Airlock Host. - 452 ''' - 453 res = get(gw_session, '/configuration/mappings', 200) - 454 return res.json().get('data') - 455 - 456 - 457def select_mappings(gw_session: GatewaySession, pattern: str = None, - 458 label: str = None) -> list: - 459 ''' - 460 Returns a list of dictionary object describing all mappings - 461 whose name is matched by the `pattern` regular expression - 462 or who are labeled with `label`.\n - 463 If no parameter is given, all mappings are returned. - 464 ''' - 465 if (not pattern and not label): - 466 return get_all_mappings(gw_session) - 467 if (pattern and label): - 468 return list(set(select_mappings(gw_session, pattern=pattern)) - 469 + set(select_mappings(gw_session, label=label)) - 470 ) - 471 if label: - 472 path = f'/configuration/mappings?filter=label=={label}' - 473 res = get(gw_session, path, exp_code=200) - 474 return res.json().get('data') - 475 mappings = [] - 476 for mapping in get_all_mappings(gw_session): - 477 if re.search(pattern, mapping['attributes']['name']): - 478 mappings.append(mapping) - 479 return mappings - 480 - 481 - 482def get_mapping_id(gw_session: GatewaySession, name: str) -> str: - 483 ''' - 484 Returns the ID of the mapping with the given `name` - 485 or None if no such mapping was found. - 486 ''' - 487 mapping = get_mapping_by_name(gw_session, name) - 488 if mapping: - 489 return mapping['id'] - 490 return None - 491 - 492 - 493def get_mapping_by_id(gw_session: GatewaySession, mapping_id: str) -> dict: - 494 ''' - 495 Returns a dictionary object representing the mapping - 496 with the given `mapping_id` or None if no such mapping - 497 was found. - 498 ''' - 499 path = f'/configuration/mappings/{mapping_id}' - 500 res = get(gw_session, path, exp_code=[200, 404]) - 501 if res.status_code == 200: - 502 return res.json().get('data') - 503 return None - 504 - 505 - 506def get_mapping_by_name(gw_session: GatewaySession, name: str) -> dict: - 507 ''' - 508 Returns a dictionary object representing the mapping - 509 with the given `name` or an empty dictionary if no - 510 such mapping was found. - 511 ''' - 512 path = f'/configuration/mappings?filter=name=={name}' - 513 res = get(gw_session, path, exp_code=200) - 514 return res.json().get('data') - 515 - 516 - 517def get_all_mapping_names(gw_session: GatewaySession) -> list: - 518 ''' - 519 Returns a sorted list of all mapping names on the Airlock Host. - 520 ''' - 521 mappings = get_all_mappings(gw_session) - 522 mapping_names = [] - 523 for mapping in mappings: - 524 mapping_name = mapping["attributes"]["name"] - 525 mapping_names.append(mapping_name) - 526 return sorted(mapping_names) - 527 - 528 - 529def import_mappings_from_xml(gw_session, mappings_xmls: list): - 530 ''' - 531 Adds all mappings specified in the list of dictionary objects - 532 representing XML files stored in `mappings_xmls` on the - 533 Airlock Host. If a mapping with the same name already exists, - 534 it will be overwritten. - 535 ''' - 536 for mapping_xml in mappings_xmls: - 537 mapping_zip = BytesIO() - 538 with ZipFile(mapping_zip, mode="w") as zip_file: - 539 zip_file.writestr("alec_table.xml", mapping_xml) - 540 - 541 mapping_zip.seek(0) - 542 - 543 req_raw(gw_session, "put", "/configuration/mappings/import", - 544 "application/zip", mapping_zip.read(), 200) + 418 if res.status_code == 404: + 419 return None + 420 return res.json().get('data') + 421 + 422 + 423def update_virtual_host_by_id(gw_session: GatewaySession, vh_id: str, + 424 attributes: dict) -> bool: + 425 ''' + 426 Updates the virtual host with ID `vh_id` with the given `attributes`, + 427 for example name, showMaintenancePage etc.\n + 428 Returns True if the update was successful and False if no virtual + 429 host with ID `vh_id` was found. + 430 ''' + 431 host_data = { + 432 "data": { + 433 "type": "virtual-host", + 434 "id": vh_id, + 435 "attributes": attributes + 436 } + 437 } + 438 path = f"/configuration/virtual-hosts/{vh_id}" + 439 res = patch(gw_session, path, host_data, [200, 404]) + 440 return res.status_code == 200 + 441 + 442 + 443def delete_virtual_host_by_id(gw_session: GatewaySession, vh_id: str) -> bool: + 444 ''' + 445 Deletes the Virtual Host with the selected ID.\n + 446 Returns True if deletion was successful and False otherwise. + 447 ''' + 448 path = f"/configuration/virtual-hosts/{vh_id}" + 449 res = delete(gw_session, path, exp_code=[204, 404]) + 450 return res.status_code == 204 + 451 + 452 + 453def get_all_mappings(gw_session: GatewaySession) -> list: + 454 ''' + 455 Returns a list of dictionary object describing + 456 all mappings on the Airlock Host. + 457 ''' + 458 res = get(gw_session, '/configuration/mappings', 200) + 459 return res.json().get('data') + 460 + 461 + 462def select_mappings(gw_session: GatewaySession, pattern: str = None, + 463 label: str = None) -> list: + 464 ''' + 465 Returns a list of dictionary object describing all mappings + 466 whose name is matched by the `pattern` regular expression + 467 or who are labeled with `label`.\n + 468 If no parameter is given, all mappings are returned. + 469 ''' + 470 if (not pattern and not label): + 471 return get_all_mappings(gw_session) + 472 if (pattern and label): + 473 return list(set(select_mappings(gw_session, pattern=pattern)) + 474 + set(select_mappings(gw_session, label=label)) + 475 ) + 476 if label: + 477 path = f'/configuration/mappings?filter=label=={label}' + 478 res = get(gw_session, path, exp_code=200) + 479 return res.json().get('data') + 480 mappings = [] + 481 for mapping in get_all_mappings(gw_session): + 482 if re.search(pattern, mapping['attributes']['name']): + 483 mappings.append(mapping) + 484 return mappings + 485 + 486 + 487def get_mapping_id(gw_session: GatewaySession, name: str) -> str: + 488 ''' + 489 Returns the ID of the mapping with the given `name` + 490 or None if no such mapping was found. + 491 ''' + 492 mapping = get_mapping_by_name(gw_session, name) + 493 if mapping: + 494 return mapping['id'] + 495 return None + 496 + 497 + 498def get_mapping_by_id(gw_session: GatewaySession, mapping_id: str) -> dict: + 499 ''' + 500 Returns a dictionary object representing the mapping + 501 with the given `mapping_id` or None if no such mapping + 502 was found. + 503 ''' + 504 path = f'/configuration/mappings/{mapping_id}' + 505 res = get(gw_session, path, exp_code=[200, 404]) + 506 if res.status_code == 200: + 507 return res.json().get('data') + 508 return None + 509 + 510 + 511def get_mapping_by_name(gw_session: GatewaySession, name: str) -> dict: + 512 ''' + 513 Returns a dictionary object representing the mapping + 514 with the given `name` or an empty dictionary if no + 515 such mapping was found. + 516 ''' + 517 path = f'/configuration/mappings?filter=name=={name}' + 518 res = get(gw_session, path, exp_code=200) + 519 return res.json().get('data') + 520 + 521 + 522def get_all_mapping_names(gw_session: GatewaySession) -> list: + 523 ''' + 524 Returns a sorted list of all mapping names on the Airlock Host. + 525 ''' + 526 mappings = get_all_mappings(gw_session) + 527 mapping_names = [] + 528 for mapping in mappings: + 529 mapping_name = mapping["attributes"]["name"] + 530 mapping_names.append(mapping_name) + 531 return sorted(mapping_names) + 532 + 533 + 534def import_mappings_from_xml(gw_session, mappings_xmls: list): + 535 ''' + 536 Adds all mappings specified in the list of dictionary objects + 537 representing XML files stored in `mappings_xmls` on the + 538 Airlock Host. If a mapping with the same name already exists, + 539 it will be overwritten. + 540 ''' + 541 for mapping_xml in mappings_xmls: + 542 mapping_zip = BytesIO() + 543 with ZipFile(mapping_zip, mode="w") as zip_file: + 544 zip_file.writestr("alec_table.xml", mapping_xml) 545 - 546 - 547def export_mappings(gw_session: GatewaySession, - 548 mapping_ids: list = None) -> list: - 549 ''' - 550 Returns a list of the XML files describing the mappings with IDs - 551 contained in the `mapping_ids` list.\n - 552 `mapping_ids` must be a list of strings. If it is omitted, all mappings - 553 are returned. \n - 554 If one or more of the mappings IDs is not found, it is ignored. - 555 ''' - 556 if mapping_ids is None: - 557 mapping_ids = [data["id"] for data in get_all_mappings(gw_session)] - 558 - 559 mapping_xmls = [] - 560 for mapping_id in mapping_ids: - 561 gw_session.add_headers({"Accept": "application/zip"}) - 562 path = f'/configuration/mappings/{mapping_id}/export' - 563 res = get(gw_session, path, exp_code=[200, 404]) - 564 if res.status_code == 200: - 565 with ZipFile(BytesIO(res.content)) as zip_file: - 566 with zip_file.open("alec_table.xml", "r") as mapping_xml: - 567 mapping_xmls.append(mapping_xml) - 568 else: - 569 logging.info("Mapping with ID %s was not found on Airlock Host", - 570 mapping_id) - 571 - 572 gw_session.add_headers({"Accept": "application/json"}) - 573 return mapping_xmls - 574 - 575 - 576def delete_mapping_by_id(gw_session: GatewaySession, mapping_id: str) -> bool: - 577 ''' - 578 Deletes the Mapping with the selected ID.\n - 579 Returns True if deletion was successful and False if no mapping with ID - 580 `mapping_id` was found.. - 581 ''' - 582 path = f"/configuration/mappings/{mapping_id}" - 583 res = delete(gw_session, path, exp_code=[204, 404]) - 584 return res.status_code == 204 - 585 - 586 - 587def get_templates(gw_session: GatewaySession) -> dict: - 588 ''' - 589 Returns a dictionary object mapping every mapping template name to its ID. - 590 ''' - 591 res = get(gw_session, '/configuration/templates/mappings', 200) - 592 data = res.json()['data'] - 593 return {x['attributes']['name']: x['id'] for x in data} - 594 - 595 - 596def update_mapping(gw_session: GatewaySession, mapping_id: str, - 597 attributes: dict) -> bool: - 598 ''' - 599 Updates the mapping with ID `mapping_id` with the given `attributes`, - 600 for example name or entry path.\n - 601 Returns True if update was successful and False if no mapping with ID - 602 `mapping_id` was found. - 603 ''' - 604 data = { - 605 "data": { - 606 "type": 'mapping', - 607 "attributes": attributes - 608 } - 609 } - 610 path = f'/configuration/mappings/{mapping_id}' - 611 res = patch(gw_session, path, data, [200, 404]) - 612 return res.status_code == 200 - 613 - 614 - 615def add_mapping(gw_session: GatewaySession, name: str, - 616 template: str = 'New_Mapping', entry_path: str = '/') -> str: - 617 ''' - 618 Adds a new mapping to the Airlock host, with the specified - 619 `name` and `entry_path`.\n Optionally, a template can - 620 be used for the new mapping.\n - 621 Returns the mapping ID of the new mapping. - 622 ''' - 623 templates = get_templates(gw_session) - 624 data = { - 625 "data": { - 626 "type": "create-mapping-from-template", - 627 "attributes": { - 628 "id": templates[template] - 629 } - 630 } - 631 } - 632 path = '/configuration/mappings/create-from-template' - 633 res = post(gw_session, path, data, 201) - 634 mapping_id = res.json()['data']['id'] - 635 attributes = { - 636 "name": name, - 637 "entryPath": {"value": entry_path} - 638 } - 639 update_mapping(gw_session, mapping_id, attributes) - 640 return mapping_id - 641 - 642 - 643def set_source_mapping(gw_session: GatewaySession, mapping_id: str, - 644 src_mapping_id: str) -> bool: - 645 ''' - 646 Sets the source mapping of mapping with ID `mapping_id` - 647 to the mapping with ID `src_mapping_id`. \n - 648 Returns True if the operation was successful and False if - 649 no mapping with ID `mapping_id` was found. - 650 ''' - 651 data = { - 652 "data": { - 653 "type": 'mapping', - 654 "id": src_mapping_id - 655 } - 656 } - 657 path = f'/configuration/mappings/{mapping_id}/relationships/template' - 658 res = patch(gw_session, path, data, [204, 404]) - 659 if res.status_code == 404: - 660 return False - 661 - 662 lock_cfg = { - 663 "enabled": True, - 664 "labels": True, - 665 "entryPath": {"settings": True} - 666 } - 667 - 668 return update_mapping(gw_session, mapping_id, {"locking": lock_cfg}) - 669 - 670 - 671def pull_from_source_mapping(gw_session: GatewaySession, - 672 mapping_id: str) -> bool: - 673 ''' - 674 Performs a pull from the source mapping on the mapping with - 675 ID `mapping_id`.\n - 676 Returns True if the pull was succesfull and False if no mapping with ID - 677 `mapping_id` was found. - 678 ''' - 679 path = f'/configuration/mappings/{mapping_id}/pull-from-source-mapping' - 680 res = post(gw_session, path, exp_code=[200, 404]) - 681 return res.status_code == 200 - 682 - 683 - 684def gen_backend_host(protocol: str, name: str, port: int) -> dict: - 685 ''' - 686 Returns a dictionary object representing a new Backend Host. - 687 ''' - 688 host_data = { - 689 "protocol": protocol, - 690 "hostName": name, - 691 "port": port - 692 } - 693 return host_data - 694 - 695 - 696def add_backend_group(gw_session: GatewaySession, beg_name: str, - 697 be_hosts: list) -> str: - 698 ''' - 699 Adds a new Backend Group with the name `beg_name` and the hosts - 700 contained in `be_hosts` to the Airlock Host.\n - 701 Returns the ID of the newly added Backend Group. - 702 ''' - 703 beg_data = { - 704 "data": { - 705 "type": "back-end-group", - 706 "attributes": { - 707 "name": beg_name, - 708 "backendHosts": be_hosts - 709 } - 710 } - 711 } - 712 res = post(gw_session, "/configuration/back-end-groups", beg_data, 201) - 713 return res.json()['data']['id'] - 714 - 715 - 716def get_backend_groups(gw_session: GatewaySession) -> list: - 717 ''' - 718 Returns a list containing all backend groups on the Airlock Host. - 719 ''' - 720 res = get(gw_session, '/configuration/back-end-groups', exp_code=200) - 721 return res.json().get('data') - 722 - 723 - 724def get_backend_group_by_id(gw_session: GatewaySession, beg_id: str) -> dict: - 725 ''' - 726 Returns a dictionary object describing the backend group with ID - 727 `beg_id`, or None if no such group was found. - 728 ''' - 729 path = f'/configuration/back-end-groups/{beg_id}' - 730 res = get(gw_session, path, exp_code=[200, 404]) - 731 if res.status_code == 200: - 732 return res.json().get('data') - 733 return None - 734 - 735 - 736def update_backend_group_by_id(gw_session: GatewaySession, beg_id: str, - 737 attributes: dict) -> bool: - 738 ''' - 739 Updates the Backend Group with ID `beg_id` with the given attributes, - 740 for example hostname or port. \n - 741 Returns True if the update was succesfull and False if no Backend Group - 742 with ID `beg_id` was found. - 743 ''' - 744 beg_data = { - 745 "data": { - 746 "type": "back-end-group", - 747 "id": beg_id, - 748 "attributes": attributes - 749 } - 750 } - 751 path = f"/configuration/back-end-groups/{beg_id}" - 752 res = patch(gw_session, path, beg_data, [200, 404]) - 753 return res.status_code == 200 - 754 - 755 - 756def delete_backend_group_by_id(gw_session: GatewaySession, - 757 beg_id: str) -> bool: - 758 ''' - 759 Deletes the Backend Group with ID `beg_id` from the Airlock Host.\n - 760 Returns True if deletion was successful and False if no Backend - 761 Group with ID `beg_id` was found. - 762 ''' - 763 path = f"/configuration/back-end-groups/{beg_id}" - 764 res = delete(gw_session, path, exp_code=[204, 404]) - 765 return res.status_code == 204 - 766 - 767 - 768def connect_virtual_host_to_map(gw_session: GatewaySession, vh_id: str, - 769 mapping_id: str) -> bool: - 770 ''' - 771 Connects Virtual Host with id `vh_id` to the Mapping with ID - 772 `mapping_id`.\n Returns True if the operation was successful - 773 and False if one of the provided IDs was not found. - 774 ''' - 775 data = { - 776 "data": [{ - 777 "type": 'mapping', - 778 "id": mapping_id - 779 }] - 780 } - 781 path = f'/configuration/virtual-hosts/{vh_id}/relationships/mappings' - 782 res = patch(gw_session, path, data, [204, 404]) - 783 return res.status_code == 204 - 784 - 785 - 786def connect_map_to_beg(gw_session: GatewaySession, mapping_id: str, - 787 beg_ids: list) -> bool: - 788 ''' - 789 Connects Mapping with ID `mapping_id` to the Backend Groups - 790 with IDs in `beg_ids`.\n - 791 Returns True if the operation was successful and False if one of - 792 the provided IDs was not found. - 793 ''' - 794 data = { - 795 "data": [] - 796 } - 797 for beg_id in beg_ids: - 798 group = { - 799 "type": 'back-end-group', - 800 "id": beg_id - 801 } - 802 data['data'].append(group) - 803 map_id = mapping_id - 804 path = f'/configuration/mappings/{map_id}/relationships/back-end-groups' - 805 res = patch(gw_session, path, data, [204, 404]) - 806 return res.status_code == 204 - 807 - 808 - 809def disconnect_virtual_host_to_map(gw_session: GatewaySession, vh_id: str, - 810 mapping_id: str) -> bool: - 811 ''' - 812 Disconnects Virtual Host with id `vh_id` to the Mapping with - 813 ID `mapping_id`.\n Returns True if the operation was successful - 814 and False if one of the provided IDs was not found. - 815 ''' - 816 data = { - 817 "data": [{ - 818 "type": 'mapping', - 819 "id": mapping_id - 820 }] - 821 } - 822 path = f'/configuration/virtual-hosts/{vh_id}/relationships/mappings' - 823 res = delete(gw_session, path, data, [204, 404]) - 824 return res.status_code == 204 - 825 - 826 - 827def disconnect_map_to_beg(gw_session: GatewaySession, mapping_id: str, - 828 beg_ids: list) -> bool: - 829 ''' - 830 Disconnects Mapping with ID `mapping_id` from the Backend Groups - 831 with IDs in `beg_ids`.\n Returns True if the operation was successful - 832 and False if one of the provided IDs was not found. - 833 ''' - 834 data = { - 835 "data": [] - 836 } - 837 for beg_id in beg_ids: - 838 group = { - 839 "type": 'back-end-group', - 840 "id": beg_id - 841 } - 842 data['data'].append(group) - 843 map_id = mapping_id - 844 path = f'/configuration/mappings/{map_id}/relationships/back-end-groups' - 845 res = delete(gw_session, path, data, [204, 404]) - 846 return res.status_code == 204 - 847 - 848 - 849def get_mapping_deny_rule_group(gw_session: GatewaySession, mapping_id: str, - 850 denyrule_group_shortname: str) -> dict: - 851 ''' - 852 Returns a dictionary object describing the deny rule group in the - 853 specified Mapping, or None if the mapping or shortname specified were not - 854 found. - 855 ''' - 856 path = f'/configuration/mappings/{mapping_id}/deny-rule-groups/{denyrule_group_shortname}' - 857 res = get(gw_session, path, exp_code=[200, 404]) - 858 return res.json().get('data') - 859 - 860 - 861def update_mapping_deny_rule_group(gw_session: GatewaySession, mapping_id: str, - 862 denyrule_group_shortname: str, - 863 attributes: dict) -> bool: - 864 ''' - 865 Updates the settings for a deny rule group within a specified mapping. - 866 Returns True if successful, and False if if the mapping or shortname - 867 specified were not found. - 868 ''' - 869 path = f'/configuration/mappings/{mapping_id}/deny-rule-groups/{denyrule_group_shortname}' - 870 data = { - 871 "data": { - 872 "type": "mapping-deny-rule-group", - 873 "attributes": attributes - 874 } - 875 } - 876 res = patch(gw_session, path, data, exp_code=[200, 404]) - 877 return res.status_code == 200 - 878 - 879 - 880def get_mapping_deny_rule(gw_session: GatewaySession, mapping_id: str, - 881 denyrule_shortname: str) -> dict: - 882 ''' - 883 Returns a dictionary object describing the deny rule in the specified - 884 Mapping, or None if the mapping or shortname specified were not found. - 885 ''' - 886 path = f'/configuration/mappings/{mapping_id}/deny-rules/{denyrule_shortname}' - 887 res = get(gw_session, path, exp_code=[200, 404]) - 888 return res.json().get("data") - 889 - 890 - 891def update_mapping_deny_rule(gw_session: GatewaySession, mapping_id: str, - 892 denyrule_shortname: str, attributes: dict) -> bool: - 893 ''' - 894 Updates the settings for a deny rule within a specified mapping. Returns - 895 True if successful, and False if if the mapping or shortname specified - 896 were not found. - 897 ''' - 898 path = f'/configuration/mappings/{mapping_id}/deny-rules/{denyrule_shortname}' - 899 data = { - 900 "data": { - 901 "type": "mapping-deny-rule", - 902 "attributes": attributes - 903 } - 904 } - 905 res = patch(gw_session, path, data, exp_code=[200, 404]) - 906 return res.status_code == 200 - 907 - 908 - 909def get_deny_rule_groups(gw_session: GatewaySession) -> dict: - 910 ''' - 911 Returns a list of all deny rule groups on the Airlock Host. - 912 ''' + 546 mapping_zip.seek(0) + 547 + 548 req_raw(gw_session, "put", "/configuration/mappings/import", + 549 "application/zip", mapping_zip.read(), 200) + 550 + 551 + 552def export_mappings(gw_session: GatewaySession, + 553 mapping_ids: list = None) -> list: + 554 ''' + 555 Returns a list of the XML files describing the mappings with IDs + 556 contained in the `mapping_ids` list.\n + 557 `mapping_ids` must be a list of strings. If it is omitted, all mappings + 558 are returned. \n + 559 If one or more of the mappings IDs is not found, it is ignored. + 560 ''' + 561 if mapping_ids is None: + 562 mapping_ids = [data["id"] for data in get_all_mappings(gw_session)] + 563 + 564 mapping_xmls = [] + 565 for mapping_id in mapping_ids: + 566 gw_session.add_headers({"Accept": "application/zip"}) + 567 path = f'/configuration/mappings/{mapping_id}/export' + 568 res = get(gw_session, path, exp_code=[200, 404]) + 569 if res.status_code == 200: + 570 with ZipFile(BytesIO(res.content)) as zip_file: + 571 with zip_file.open("alec_table.xml", "r") as mapping_xml: + 572 mapping_xmls.append(mapping_xml) + 573 else: + 574 logging.info("Mapping with ID %s was not found on Airlock Host", + 575 mapping_id) + 576 + 577 gw_session.add_headers({"Accept": "application/json"}) + 578 return mapping_xmls + 579 + 580 + 581def delete_mapping_by_id(gw_session: GatewaySession, mapping_id: str) -> bool: + 582 ''' + 583 Deletes the Mapping with the selected ID.\n + 584 Returns True if deletion was successful and False if no mapping with ID + 585 `mapping_id` was found.. + 586 ''' + 587 path = f"/configuration/mappings/{mapping_id}" + 588 res = delete(gw_session, path, exp_code=[204, 404]) + 589 return res.status_code == 204 + 590 + 591 + 592def get_templates(gw_session: GatewaySession) -> dict: + 593 ''' + 594 Returns a dictionary object mapping every mapping template name to its ID. + 595 ''' + 596 res = get(gw_session, '/configuration/templates/mappings', 200) + 597 data = res.json()['data'] + 598 return {x['attributes']['name']: x['id'] for x in data} + 599 + 600 + 601def update_mapping(gw_session: GatewaySession, mapping_id: str, + 602 attributes: dict) -> bool: + 603 ''' + 604 Updates the mapping with ID `mapping_id` with the given `attributes`, + 605 for example name or entry path.\n + 606 Returns True if update was successful and False if no mapping with ID + 607 `mapping_id` was found. + 608 ''' + 609 data = { + 610 "data": { + 611 "type": 'mapping', + 612 "attributes": attributes + 613 } + 614 } + 615 path = f'/configuration/mappings/{mapping_id}' + 616 res = patch(gw_session, path, data, [200, 404]) + 617 return res.status_code == 200 + 618 + 619 + 620def add_mapping(gw_session: GatewaySession, name: str, + 621 template: str = 'New_Mapping', entry_path: str = '/') -> str: + 622 ''' + 623 Adds a new mapping to the Airlock host, with the specified + 624 `name` and `entry_path`.\n Optionally, a template can + 625 be used for the new mapping.\n + 626 Returns the mapping ID of the new mapping. + 627 ''' + 628 templates = get_templates(gw_session) + 629 data = { + 630 "data": { + 631 "type": "create-mapping-from-template", + 632 "attributes": { + 633 "id": templates[template] + 634 } + 635 } + 636 } + 637 path = '/configuration/mappings/create-from-template' + 638 res = post(gw_session, path, data, 201) + 639 mapping_id = res.json()['data']['id'] + 640 attributes = { + 641 "name": name, + 642 "entryPath": {"value": entry_path} + 643 } + 644 update_mapping(gw_session, mapping_id, attributes) + 645 return mapping_id + 646 + 647 + 648def set_source_mapping(gw_session: GatewaySession, mapping_id: str, + 649 src_mapping_id: str) -> bool: + 650 ''' + 651 Sets the source mapping of mapping with ID `mapping_id` + 652 to the mapping with ID `src_mapping_id`. \n + 653 Returns True if the operation was successful and False if + 654 no mapping with ID `mapping_id` was found. + 655 ''' + 656 data = { + 657 "data": { + 658 "type": 'mapping', + 659 "id": src_mapping_id + 660 } + 661 } + 662 path = f'/configuration/mappings/{mapping_id}/relationships/template' + 663 res = patch(gw_session, path, data, [204, 404]) + 664 if res.status_code == 404: + 665 return False + 666 + 667 lock_cfg = { + 668 "enabled": True, + 669 "labels": True, + 670 "entryPath": {"settings": True} + 671 } + 672 + 673 return update_mapping(gw_session, mapping_id, {"locking": lock_cfg}) + 674 + 675 + 676def pull_from_source_mapping(gw_session: GatewaySession, + 677 mapping_id: str) -> bool: + 678 ''' + 679 Performs a pull from the source mapping on the mapping with + 680 ID `mapping_id`.\n + 681 Returns True if the pull was succesfull and False if no mapping with ID + 682 `mapping_id` was found. + 683 ''' + 684 path = f'/configuration/mappings/{mapping_id}/pull-from-source-mapping' + 685 res = post(gw_session, path, exp_code=[200, 404]) + 686 return res.status_code == 200 + 687 + 688 + 689def gen_backend_host(protocol: str, name: str, port: int) -> dict: + 690 ''' + 691 Returns a dictionary object representing a new Backend Host. + 692 ''' + 693 host_data = { + 694 "protocol": protocol, + 695 "hostName": name, + 696 "port": port + 697 } + 698 return host_data + 699 + 700 + 701def add_backend_group(gw_session: GatewaySession, beg_name: str, + 702 be_hosts: list) -> str: + 703 ''' + 704 Adds a new Backend Group with the name `beg_name` and the hosts + 705 contained in `be_hosts` to the Airlock Host.\n + 706 Returns the ID of the newly added Backend Group. + 707 ''' + 708 beg_data = { + 709 "data": { + 710 "type": "back-end-group", + 711 "attributes": { + 712 "name": beg_name, + 713 "backendHosts": be_hosts + 714 } + 715 } + 716 } + 717 res = post(gw_session, "/configuration/back-end-groups", beg_data, 201) + 718 return res.json()['data']['id'] + 719 + 720 + 721def get_backend_groups(gw_session: GatewaySession) -> list: + 722 ''' + 723 Returns a list containing all backend groups on the Airlock Host. + 724 ''' + 725 res = get(gw_session, '/configuration/back-end-groups', exp_code=200) + 726 return res.json().get('data') + 727 + 728 + 729def get_backend_group_by_id(gw_session: GatewaySession, beg_id: str) -> dict: + 730 ''' + 731 Returns a dictionary object describing the backend group with ID + 732 `beg_id`, or None if no such group was found. + 733 ''' + 734 path = f'/configuration/back-end-groups/{beg_id}' + 735 res = get(gw_session, path, exp_code=[200, 404]) + 736 if res.status_code == 200: + 737 return res.json().get('data') + 738 return None + 739 + 740 + 741def update_backend_group_by_id(gw_session: GatewaySession, beg_id: str, + 742 attributes: dict) -> bool: + 743 ''' + 744 Updates the Backend Group with ID `beg_id` with the given attributes, + 745 for example hostname or port. \n + 746 Returns True if the update was succesfull and False if no Backend Group + 747 with ID `beg_id` was found. + 748 ''' + 749 beg_data = { + 750 "data": { + 751 "type": "back-end-group", + 752 "id": beg_id, + 753 "attributes": attributes + 754 } + 755 } + 756 path = f"/configuration/back-end-groups/{beg_id}" + 757 res = patch(gw_session, path, beg_data, [200, 404]) + 758 return res.status_code == 200 + 759 + 760 + 761def delete_backend_group_by_id(gw_session: GatewaySession, + 762 beg_id: str) -> bool: + 763 ''' + 764 Deletes the Backend Group with ID `beg_id` from the Airlock Host.\n + 765 Returns True if deletion was successful and False if no Backend + 766 Group with ID `beg_id` was found. + 767 ''' + 768 path = f"/configuration/back-end-groups/{beg_id}" + 769 res = delete(gw_session, path, exp_code=[204, 404]) + 770 return res.status_code == 204 + 771 + 772 + 773def connect_virtual_host_to_map(gw_session: GatewaySession, vh_id: str, + 774 mapping_id: str) -> bool: + 775 ''' + 776 Connects Virtual Host with id `vh_id` to the Mapping with ID + 777 `mapping_id`.\n Returns True if the operation was successful + 778 and False if one of the provided IDs was not found. + 779 ''' + 780 data = { + 781 "data": [{ + 782 "type": 'mapping', + 783 "id": mapping_id + 784 }] + 785 } + 786 path = f'/configuration/virtual-hosts/{vh_id}/relationships/mappings' + 787 res = patch(gw_session, path, data, [204, 404]) + 788 return res.status_code == 204 + 789 + 790 + 791def connect_map_to_beg(gw_session: GatewaySession, mapping_id: str, + 792 beg_ids: list) -> bool: + 793 ''' + 794 Connects Mapping with ID `mapping_id` to the Backend Groups + 795 with IDs in `beg_ids`.\n + 796 Returns True if the operation was successful and False if one of + 797 the provided IDs was not found. + 798 ''' + 799 data = { + 800 "data": [] + 801 } + 802 for beg_id in beg_ids: + 803 group = { + 804 "type": 'back-end-group', + 805 "id": beg_id + 806 } + 807 data['data'].append(group) + 808 map_id = mapping_id + 809 path = f'/configuration/mappings/{map_id}/relationships/back-end-groups' + 810 res = patch(gw_session, path, data, [204, 404]) + 811 return res.status_code == 204 + 812 + 813 + 814def disconnect_virtual_host_to_map(gw_session: GatewaySession, vh_id: str, + 815 mapping_id: str) -> bool: + 816 ''' + 817 Disconnects Virtual Host with id `vh_id` to the Mapping with + 818 ID `mapping_id`.\n Returns True if the operation was successful + 819 and False if one of the provided IDs was not found. + 820 ''' + 821 data = { + 822 "data": [{ + 823 "type": 'mapping', + 824 "id": mapping_id + 825 }] + 826 } + 827 path = f'/configuration/virtual-hosts/{vh_id}/relationships/mappings' + 828 res = delete(gw_session, path, data, [204, 404]) + 829 return res.status_code == 204 + 830 + 831 + 832def disconnect_map_to_beg(gw_session: GatewaySession, mapping_id: str, + 833 beg_ids: list) -> bool: + 834 ''' + 835 Disconnects Mapping with ID `mapping_id` from the Backend Groups + 836 with IDs in `beg_ids`.\n Returns True if the operation was successful + 837 and False if one of the provided IDs was not found. + 838 ''' + 839 data = { + 840 "data": [] + 841 } + 842 for beg_id in beg_ids: + 843 group = { + 844 "type": 'back-end-group', + 845 "id": beg_id + 846 } + 847 data['data'].append(group) + 848 map_id = mapping_id + 849 path = f'/configuration/mappings/{map_id}/relationships/back-end-groups' + 850 res = delete(gw_session, path, data, [204, 404]) + 851 return res.status_code == 204 + 852 + 853 + 854def get_mapping_deny_rule_group(gw_session: GatewaySession, mapping_id: str, + 855 denyrule_group_shortname: str) -> dict: + 856 ''' + 857 Returns a dictionary object describing the deny rule group in the + 858 specified Mapping, or None if the mapping or shortname specified were not + 859 found. + 860 ''' + 861 path = f'/configuration/mappings/{mapping_id}/deny-rule-groups/{denyrule_group_shortname}' + 862 res = get(gw_session, path, exp_code=[200, 404]) + 863 return res.json().get('data') + 864 + 865 + 866def update_mapping_deny_rule_group(gw_session: GatewaySession, mapping_id: str, + 867 denyrule_group_shortname: str, + 868 attributes: dict) -> bool: + 869 ''' + 870 Updates the settings for a deny rule group within a specified mapping. + 871 Returns True if successful, and False if if the mapping or shortname + 872 specified were not found. + 873 ''' + 874 path = f'/configuration/mappings/{mapping_id}/deny-rule-groups/{denyrule_group_shortname}' + 875 data = { + 876 "data": { + 877 "type": "mapping-deny-rule-group", + 878 "attributes": attributes + 879 } + 880 } + 881 res = patch(gw_session, path, data, exp_code=[200, 404]) + 882 return res.status_code == 200 + 883 + 884 + 885def get_mapping_deny_rule(gw_session: GatewaySession, mapping_id: str, + 886 denyrule_shortname: str) -> dict: + 887 ''' + 888 Returns a dictionary object describing the deny rule in the specified + 889 Mapping, or None if the mapping or shortname specified were not found. + 890 ''' + 891 path = f'/configuration/mappings/{mapping_id}/deny-rules/{denyrule_shortname}' + 892 res = get(gw_session, path, exp_code=[200, 404]) + 893 return res.json().get("data") + 894 + 895 + 896def update_mapping_deny_rule(gw_session: GatewaySession, mapping_id: str, + 897 denyrule_shortname: str, attributes: dict) -> bool: + 898 ''' + 899 Updates the settings for a deny rule within a specified mapping. Returns + 900 True if successful, and False if if the mapping or shortname specified + 901 were not found. + 902 ''' + 903 path = f'/configuration/mappings/{mapping_id}/deny-rules/{denyrule_shortname}' + 904 data = { + 905 "data": { + 906 "type": "mapping-deny-rule", + 907 "attributes": attributes + 908 } + 909 } + 910 res = patch(gw_session, path, data, exp_code=[200, 404]) + 911 return res.status_code == 200 + 912 913 - 914 path = '/configuration/deny-rule-groups' - 915 res = get(gw_session, path, exp_code=200) - 916 return res.json().get("data") - 917 + 914def get_deny_rule_groups(gw_session: GatewaySession) -> dict: + 915 ''' + 916 Returns a list of all deny rule groups on the Airlock Host. + 917 ''' 918 - 919def get_deny_rule_group(gw_session: GatewaySession, short_name: str) -> dict: - 920 ''' - 921 Returns a dictionary object describing the specified deny rule group, - 922 or None if it does not exist. - 923 ''' - 924 - 925 path = f'/configuration/deny-rule-groups/{short_name}' - 926 res = get(gw_session, path, exp_code=[200, 404]) - 927 return res.json().get("data") - 928 + 919 path = '/configuration/deny-rule-groups' + 920 res = get(gw_session, path, exp_code=200) + 921 return res.json().get("data") + 922 + 923 + 924def get_deny_rule_group(gw_session: GatewaySession, short_name: str) -> dict: + 925 ''' + 926 Returns a dictionary object describing the specified deny rule group, + 927 or None if it does not exist. + 928 ''' 929 - 930def get_deny_rules(gw_session: GatewaySession) -> list: - 931 ''' - 932 Returns a list of all deny-rules on the Airlock Host. - 933 ''' + 930 path = f'/configuration/deny-rule-groups/{short_name}' + 931 res = get(gw_session, path, exp_code=[200, 404]) + 932 return res.json().get("data") + 933 934 - 935 path = '/configuration/deny-rules' - 936 res = get(gw_session, path, exp_code=200) - 937 return res.json().get("data") - 938 + 935def get_deny_rules(gw_session: GatewaySession) -> list: + 936 ''' + 937 Returns a list of all deny-rules on the Airlock Host. + 938 ''' 939 - 940def get_deny_rule(gw_session: GatewaySession, short_name: str) -> dict: - 941 ''' - 942 Returns a dictionary object describing the specified deny-rule, or None - 943 if it does not exist. - 944 ''' - 945 path = f'/configuration/deny-rules/{short_name}' - 946 res = get(gw_session, path, exp_code=[200, 404]) - 947 return res.json().get("data") - 948 - 949 - 950def load_config(gw_session: GatewaySession, config_id: int, - 951 host_name: str = None) -> bool: - 952 ''' - 953 Loads the configuration with ID `config_id` on the Airlock Host.\n - 954 Returns True if the operation was successful and False if no configuration - 955 with ID `config_id` was found. - 956 ''' - 957 data = {"hostname": host_name or gw_session.host_name} - 958 path = f"/configuration/configurations/{config_id}/load" - 959 res = post(gw_session, path, data, [204, 404]) - 960 return res.status_code == 204 - 961 - 962 - 963def load_empty_config(gw_session: GatewaySession, host_name: str = None): - 964 ''' - 965 Loads the empty configuration on the Airlock Host. - 966 ''' - 967 data = {"hostname": host_name or gw_session.host_name} - 968 path = "/configuration/configurations/load-empty-config" - 969 post(gw_session, path, data, 204) - 970 - 971 - 972def load_active_config(gw_session: GatewaySession): - 973 ''' - 974 Loads the currently active configuration on the Airlock Host. - 975 ''' - 976 post(gw_session, '/configuration/configurations/load-active', None, 204) - 977 - 978 - 979def load_initial_config(gw_session: GatewaySession): - 980 ''' - 981 Loads the initial configuration on the Airlock Host. - 982 ''' - 983 res = get(gw_session, '/configuration/configurations', exp_code=200) - 984 data = res.json()['data'] - 985 init_cfg_id = [x['id'] for x in data - 986 if x['attributes']['configType'] == 'INITIAL'][0] - 987 path = f'/configuration/configurations/{init_cfg_id}/load' - 988 post(gw_session, path, None, 204) - 989 - 990 - 991def _get_hostname_from_config_zip(cfg_zip: str): - 992 ''' - 993 Returns the name of the Airlock Host from the config - 994 zip file located at `cfg_zip`. - 995 ''' - 996 host_name = None - 997 with zipfile.ZipFile(cfg_zip) as zip_file: - 998 with zip_file.open('alec_full.xml') as config_xml: - 999 doc = ET.parse(config_xml) -1000 host_names = [n.text for n in doc.findall("./Nodes/*/HostName")] -1001 if host_names: -1002 host_name = host_names[0] -1003 return host_name -1004 -1005 -1006def import_config(gw_session: GatewaySession, cfg_zip: str): -1007 ''' -1008 Imports the configuration zip file located at -1009 `cfg_zip` to the Airlock Host. -1010 ''' -1011 with open(cfg_zip, 'rb') as file: -1012 cfg_host_name = _get_hostname_from_config_zip(cfg_zip) -1013 load_empty_config(gw_session, cfg_host_name) -1014 path = "/configuration/configurations/import/" -1015 req_raw(gw_session, "PUT", path, "application/zip", file, 200) -1016 -1017 -1018def _export_current_config_data(gw_session: GatewaySession): -1019 ''' -1020 Returns a zip file that describes the currently active configuration -1021 on Airlock Host. -1022 ''' -1023 path = '/configuration/configurations/export' -1024 res = get(gw_session, path, exp_code=200) -1025 return res.content -1026 -1027 -1028def export_current_config_file(gw_session: GatewaySession, cfg_zip: str): -1029 ''' -1030 Exports the currently active configuration to a -1031 zip file located at `cfg_zip`. -1032 ''' -1033 data = _export_current_config_data(gw_session) -1034 with open(cfg_zip, 'wb') as file: -1035 file.write(data) -1036 -1037 -1038def get_error_page_settings(gw_session: GatewaySession) -> dict: -1039 ''' -1040 Returns a dictionary object describing the current error page settings. -1041 ''' -1042 path = '/configuration/error-pages' -1043 res = get(gw_session, path, exp_code=200) -1044 return res.json().get('data') -1045 -1046 -1047def set_error_page_settings(gw_session: GatewaySession, attributes: dict): -1048 ''' -1049 Updates the error page settings with the given attributes. -1050 ''' -1051 path = '/configuration/error-pages' -1052 data = { -1053 "data": { -1054 "type": "error-pages", -1055 "attributes": attributes -1056 } -1057 } -1058 patch(gw_session, path, data, exp_code=200) -1059 -1060 -1061def get_error_pages(gw_session: GatewaySession) -> Union[bytes, None]: -1062 ''' -1063 Returns a zip file containing the error pages -1064 ''' -1065 path = '/configuration/error-pages/content' -1066 res = get(gw_session, path, exp_code=[200, 404]) -1067 if res.status_code == 404: -1068 return None -1069 return res.content -1070 -1071 -1072def set_error_pages(gw_session: GatewaySession, error_page_zip: str): -1073 ''' -1074 Imports the error page zip-file located at `error_page_zip`. -1075 ''' -1076 with open(error_page_zip, 'rb') as file: -1077 path = "/configuration/error-pages/content" -1078 req_raw(gw_session, "PUT", path, "application/zip", file, 200) -1079 -1080 -1081def delete_error_pages(gw_session: GatewaySession): -1082 ''' -1083 Remove the custom error pages. -1084 ''' -1085 path = '/configuration/error-pages/content' -1086 delete(gw_session, path, exp_code=200) -1087 -1088 -1089def get_default_error_pages(gw_session: GatewaySession) -> bytes: -1090 ''' -1091 Returns a zip file containing the default error pages. -1092 ''' -1093 path = '/configuration/error-pages/content/default' -1094 res = get(gw_session, path, exp_code=200) -1095 return res.content -1096 -1097 -1098def get_expert_settings(gw_session: GatewaySession) -> dict: -1099 ''' -1100 Returns a dict containing the global expert settings for the Gateway as well as for Apache -1101 ''' -1102 path = '/configuration/expert-settings' -1103 res = get(gw_session, path, exp_code=200) -1104 return res.json().get('data') -1105 -1106 -1107def set_expert_settings(gw_session: GatewaySession, attributes: dict) -> None: -1108 ''' -1109 Updates the global expert settings with the given attributes. -1110 ''' -1111 path = '/configuration/expert-settings' -1112 data = { -1113 "data": { -1114 "type": 'expert-settings', -1115 "attributes": attributes -1116 } -1117 } -1118 patch(gw_session, path, data, exp_code=200) + 940 path = '/configuration/deny-rules' + 941 res = get(gw_session, path, exp_code=200) + 942 return res.json().get("data") + 943 + 944 + 945def get_deny_rule(gw_session: GatewaySession, short_name: str) -> dict: + 946 ''' + 947 Returns a dictionary object describing the specified deny-rule, or None + 948 if it does not exist. + 949 ''' + 950 path = f'/configuration/deny-rules/{short_name}' + 951 res = get(gw_session, path, exp_code=[200, 404]) + 952 return res.json().get("data") + 953 + 954 + 955def load_config(gw_session: GatewaySession, config_id: int, + 956 host_name: str = None) -> bool: + 957 ''' + 958 Loads the configuration with ID `config_id` on the Airlock Host.\n + 959 Returns True if the operation was successful and False if no configuration + 960 with ID `config_id` was found. + 961 ''' + 962 data = {"hostname": host_name or gw_session.host_name} + 963 path = f"/configuration/configurations/{config_id}/load" + 964 res = post(gw_session, path, data, [204, 404]) + 965 return res.status_code == 204 + 966 + 967 + 968def load_empty_config(gw_session: GatewaySession, host_name: str = None): + 969 ''' + 970 Loads the empty configuration on the Airlock Host. + 971 ''' + 972 data = {"hostname": host_name or gw_session.host_name} + 973 path = "/configuration/configurations/load-empty-config" + 974 post(gw_session, path, data, 204) + 975 + 976 + 977def load_active_config(gw_session: GatewaySession): + 978 ''' + 979 Loads the currently active configuration on the Airlock Host. + 980 ''' + 981 post(gw_session, '/configuration/configurations/load-active', None, 204) + 982 + 983 + 984def load_initial_config(gw_session: GatewaySession): + 985 ''' + 986 Loads the initial configuration on the Airlock Host. + 987 ''' + 988 res = get(gw_session, '/configuration/configurations', exp_code=200) + 989 data = res.json()['data'] + 990 init_cfg_id = [x['id'] for x in data + 991 if x['attributes']['configType'] == 'INITIAL'][0] + 992 path = f'/configuration/configurations/{init_cfg_id}/load' + 993 post(gw_session, path, None, 204) + 994 + 995 + 996def _get_hostname_from_config_zip(cfg_zip: str): + 997 ''' + 998 Returns the name of the Airlock Host from the config + 999 zip file located at `cfg_zip`. +1000 ''' +1001 host_name = None +1002 with zipfile.ZipFile(cfg_zip) as zip_file: +1003 with zip_file.open('alec_full.xml') as config_xml: +1004 doc = ET.parse(config_xml) +1005 host_names = [n.text for n in doc.findall("./Nodes/*/HostName")] +1006 if host_names: +1007 host_name = host_names[0] +1008 return host_name +1009 +1010 +1011def import_config(gw_session: GatewaySession, cfg_zip: str): +1012 ''' +1013 Imports the configuration zip file located at +1014 `cfg_zip` to the Airlock Host. +1015 ''' +1016 with open(cfg_zip, 'rb') as file: +1017 cfg_host_name = _get_hostname_from_config_zip(cfg_zip) +1018 load_empty_config(gw_session, cfg_host_name) +1019 path = "/configuration/configurations/import/" +1020 req_raw(gw_session, "PUT", path, "application/zip", file, 200) +1021 +1022 +1023def _export_current_config_data(gw_session: GatewaySession): +1024 ''' +1025 Returns a zip file that describes the currently active configuration +1026 on Airlock Host. +1027 ''' +1028 path = '/configuration/configurations/export' +1029 res = get(gw_session, path, exp_code=200) +1030 return res.content +1031 +1032 +1033def export_current_config_file(gw_session: GatewaySession, cfg_zip: str): +1034 ''' +1035 Exports the currently active configuration to a +1036 zip file located at `cfg_zip`. +1037 ''' +1038 data = _export_current_config_data(gw_session) +1039 with open(cfg_zip, 'wb') as file: +1040 file.write(data) +1041 +1042 +1043def get_error_page_settings(gw_session: GatewaySession) -> dict: +1044 ''' +1045 Returns a dictionary object describing the current error page settings. +1046 ''' +1047 path = '/configuration/error-pages' +1048 res = get(gw_session, path, exp_code=200) +1049 return res.json().get('data') +1050 +1051 +1052def set_error_page_settings(gw_session: GatewaySession, attributes: dict): +1053 ''' +1054 Updates the error page settings with the given attributes. +1055 ''' +1056 path = '/configuration/error-pages' +1057 data = { +1058 "data": { +1059 "type": "error-pages", +1060 "attributes": attributes +1061 } +1062 } +1063 patch(gw_session, path, data, exp_code=200) +1064 +1065 +1066def get_error_pages(gw_session: GatewaySession) -> Union[bytes, None]: +1067 ''' +1068 Returns a zip file containing the error pages +1069 ''' +1070 path = '/configuration/error-pages/content' +1071 res = get(gw_session, path, exp_code=[200, 404]) +1072 if res.status_code == 404: +1073 return None +1074 return res.content +1075 +1076 +1077def set_error_pages(gw_session: GatewaySession, error_page_zip: str): +1078 ''' +1079 Imports the error page zip-file located at `error_page_zip`. +1080 ''' +1081 with open(error_page_zip, 'rb') as file: +1082 path = "/configuration/error-pages/content" +1083 req_raw(gw_session, "PUT", path, "application/zip", file, 200) +1084 +1085 +1086def delete_error_pages(gw_session: GatewaySession): +1087 ''' +1088 Remove the custom error pages. +1089 ''' +1090 path = '/configuration/error-pages/content' +1091 delete(gw_session, path, exp_code=200) +1092 +1093 +1094def get_default_error_pages(gw_session: GatewaySession) -> bytes: +1095 ''' +1096 Returns a zip file containing the default error pages. +1097 ''' +1098 path = '/configuration/error-pages/content/default' +1099 res = get(gw_session, path, exp_code=200) +1100 return res.content +1101 +1102 +1103def get_expert_settings(gw_session: GatewaySession) -> dict: +1104 ''' +1105 Returns a dict containing the global expert settings for the Gateway as well as for Apache +1106 ''' +1107 path = '/configuration/expert-settings' +1108 res = get(gw_session, path, exp_code=200) +1109 return res.json().get('data') +1110 +1111 +1112def set_expert_settings(gw_session: GatewaySession, attributes: dict) -> None: +1113 ''' +1114 Updates the global expert settings with the given attributes. +1115 ''' +1116 path = '/configuration/expert-settings' +1117 data = { +1118 "data": { +1119 "type": 'expert-settings', +1120 "attributes": attributes +1121 } +1122 } +1123 patch(gw_session, path, data, exp_code=200) @@ -1428,15 +1433,16 @@

-
41class AirlockGatewayRestError(Exception):
-42    '''
-43    Custom Exception to inform Library users that an unexpected status
-44    has been returbned by the performed REST call.
-45    '''
-46    def __init__(self, status_code, message):
-47        self.status_code = status_code
-48        self.message = "Status code " + str(status_code) + ": " + message
-49        super().__init__(self.message)
+            
43class AirlockGatewayRestError(Exception):
+44    '''
+45    Custom Exception to inform Library users that an unexpected status
+46    has been returbned by the performed REST call.
+47    '''
+48
+49    def __init__(self, status_code, message):
+50        self.status_code = status_code
+51        self.message = "Status code " + str(status_code) + ": " + message
+52        super().__init__(self.message)
 
@@ -1455,10 +1461,10 @@

-
46    def __init__(self, status_code, message):
-47        self.status_code = status_code
-48        self.message = "Status code " + str(status_code) + ": " + message
-49        super().__init__(self.message)
+            
49    def __init__(self, status_code, message):
+50        self.status_code = status_code
+51        self.message = "Status code " + str(status_code) + ": " + message
+52        super().__init__(self.message)
 
@@ -1486,34 +1492,35 @@
Inherited Members
-
52class GatewaySession:
-53    '''Wrapper class for a REST Session with Airlock Gateway.
-54
-55    Uses the `requests` Python library to perform HTTP.
-56    '''
-57    def __init__(self, host_name: str, ses: Session, port: int = None):
-58        self.port = port if port else 443
-59        self.host = f"{host_name}:{port}" if port != 443 else host_name
-60        self.host_name = host_name
-61        self.ses = ses
-62    host = None
-63    host_name = None
-64    port = 443
-65    ses = None
-66
-67    def add_headers(self, headers: dict):
-68        '''
-69        Adds the given `headers` to the REST Session.\n
-70        If one of the given `headers` was already set, it will be
-71        overwritten.
-72        '''
-73        self.ses.headers.update(headers)
-74
-75    def get_session(self) -> Session:
-76        '''
-77        Returns the internal Session object of this object.
-78        '''
-79        return self.ses
+            
55class GatewaySession:
+56    '''Wrapper class for a REST Session with Airlock Gateway.
+57
+58    Uses the `requests` Python library to perform HTTP.
+59    '''
+60
+61    def __init__(self, host_name: str, ses: Session, port: int = None):
+62        self.port = port if port else 443
+63        self.host = f"{host_name}:{port}" if port != 443 else host_name
+64        self.host_name = host_name
+65        self.ses = ses
+66    host = None
+67    host_name = None
+68    port = 443
+69    ses = None
+70
+71    def add_headers(self, headers: dict):
+72        '''
+73        Adds the given `headers` to the REST Session.\n
+74        If one of the given `headers` was already set, it will be
+75        overwritten.
+76        '''
+77        self.ses.headers.update(headers)
+78
+79    def get_session(self) -> Session:
+80        '''
+81        Returns the internal Session object of this object.
+82        '''
+83        return self.ses
 
@@ -1533,11 +1540,11 @@
Inherited Members
-
57    def __init__(self, host_name: str, ses: Session, port: int = None):
-58        self.port = port if port else 443
-59        self.host = f"{host_name}:{port}" if port != 443 else host_name
-60        self.host_name = host_name
-61        self.ses = ses
+            
61    def __init__(self, host_name: str, ses: Session, port: int = None):
+62        self.port = port if port else 443
+63        self.host = f"{host_name}:{port}" if port != 443 else host_name
+64        self.host_name = host_name
+65        self.ses = ses
 
@@ -1555,13 +1562,13 @@
Inherited Members
-
67    def add_headers(self, headers: dict):
-68        '''
-69        Adds the given `headers` to the REST Session.\n
-70        If one of the given `headers` was already set, it will be
-71        overwritten.
-72        '''
-73        self.ses.headers.update(headers)
+            
71    def add_headers(self, headers: dict):
+72        '''
+73        Adds the given `headers` to the REST Session.\n
+74        If one of the given `headers` was already set, it will be
+75        overwritten.
+76        '''
+77        self.ses.headers.update(headers)
 
@@ -1584,11 +1591,11 @@
Inherited Members
-
75    def get_session(self) -> Session:
-76        '''
-77        Returns the internal Session object of this object.
-78        '''
-79        return self.ses
+            
79    def get_session(self) -> Session:
+80        '''
+81        Returns the internal Session object of this object.
+82        '''
+83        return self.ses
 
@@ -1609,13 +1616,13 @@
Inherited Members
-
82def get_version(gw_session: GatewaySession) -> Union[str, None]:
-83    '''
-84    Returns the major and minor realease number (for example 8.0) of the
-85    Airlock Host, or None if the version could not be retrieved.\n
-86    '''
-87    res = get(gw_session, "/system/status/node", exp_code=200)
-88    return res.json()["data"]["attributes"].get("version")
+            
86def get_version(gw_session: GatewaySession) -> Union[str, None]:
+87    '''
+88    Returns the major and minor realease number (for example 8.0) of the
+89    Airlock Host, or None if the version could not be retrieved.\n
+90    '''
+91    res = get(gw_session, "/system/status/node", exp_code=200)
+92    return res.json()["data"]["attributes"].get("version")
 
@@ -1636,24 +1643,24 @@
Inherited Members
-
105def req_raw(gw_session: GatewaySession, method: str, path: str,
-106            ctype: str = None, data=None,
-107            exp_code: Union[list, int] = None) -> Response:
-108    '''
-109    Performs a request to the Airlock Host at the specified path
-110    with the given method. Optionally, the Content Type, payload and
-111    expected response status codes can be specified.\n
-112    Returns the response object to the performed request.
-113    '''
-114    uri = f'https://{gw_session.host}/airlock/rest{path}'
-115    logging.info("Performing a %s request at URI: %s", method, uri)
-116    headers = None
-117    if ctype:
-118        headers = {'Content-Type': ctype}
-119    res = gw_session.ses.request(method, uri, data=data, headers=headers,
-120                                 verify=False)
-121    _res_expect_handle(res, exp_code)
-122    return res
+            
110def req_raw(gw_session: GatewaySession, method: str, path: str,
+111            ctype: str = None, data=None,
+112            exp_code: Union[list, int] = None) -> Response:
+113    '''
+114    Performs a request to the Airlock Host at the specified path
+115    with the given method. Optionally, the Content Type, payload and
+116    expected response status codes can be specified.\n
+117    Returns the response object to the performed request.
+118    '''
+119    uri = f'https://{gw_session.host}/airlock/rest{path}'
+120    logging.info("Performing a %s request at URI: %s", method, uri)
+121    headers = None
+122    if ctype:
+123        headers = {'Content-Type': ctype}
+124    res = gw_session.ses.request(method, uri, data=data, headers=headers,
+125                                 verify=False)
+126    _res_expect_handle(res, exp_code)
+127    return res
 
@@ -1677,23 +1684,23 @@
Inherited Members
-
125def req(gw_session: GatewaySession, method: str,
-126        path: str, body_dict: dict = None,
-127        exp_code: Union[list, int] = None) -> Response:
-128    '''
-129    Performs a request to the Airlock Host at the specified path
-130    with the given method. Optionally, the JSON payload and
-131    expected response status codes can be specified.\n
-132    Returns the response object to the performed request.
-133    '''
-134    uri = f'https://{gw_session.host}/airlock/rest{path}'
-135    logging.info("Performing a %s request at URI: %s ", method, uri)
-136    if isinstance(body_dict, dict):
-137        logging.debug("JSON payload of request:")
-138        logging.debug(json.dumps(body_dict, indent=4))
-139    res = gw_session.ses.request(method, uri, json=body_dict)
-140    _res_expect_handle(res, exp_code)
-141    return res
+            
130def req(gw_session: GatewaySession, method: str,
+131        path: str, body_dict: dict = None,
+132        exp_code: Union[list, int] = None) -> Response:
+133    '''
+134    Performs a request to the Airlock Host at the specified path
+135    with the given method. Optionally, the JSON payload and
+136    expected response status codes can be specified.\n
+137    Returns the response object to the performed request.
+138    '''
+139    uri = f'https://{gw_session.host}/airlock/rest{path}'
+140    logging.info("Performing a %s request at URI: %s ", method, uri)
+141    if isinstance(body_dict, dict):
+142        logging.debug("JSON payload of request:")
+143        logging.debug(json.dumps(body_dict, indent=4))
+144    res = gw_session.ses.request(method, uri, json=body_dict)
+145    _res_expect_handle(res, exp_code)
+146    return res
 
@@ -1717,15 +1724,15 @@
Inherited Members
-
144def post(gw_session: GatewaySession, path: str, body_dict: dict = None,
-145         exp_code: Union[list, int] = None) -> Response:
-146    '''
-147    Performs a POST request to the Airlock Host at the specified path.
-148    Optionally, the JSON payload and expected response status codes
-149    can be specified.\n
-150    Returns the Response object to the performed request.
-151    '''
-152    return req(gw_session, 'POST', path, body_dict, exp_code)
+            
149def post(gw_session: GatewaySession, path: str, body_dict: dict = None,
+150         exp_code: Union[list, int] = None) -> Response:
+151    '''
+152    Performs a POST request to the Airlock Host at the specified path.
+153    Optionally, the JSON payload and expected response status codes
+154    can be specified.\n
+155    Returns the Response object to the performed request.
+156    '''
+157    return req(gw_session, 'POST', path, body_dict, exp_code)
 
@@ -1749,15 +1756,15 @@
Inherited Members
-
155def patch(gw_session: GatewaySession, path: str, body_dict: dict,
-156          exp_code: Union[list, int] = None) -> Response:
-157    '''
-158    Performs a PATCH request to the Airlock Host at the specified path.
-159    Optionally, the JSON payload and expected response status codes
-160    can be specified.\n
-161    Returns the Response object to the performed request.
-162    '''
-163    return req(gw_session, 'PATCH', path, body_dict, exp_code)
+            
160def patch(gw_session: GatewaySession, path: str, body_dict: dict,
+161          exp_code: Union[list, int] = None) -> Response:
+162    '''
+163    Performs a PATCH request to the Airlock Host at the specified path.
+164    Optionally, the JSON payload and expected response status codes
+165    can be specified.\n
+166    Returns the Response object to the performed request.
+167    '''
+168    return req(gw_session, 'PATCH', path, body_dict, exp_code)
 
@@ -1781,15 +1788,15 @@
Inherited Members
-
166def put(gw_session: GatewaySession, path: str, body_dict: dict,
-167        exp_code: Union[list, int] = None) -> Response:
-168    '''
-169    Performs a PUT request to the Airlock Host at the specified path.
-170    Optionally, the JSON payload and expected response status codes
-171    can be specified.\n
-172    Returns the Response object to the performed request.
-173    '''
-174    return req(gw_session, 'PUT', path, body_dict, exp_code)
+            
171def put(gw_session: GatewaySession, path: str, body_dict: dict,
+172        exp_code: Union[list, int] = None) -> Response:
+173    '''
+174    Performs a PUT request to the Airlock Host at the specified path.
+175    Optionally, the JSON payload and expected response status codes
+176    can be specified.\n
+177    Returns the Response object to the performed request.
+178    '''
+179    return req(gw_session, 'PUT', path, body_dict, exp_code)
 
@@ -1813,14 +1820,14 @@
Inherited Members
-
177def delete(gw_session: GatewaySession, path: str, body_dict: dict = None,
-178           exp_code: Union[list, int] = None) -> Response:
-179    '''
-180    Performs a DELETE request to the Airlock Host at the specified path.
-181    Optionally, the expected response status codes can be specified.\n
-182    Returns the Response object to the performed request.
-183    '''
-184    return req(gw_session, 'DELETE', path, body_dict, exp_code)
+            
182def delete(gw_session: GatewaySession, path: str, body_dict: dict = None,
+183           exp_code: Union[list, int] = None) -> Response:
+184    '''
+185    Performs a DELETE request to the Airlock Host at the specified path.
+186    Optionally, the expected response status codes can be specified.\n
+187    Returns the Response object to the performed request.
+188    '''
+189    return req(gw_session, 'DELETE', path, body_dict, exp_code)
 
@@ -1843,14 +1850,14 @@
Inherited Members
-
187def get(gw_session: GatewaySession, path: str,
-188        exp_code: Union[list, int] = None) -> Response:
-189    '''
-190    Performs a GET request to the Airlock Host at the specified path.
-191    Optionally, the expected response status codes can be specified.\n
-192    Returns the Response object to the performed request.
-193    '''
-194    return req(gw_session, 'GET', path, None, exp_code)
+            
192def get(gw_session: GatewaySession, path: str,
+193        exp_code: Union[list, int] = None) -> Response:
+194    '''
+195    Performs a GET request to the Airlock Host at the specified path.
+196    Optionally, the expected response status codes can be specified.\n
+197    Returns the Response object to the performed request.
+198    '''
+199    return req(gw_session, 'GET', path, None, exp_code)
 
@@ -1873,32 +1880,32 @@
Inherited Members
-
197def create_session(host: str, api_key: str, port: int = 443) -> GatewaySession:
-198    '''
-199    Creates a new session with the given host.
-200
-201    Returns the generated GatewaySession object,
-202    or None if the Session couldn't be started.
-203    '''
-204    ses = requests.Session()
-205    ses.verify = False
-206    gw_session = GatewaySession(host, ses, port)
-207    gw_session.add_headers({"Authorization": f"Bearer {api_key}"})
-208    logging.info("Starting the REST Session with Host %s", host)
-209    res = post(gw_session, "/session/create", exp_code=[200, 404])
-210    if res.status_code == 200:
-211        version = get_version(gw_session)
-212        if version:
-213            if not version.startswith(LIBRARY_COMPATIBILITY_VERSION):
-214                logging.warning("You are using Airlock version %s while this \
-215library version is developed for Airlock hosts running version %s. Some Rest \
-216calls will not work on this Airlock version", version,
-217                                LIBRARY_COMPATIBILITY_VERSION)
-218        else:
-219            logging.warning('The Airlock version could not be determined, \
-220this library version might be incompatible with this Airlock Host')
-221        return gw_session
-222    return None
+            
202def create_session(host: str, api_key: str, port: int = 443) -> GatewaySession:
+203    '''
+204    Creates a new session with the given host.
+205
+206    Returns the generated GatewaySession object,
+207    or None if the Session couldn't be started.
+208    '''
+209    ses = requests.Session()
+210    ses.verify = False
+211    gw_session = GatewaySession(host, ses, port)
+212    gw_session.add_headers({"Authorization": f"Bearer {api_key}"})
+213    logging.info("Starting the REST Session with Host %s", host)
+214    res = post(gw_session, "/session/create", exp_code=[200, 404])
+215    if res.status_code == 200:
+216        version = get_version(gw_session)
+217        if version:
+218            if not version.startswith(LIBRARY_COMPATIBILITY_VERSION):
+219                logging.warning("You are using Airlock version %s while this \
+220library version is developed for Airlock hosts running version %s. Some Rest \
+221calls will not work on this Airlock version", version,
+222                                LIBRARY_COMPATIBILITY_VERSION)
+223        else:
+224            logging.warning('The Airlock version could not be determined, \
+225this library version might be incompatible with this Airlock Host')
+226        return gw_session
+227    return None
 
@@ -1921,16 +1928,16 @@
Inherited Members
-
225def create_session_from_cookie(host: str, jsessionid: str) -> GatewaySession:
-226    '''
-227    Retrieves an existing Gateway Session from the JSESSIONID Cookie.\n
-228    Returns the generated GatewaySession object.
-229    '''
-230    ses = requests.Session()
-231    ses.verify = False
-232    cookie = requests.cookies.create_cookie("JSESSIONID", jsessionid)
-233    ses.cookies.set_cookie(cookie)
-234    return GatewaySession(host, ses)
+            
230def create_session_from_cookie(host: str, jsessionid: str) -> GatewaySession:
+231    '''
+232    Retrieves an existing Gateway Session from the JSESSIONID Cookie.\n
+233    Returns the generated GatewaySession object.
+234    '''
+235    ses = requests.Session()
+236    ses.verify = False
+237    cookie = requests.cookies.create_cookie("JSESSIONID", jsessionid)
+238    ses.cookies.set_cookie(cookie)
+239    return GatewaySession(host, ses)
 
@@ -1952,13 +1959,13 @@
Inherited Members
-
245def get_jsession_id(gw_session: GatewaySession) -> str:
-246    '''
-247    Returns the value of the JSESSIONID Cookie,
-248    or None if no such Cookie was found.
-249    '''
-250    cookie = _get_cookies(gw_session).get('JSESSIONID')
-251    return cookie.value if cookie else None
+            
250def get_jsession_id(gw_session: GatewaySession) -> str:
+251    '''
+252    Returns the value of the JSESSIONID Cookie,
+253    or None if no such Cookie was found.
+254    '''
+255    cookie = _get_cookies(gw_session).get('JSESSIONID')
+256    return cookie.value if cookie else None
 
@@ -1979,11 +1986,11 @@
Inherited Members
-
254def terminate_session(gw_session: GatewaySession) -> None:
-255    '''
-256    Terminates the Gateway Session.
-257    '''
-258    post(gw_session, "/session/terminate", exp_code=200)
+            
259def terminate_session(gw_session: GatewaySession) -> None:
+260    '''
+261    Terminates the Gateway Session.
+262    '''
+263    post(gw_session, "/session/terminate", exp_code=200)
 
@@ -2003,13 +2010,13 @@
Inherited Members
-
261def get_configs(gw_session: GatewaySession) -> list:
-262    '''
-263    Returns a list containing all configurations on the
-264    Airlock Host as dictionary objects.
-265    '''
-266    res = get(gw_session, "/configuration/configurations", exp_code=200)
-267    return res.json()["data"]
+            
266def get_configs(gw_session: GatewaySession) -> list:
+267    '''
+268    Returns a list containing all configurations on the
+269    Airlock Host as dictionary objects.
+270    '''
+271    res = get(gw_session, "/configuration/configurations", exp_code=200)
+272    return res.json()["data"]
 
@@ -2030,20 +2037,20 @@
Inherited Members
-
270def validate(gw_session: GatewaySession) -> Tuple[bool, list]:
-271    '''
-272    Returns True and an empty list if the configuration is valid,
-273    False and a list of error messages if it isn't.
-274    '''
-275    path = "/configuration/validator-messages?filter=meta.severity==ERROR"
-276    res = get(gw_session, path, exp_code=200)
-277    rdata = res.json()
-278    if len(rdata["data"]) > 0:
-279        msgs = [e["attributes"]["detail"] for e in rdata["data"]]
-280        logging.info("Validation failed with the following error\
-281 message(s):\n %s", str(msgs))
-282        return False, msgs
-283    return True, []
+            
275def validate(gw_session: GatewaySession) -> Tuple[bool, list]:
+276    '''
+277    Returns True and an empty list if the configuration is valid,
+278    False and a list of error messages if it isn't.
+279    '''
+280    path = "/configuration/validator-messages?filter=meta.severity==ERROR"
+281    res = get(gw_session, path, exp_code=200)
+282    rdata = res.json()
+283    if len(rdata["data"]) > 0:
+284        msgs = [e["attributes"]["detail"] for e in rdata["data"]]
+285        logging.info("Validation failed with the following error\
+286 message(s):\n %s", str(msgs))
+287        return False, msgs
+288    return True, []
 
@@ -2064,24 +2071,24 @@
Inherited Members
-
286def activate(gw_session: GatewaySession, comment: str = None) -> bool:
-287    '''
-288    Activates the currently loaded configuration on Airlock Host and
-289    optionally adds a comment to the activation.\n
-290    Returns True if the configuration was activated successfully and False
-291    otherwise
-292    '''
-293    data = None
-294    if comment:
-295        options = {"ignoreOutdatedConfiguration": True,
-296                   "failoverActivation": False}
-297        data = {"comment": comment, "options": options}
-298    if not validate(gw_session)[0]:
-299        logging.info("Configuration could not be activated as it isn't valid")
-300        return False
-301    path = "/configuration/configurations/activate"
-302    post(gw_session, path, data, 200)
-303    return True
+            
291def activate(gw_session: GatewaySession, comment: str = None) -> bool:
+292    '''
+293    Activates the currently loaded configuration on Airlock Host and
+294    optionally adds a comment to the activation.\n
+295    Returns True if the configuration was activated successfully and False
+296    otherwise
+297    '''
+298    data = None
+299    if comment:
+300        options = {"ignoreOutdatedConfiguration": True,
+301                   "failoverActivation": False}
+302        data = {"comment": comment, "options": options}
+303    if not validate(gw_session)[0]:
+304        logging.info("Configuration could not be activated as it isn't valid")
+305        return False
+306    path = "/configuration/configurations/activate"
+307    post(gw_session, path, data, 200)
+308    return True
 
@@ -2105,23 +2112,23 @@
Inherited Members
-
306def save_config(gw_session: GatewaySession, comment: str = None) -> str:
-307    '''
-308    Saves the current configuration with an optional
-309    `comment` without activating it.\n
-310    Returns the ID of the newly saved configuration or None if
-311    the configuration could not be saved.
-312    '''
-313    data = None
-314    if comment:
-315        data = {"comment": comment}
-316    path = "/configuration/configurations/save"
-317    res = post(gw_session, path, data, [200, 400])
-318    if res.status_code == 400:
-319        logging.warning("Configuration could not be saved\
-320 as no configuration was loaded!")
-321        return None
-322    return res.json()['data']['id']
+            
311def save_config(gw_session: GatewaySession, comment: str = None) -> str:
+312    '''
+313    Saves the current configuration with an optional
+314    `comment` without activating it.\n
+315    Returns the ID of the newly saved configuration or None if
+316    the configuration could not be saved.
+317    '''
+318    data = None
+319    if comment:
+320        data = {"comment": comment}
+321    path = "/configuration/configurations/save"
+322    res = post(gw_session, path, data, [200, 400])
+323    if res.status_code == 400:
+324        logging.warning("Configuration could not be saved\
+325 as no configuration was loaded!")
+326        return None
+327    return res.json()['data']['id']
 
@@ -2145,22 +2152,22 @@
Inherited Members
-
325def update_license(gw_session: GatewaySession, lic_str: str) -> None:
-326    '''
-327    Updates the license on the Airlock Host.
-328    '''
-329    res = get(gw_session, '/configuration/license')
-330    logging.debug("Current license: \n %s", json.dumps(res.json(), indent=4))
-331
-332    lic_patch_data = {
-333        "data": {
-334            "type": "license",
-335            "attributes": {
-336                "license": lic_str
-337            }
-338        }
-339    }
-340    patch(gw_session, "/configuration/license", lic_patch_data, 200)
+            
330def update_license(gw_session: GatewaySession, lic_str: str) -> None:
+331    '''
+332    Updates the license on the Airlock Host.
+333    '''
+334    res = get(gw_session, '/configuration/license')
+335    logging.debug("Current license: \n %s", json.dumps(res.json(), indent=4))
+336
+337    lic_patch_data = {
+338        "data": {
+339            "type": "license",
+340            "attributes": {
+341                "license": lic_str
+342            }
+343        }
+344    }
+345    patch(gw_session, "/configuration/license", lic_patch_data, 200)
 
@@ -2180,13 +2187,13 @@
Inherited Members
-
343def get_virtualhosts(gw_session: GatewaySession) -> list:
-344    '''
-345    Returns a list of dictionary objects describing all
-346    virtual hosts on the Airlock Host.
-347    '''
-348    res = get(gw_session, '/configuration/virtual-hosts', exp_code=200)
-349    return res.json().get('data')
+            
348def get_virtualhosts(gw_session: GatewaySession) -> list:
+349    '''
+350    Returns a list of dictionary objects describing all
+351    virtual hosts on the Airlock Host.
+352    '''
+353    res = get(gw_session, '/configuration/virtual-hosts', exp_code=200)
+354    return res.json().get('data')
 
@@ -2207,46 +2214,46 @@
Inherited Members
-
352def gen_standard_virtual_host_data(vh_name: str, ipv4_addr: str,
-353                                   interface: str,
-354                                   certificate: dict) -> dict:
-355    '''
-356    Generates and returns the data object necessary to upload a new virtual
-357    host to the Airlock Host. This object can then for example be passed
-358    to the `add_virtual_host()` function to add a new virtual host. \n
-359    The virtual host data will have standard values for every attribute that
-360    can not be given to this function as an argument.
-361    '''
-362    host_data = {
-363        "data": {
-364            "type": "virtual-host",
-365            "attributes": {
-366                "name": vh_name,
-367                "hostName": vh_name,
-368                "serverAdmin": "admin@" + vh_name,
-369                "showMaintenancePage": False,
-370                "strictlyMatchFullyQualifiedDomainName": False,
-371                "keepAliveTimeout": 10,
-372                "networkInterface": {
-373                    "externalLogicalInterfaceName": interface,
-374                    "ipV4Address": ipv4_addr,
-375                    "ipV6Address": "",
-376                    "http": {
-377                        "enabled": True,
-378                        "port": 80,
-379                        "httpsRedirectEnforced": True
-380                    },
-381                    "https": {
+            
357def gen_standard_virtual_host_data(vh_name: str, ipv4_addr: str,
+358                                   interface: str,
+359                                   certificate: dict) -> dict:
+360    '''
+361    Generates and returns the data object necessary to upload a new virtual
+362    host to the Airlock Host. This object can then for example be passed
+363    to the `add_virtual_host()` function to add a new virtual host. \n
+364    The virtual host data will have standard values for every attribute that
+365    can not be given to this function as an argument.
+366    '''
+367    host_data = {
+368        "data": {
+369            "type": "virtual-host",
+370            "attributes": {
+371                "name": vh_name,
+372                "hostName": vh_name,
+373                "serverAdmin": "admin@" + vh_name,
+374                "showMaintenancePage": False,
+375                "strictlyMatchFullyQualifiedDomainName": False,
+376                "keepAliveTimeout": 10,
+377                "networkInterface": {
+378                    "externalLogicalInterfaceName": interface,
+379                    "ipV4Address": ipv4_addr,
+380                    "ipV6Address": "",
+381                    "http": {
 382                        "enabled": True,
-383                        "port": 443,
-384                        "http2Allowed": True
-385                    }
-386                },
-387                "tls":  certificate,
-388            }
-389        }
-390    }
-391    return host_data
+383                        "port": 80,
+384                        "httpsRedirectEnforced": True
+385                    },
+386                    "https": {
+387                        "enabled": True,
+388                        "port": 443,
+389                        "http2Allowed": True
+390                    }
+391                },
+392                "tls": certificate,
+393            }
+394        }
+395    }
+396    return host_data
 
@@ -2271,16 +2278,16 @@
Inherited Members
-
394def add_virtual_host(gw_session: GatewaySession, data: dict) -> str:
-395    '''
-396    Adds a new virtual host to the Airlock Host. The `data` parameter
-397    has to fully specify a valid virtual host configuration.\n
-398    For standard virtual hosts configuration use
-399    `add_standard_virtual_host()` instead.\n
-400    Returns the ID of the added virtual host.
-401    '''
-402    res = post(gw_session, "/configuration/virtual-hosts", data, 201)
-403    return res.json()['data']['id']
+            
399def add_virtual_host(gw_session: GatewaySession, data: dict) -> str:
+400    '''
+401    Adds a new virtual host to the Airlock Host. The `data` parameter
+402    has to fully specify a valid virtual host configuration.\n
+403    For standard virtual hosts configuration use
+404    `add_standard_virtual_host()` instead.\n
+405    Returns the ID of the added virtual host.
+406    '''
+407    res = post(gw_session, "/configuration/virtual-hosts", data, 201)
+408    return res.json()['data']['id']
 
@@ -2306,17 +2313,17 @@
Inherited Members
-
406def get_virtual_host_by_id(gw_session: GatewaySession, vh_id: str) -> dict:
-407    '''
-408    Returns a dictionary object representing the virtual host with
-409    the given `vh_id` or None if no such virtual host was found
-410    '''
-411    path = f'/configuration/virtual-hosts/{vh_id}'
-412    res = get(gw_session, path, exp_code=[200, 404])
-413
-414    if res.status_code == 404:
-415        return None
-416    return res.json().get('data')
+            
411def get_virtual_host_by_id(gw_session: GatewaySession, vh_id: str) -> dict:
+412    '''
+413    Returns a dictionary object representing the virtual host with
+414    the given `vh_id` or None if no such virtual host was found
+415    '''
+416    path = f'/configuration/virtual-hosts/{vh_id}'
+417    res = get(gw_session, path, exp_code=[200, 404])
+418
+419    if res.status_code == 404:
+420        return None
+421    return res.json().get('data')
 
@@ -2337,24 +2344,24 @@
Inherited Members
-
419def update_virtual_host_by_id(gw_session: GatewaySession, vh_id: str,
-420                              attributes: dict) -> bool:
-421    '''
-422    Updates the virtual host with ID `vh_id` with the given `attributes`,
-423    for example name, showMaintenancePage etc.\n
-424    Returns True if the update was successful and False if no virtual
-425    host with ID `vh_id` was found.
-426    '''
-427    host_data = {
-428        "data": {
-429            "type": "virtual-host",
-430            "id": vh_id,
-431            "attributes": attributes
-432        }
-433    }
-434    path = f"/configuration/virtual-hosts/{vh_id}"
-435    res = patch(gw_session, path, host_data, [200, 404])
-436    return res.status_code == 200
+            
424def update_virtual_host_by_id(gw_session: GatewaySession, vh_id: str,
+425                              attributes: dict) -> bool:
+426    '''
+427    Updates the virtual host with ID `vh_id` with the given `attributes`,
+428    for example name, showMaintenancePage etc.\n
+429    Returns True if the update was successful and False if no virtual
+430    host with ID `vh_id` was found.
+431    '''
+432    host_data = {
+433        "data": {
+434            "type": "virtual-host",
+435            "id": vh_id,
+436            "attributes": attributes
+437        }
+438    }
+439    path = f"/configuration/virtual-hosts/{vh_id}"
+440    res = patch(gw_session, path, host_data, [200, 404])
+441    return res.status_code == 200
 
@@ -2378,14 +2385,14 @@
Inherited Members
-
439def delete_virtual_host_by_id(gw_session: GatewaySession, vh_id: str) -> bool:
-440    '''
-441    Deletes the Virtual Host with the selected ID.\n
-442    Returns True if deletion was successful and False otherwise.
-443    '''
-444    path = f"/configuration/virtual-hosts/{vh_id}"
-445    res = delete(gw_session, path, exp_code=[204, 404])
-446    return res.status_code == 204
+            
444def delete_virtual_host_by_id(gw_session: GatewaySession, vh_id: str) -> bool:
+445    '''
+446    Deletes the Virtual Host with the selected ID.\n
+447    Returns True if deletion was successful and False otherwise.
+448    '''
+449    path = f"/configuration/virtual-hosts/{vh_id}"
+450    res = delete(gw_session, path, exp_code=[204, 404])
+451    return res.status_code == 204
 
@@ -2407,13 +2414,13 @@
Inherited Members
-
449def get_all_mappings(gw_session: GatewaySession) -> list:
-450    '''
-451    Returns a list of dictionary object describing
-452    all mappings on the Airlock Host.
-453    '''
-454    res = get(gw_session, '/configuration/mappings', 200)
-455    return res.json().get('data')
+            
454def get_all_mappings(gw_session: GatewaySession) -> list:
+455    '''
+456    Returns a list of dictionary object describing
+457    all mappings on the Airlock Host.
+458    '''
+459    res = get(gw_session, '/configuration/mappings', 200)
+460    return res.json().get('data')
 
@@ -2434,29 +2441,29 @@
Inherited Members
-
458def select_mappings(gw_session: GatewaySession, pattern: str = None,
-459                    label: str = None) -> list:
-460    '''
-461    Returns a list of dictionary object describing all mappings
-462    whose name is matched by the `pattern` regular expression
-463    or who are labeled with `label`.\n
-464    If no parameter is given, all mappings are returned.
-465    '''
-466    if (not pattern and not label):
-467        return get_all_mappings(gw_session)
-468    if (pattern and label):
-469        return list(set(select_mappings(gw_session, pattern=pattern))
-470                    + set(select_mappings(gw_session, label=label))
-471                    )
-472    if label:
-473        path = f'/configuration/mappings?filter=label=={label}'
-474        res = get(gw_session, path, exp_code=200)
-475        return res.json().get('data')
-476    mappings = []
-477    for mapping in get_all_mappings(gw_session):
-478        if re.search(pattern, mapping['attributes']['name']):
-479            mappings.append(mapping)
-480    return mappings
+            
463def select_mappings(gw_session: GatewaySession, pattern: str = None,
+464                    label: str = None) -> list:
+465    '''
+466    Returns a list of dictionary object describing all mappings
+467    whose name is matched by the `pattern` regular expression
+468    or who are labeled with `label`.\n
+469    If no parameter is given, all mappings are returned.
+470    '''
+471    if (not pattern and not label):
+472        return get_all_mappings(gw_session)
+473    if (pattern and label):
+474        return list(set(select_mappings(gw_session, pattern=pattern))
+475                    + set(select_mappings(gw_session, label=label))
+476                    )
+477    if label:
+478        path = f'/configuration/mappings?filter=label=={label}'
+479        res = get(gw_session, path, exp_code=200)
+480        return res.json().get('data')
+481    mappings = []
+482    for mapping in get_all_mappings(gw_session):
+483        if re.search(pattern, mapping['attributes']['name']):
+484            mappings.append(mapping)
+485    return mappings
 
@@ -2480,15 +2487,15 @@
Inherited Members
-
483def get_mapping_id(gw_session: GatewaySession, name: str) -> str:
-484    '''
-485    Returns the ID of the mapping with the given `name`
-486    or None if no such mapping was found.
-487    '''
-488    mapping = get_mapping_by_name(gw_session, name)
-489    if mapping:
-490        return mapping['id']
-491    return None
+            
488def get_mapping_id(gw_session: GatewaySession, name: str) -> str:
+489    '''
+490    Returns the ID of the mapping with the given `name`
+491    or None if no such mapping was found.
+492    '''
+493    mapping = get_mapping_by_name(gw_session, name)
+494    if mapping:
+495        return mapping['id']
+496    return None
 
@@ -2509,17 +2516,17 @@
Inherited Members
-
494def get_mapping_by_id(gw_session: GatewaySession, mapping_id: str) -> dict:
-495    '''
-496    Returns a dictionary object representing the mapping
-497    with the given `mapping_id` or None if no such mapping
-498    was found.
-499    '''
-500    path = f'/configuration/mappings/{mapping_id}'
-501    res = get(gw_session, path, exp_code=[200, 404])
-502    if res.status_code == 200:
-503        return res.json().get('data')
-504    return None
+            
499def get_mapping_by_id(gw_session: GatewaySession, mapping_id: str) -> dict:
+500    '''
+501    Returns a dictionary object representing the mapping
+502    with the given `mapping_id` or None if no such mapping
+503    was found.
+504    '''
+505    path = f'/configuration/mappings/{mapping_id}'
+506    res = get(gw_session, path, exp_code=[200, 404])
+507    if res.status_code == 200:
+508        return res.json().get('data')
+509    return None
 
@@ -2541,15 +2548,15 @@
Inherited Members
-
507def get_mapping_by_name(gw_session: GatewaySession, name: str) -> dict:
-508    '''
-509    Returns a dictionary object representing the mapping
-510    with the given `name` or an empty dictionary if no
-511    such mapping was found.
-512    '''
-513    path = f'/configuration/mappings?filter=name=={name}'
-514    res = get(gw_session, path, exp_code=200)
-515    return res.json().get('data')
+            
512def get_mapping_by_name(gw_session: GatewaySession, name: str) -> dict:
+513    '''
+514    Returns a dictionary object representing the mapping
+515    with the given `name` or an empty dictionary if no
+516    such mapping was found.
+517    '''
+518    path = f'/configuration/mappings?filter=name=={name}'
+519    res = get(gw_session, path, exp_code=200)
+520    return res.json().get('data')
 
@@ -2571,16 +2578,16 @@
Inherited Members
-
518def get_all_mapping_names(gw_session: GatewaySession) -> list:
-519    '''
-520    Returns a sorted list of all mapping names on the Airlock Host.
-521    '''
-522    mappings = get_all_mappings(gw_session)
-523    mapping_names = []
-524    for mapping in mappings:
-525        mapping_name = mapping["attributes"]["name"]
-526        mapping_names.append(mapping_name)
-527    return sorted(mapping_names)
+            
523def get_all_mapping_names(gw_session: GatewaySession) -> list:
+524    '''
+525    Returns a sorted list of all mapping names on the Airlock Host.
+526    '''
+527    mappings = get_all_mappings(gw_session)
+528    mapping_names = []
+529    for mapping in mappings:
+530        mapping_name = mapping["attributes"]["name"]
+531        mapping_names.append(mapping_name)
+532    return sorted(mapping_names)
 
@@ -2600,22 +2607,22 @@
Inherited Members
-
530def import_mappings_from_xml(gw_session, mappings_xmls: list):
-531    '''
-532    Adds all mappings specified in the list of dictionary objects
-533    representing XML files stored in  `mappings_xmls` on the
-534    Airlock Host. If a mapping with the same name already exists,
-535    it will be overwritten.
-536    '''
-537    for mapping_xml in mappings_xmls:
-538        mapping_zip = BytesIO()
-539        with ZipFile(mapping_zip, mode="w") as zip_file:
-540            zip_file.writestr("alec_table.xml", mapping_xml)
-541
-542        mapping_zip.seek(0)
-543
-544        req_raw(gw_session, "put", "/configuration/mappings/import",
-545                "application/zip", mapping_zip.read(), 200)
+            
535def import_mappings_from_xml(gw_session, mappings_xmls: list):
+536    '''
+537    Adds all mappings specified in the list of dictionary objects
+538    representing XML files stored in  `mappings_xmls` on the
+539    Airlock Host. If a mapping with the same name already exists,
+540    it will be overwritten.
+541    '''
+542    for mapping_xml in mappings_xmls:
+543        mapping_zip = BytesIO()
+544        with ZipFile(mapping_zip, mode="w") as zip_file:
+545            zip_file.writestr("alec_table.xml", mapping_xml)
+546
+547        mapping_zip.seek(0)
+548
+549        req_raw(gw_session, "put", "/configuration/mappings/import",
+550                "application/zip", mapping_zip.read(), 200)
 
@@ -2638,33 +2645,33 @@
Inherited Members
-
548def export_mappings(gw_session: GatewaySession,
-549                    mapping_ids: list = None) -> list:
-550    '''
-551    Returns a list of the XML files describing the mappings with IDs
-552    contained in the `mapping_ids` list.\n
-553    `mapping_ids` must be a list of strings. If it is omitted, all mappings
-554    are returned. \n
-555    If one or more of the mappings IDs is not found, it is ignored.
-556    '''
-557    if mapping_ids is None:
-558        mapping_ids = [data["id"] for data in get_all_mappings(gw_session)]
-559
-560    mapping_xmls = []
-561    for mapping_id in mapping_ids:
-562        gw_session.add_headers({"Accept": "application/zip"})
-563        path = f'/configuration/mappings/{mapping_id}/export'
-564        res = get(gw_session, path, exp_code=[200, 404])
-565        if res.status_code == 200:
-566            with ZipFile(BytesIO(res.content)) as zip_file:
-567                with zip_file.open("alec_table.xml", "r") as mapping_xml:
-568                    mapping_xmls.append(mapping_xml)
-569        else:
-570            logging.info("Mapping with ID %s was not found on Airlock Host",
-571                         mapping_id)
-572
-573    gw_session.add_headers({"Accept": "application/json"})
-574    return mapping_xmls
+            
553def export_mappings(gw_session: GatewaySession,
+554                    mapping_ids: list = None) -> list:
+555    '''
+556    Returns a list of the XML files describing the mappings with IDs
+557    contained in the `mapping_ids` list.\n
+558    `mapping_ids` must be a list of strings. If it is omitted, all mappings
+559    are returned. \n
+560    If one or more of the mappings IDs is not found, it is ignored.
+561    '''
+562    if mapping_ids is None:
+563        mapping_ids = [data["id"] for data in get_all_mappings(gw_session)]
+564
+565    mapping_xmls = []
+566    for mapping_id in mapping_ids:
+567        gw_session.add_headers({"Accept": "application/zip"})
+568        path = f'/configuration/mappings/{mapping_id}/export'
+569        res = get(gw_session, path, exp_code=[200, 404])
+570        if res.status_code == 200:
+571            with ZipFile(BytesIO(res.content)) as zip_file:
+572                with zip_file.open("alec_table.xml", "r") as mapping_xml:
+573                    mapping_xmls.append(mapping_xml)
+574        else:
+575            logging.info("Mapping with ID %s was not found on Airlock Host",
+576                         mapping_id)
+577
+578    gw_session.add_headers({"Accept": "application/json"})
+579    return mapping_xmls
 
@@ -2690,15 +2697,15 @@
Inherited Members
-
577def delete_mapping_by_id(gw_session: GatewaySession, mapping_id: str) -> bool:
-578    '''
-579    Deletes the Mapping with the selected ID.\n
-580    Returns True if deletion was successful and False if no mapping with ID
-581    `mapping_id` was found..
-582    '''
-583    path = f"/configuration/mappings/{mapping_id}"
-584    res = delete(gw_session, path, exp_code=[204, 404])
-585    return res.status_code == 204
+            
582def delete_mapping_by_id(gw_session: GatewaySession, mapping_id: str) -> bool:
+583    '''
+584    Deletes the Mapping with the selected ID.\n
+585    Returns True if deletion was successful and False if no mapping with ID
+586    `mapping_id` was found..
+587    '''
+588    path = f"/configuration/mappings/{mapping_id}"
+589    res = delete(gw_session, path, exp_code=[204, 404])
+590    return res.status_code == 204
 
@@ -2721,13 +2728,13 @@
Inherited Members
-
588def get_templates(gw_session: GatewaySession) -> dict:
-589    '''
-590    Returns a dictionary object mapping every mapping template name to its ID.
-591    '''
-592    res = get(gw_session, '/configuration/templates/mappings', 200)
-593    data = res.json()['data']
-594    return {x['attributes']['name']: x['id'] for x in data}
+            
593def get_templates(gw_session: GatewaySession) -> dict:
+594    '''
+595    Returns a dictionary object mapping every mapping template name to its ID.
+596    '''
+597    res = get(gw_session, '/configuration/templates/mappings', 200)
+598    data = res.json()['data']
+599    return {x['attributes']['name']: x['id'] for x in data}
 
@@ -2747,23 +2754,23 @@
Inherited Members
-
597def update_mapping(gw_session: GatewaySession, mapping_id: str,
-598                   attributes: dict) -> bool:
-599    '''
-600    Updates the mapping with ID `mapping_id` with the given `attributes`,
-601    for example name or entry path.\n
-602    Returns True if update was successful and False if no mapping with ID
-603    `mapping_id` was found.
-604    '''
-605    data = {
-606        "data": {
-607            "type": 'mapping',
-608            "attributes": attributes
-609        }
-610    }
-611    path = f'/configuration/mappings/{mapping_id}'
-612    res = patch(gw_session, path, data, [200, 404])
-613    return res.status_code == 200
+            
602def update_mapping(gw_session: GatewaySession, mapping_id: str,
+603                   attributes: dict) -> bool:
+604    '''
+605    Updates the mapping with ID `mapping_id` with the given `attributes`,
+606    for example name or entry path.\n
+607    Returns True if update was successful and False if no mapping with ID
+608    `mapping_id` was found.
+609    '''
+610    data = {
+611        "data": {
+612            "type": 'mapping',
+613            "attributes": attributes
+614        }
+615    }
+616    path = f'/configuration/mappings/{mapping_id}'
+617    res = patch(gw_session, path, data, [200, 404])
+618    return res.status_code == 200
 
@@ -2787,32 +2794,32 @@
Inherited Members
-
616def add_mapping(gw_session: GatewaySession, name: str,
-617                template: str = 'New_Mapping', entry_path: str = '/') -> str:
-618    '''
-619    Adds a new mapping to the Airlock host, with the specified
-620    `name` and `entry_path`.\n Optionally, a template can
-621    be used for the new mapping.\n
-622    Returns the mapping ID of the new mapping.
-623    '''
-624    templates = get_templates(gw_session)
-625    data = {
-626        "data": {
-627            "type": "create-mapping-from-template",
-628            "attributes": {
-629                "id": templates[template]
-630            }
-631        }
-632    }
-633    path = '/configuration/mappings/create-from-template'
-634    res = post(gw_session, path, data, 201)
-635    mapping_id = res.json()['data']['id']
-636    attributes = {
-637        "name": name,
-638        "entryPath": {"value": entry_path}
-639    }
-640    update_mapping(gw_session, mapping_id, attributes)
-641    return mapping_id
+            
621def add_mapping(gw_session: GatewaySession, name: str,
+622                template: str = 'New_Mapping', entry_path: str = '/') -> str:
+623    '''
+624    Adds a new mapping to the Airlock host, with the specified
+625    `name` and `entry_path`.\n Optionally, a template can
+626    be used for the new mapping.\n
+627    Returns the mapping ID of the new mapping.
+628    '''
+629    templates = get_templates(gw_session)
+630    data = {
+631        "data": {
+632            "type": "create-mapping-from-template",
+633            "attributes": {
+634                "id": templates[template]
+635            }
+636        }
+637    }
+638    path = '/configuration/mappings/create-from-template'
+639    res = post(gw_session, path, data, 201)
+640    mapping_id = res.json()['data']['id']
+641    attributes = {
+642        "name": name,
+643        "entryPath": {"value": entry_path}
+644    }
+645    update_mapping(gw_session, mapping_id, attributes)
+646    return mapping_id
 
@@ -2837,32 +2844,32 @@
Inherited Members
-
644def set_source_mapping(gw_session: GatewaySession, mapping_id: str,
-645                       src_mapping_id: str) -> bool:
-646    '''
-647    Sets the source mapping of mapping with ID `mapping_id`
-648    to the mapping with ID `src_mapping_id`. \n
-649    Returns True if the operation was successful and False if
-650    no mapping with ID `mapping_id` was found.
-651    '''
-652    data = {
-653        "data": {
-654            "type": 'mapping',
-655            "id": src_mapping_id
-656        }
-657    }
-658    path = f'/configuration/mappings/{mapping_id}/relationships/template'
-659    res = patch(gw_session, path, data, [204, 404])
-660    if res.status_code == 404:
-661        return False
-662
-663    lock_cfg = {
-664        "enabled": True,
-665        "labels": True,
-666        "entryPath": {"settings": True}
-667    }
-668
-669    return update_mapping(gw_session, mapping_id, {"locking": lock_cfg})
+            
649def set_source_mapping(gw_session: GatewaySession, mapping_id: str,
+650                       src_mapping_id: str) -> bool:
+651    '''
+652    Sets the source mapping of mapping with ID `mapping_id`
+653    to the mapping with ID `src_mapping_id`. \n
+654    Returns True if the operation was successful and False if
+655    no mapping with ID `mapping_id` was found.
+656    '''
+657    data = {
+658        "data": {
+659            "type": 'mapping',
+660            "id": src_mapping_id
+661        }
+662    }
+663    path = f'/configuration/mappings/{mapping_id}/relationships/template'
+664    res = patch(gw_session, path, data, [204, 404])
+665    if res.status_code == 404:
+666        return False
+667
+668    lock_cfg = {
+669        "enabled": True,
+670        "labels": True,
+671        "entryPath": {"settings": True}
+672    }
+673
+674    return update_mapping(gw_session, mapping_id, {"locking": lock_cfg})
 
@@ -2886,17 +2893,17 @@
Inherited Members
-
672def pull_from_source_mapping(gw_session: GatewaySession,
-673                             mapping_id: str) -> bool:
-674    '''
-675    Performs a pull from the source mapping on the mapping with
-676    ID `mapping_id`.\n
-677    Returns True if the pull was succesfull and False if no mapping with ID
-678    `mapping_id` was found.
-679    '''
-680    path = f'/configuration/mappings/{mapping_id}/pull-from-source-mapping'
-681    res = post(gw_session, path, exp_code=[200, 404])
-682    return res.status_code == 200
+            
677def pull_from_source_mapping(gw_session: GatewaySession,
+678                             mapping_id: str) -> bool:
+679    '''
+680    Performs a pull from the source mapping on the mapping with
+681    ID `mapping_id`.\n
+682    Returns True if the pull was succesfull and False if no mapping with ID
+683    `mapping_id` was found.
+684    '''
+685    path = f'/configuration/mappings/{mapping_id}/pull-from-source-mapping'
+686    res = post(gw_session, path, exp_code=[200, 404])
+687    return res.status_code == 200
 
@@ -2920,16 +2927,16 @@
Inherited Members
-
685def gen_backend_host(protocol: str, name: str, port: int) -> dict:
-686    '''
-687    Returns a dictionary object representing a new Backend Host.
-688    '''
-689    host_data = {
-690        "protocol": protocol,
-691        "hostName": name,
-692        "port": port
-693    }
-694    return host_data
+            
690def gen_backend_host(protocol: str, name: str, port: int) -> dict:
+691    '''
+692    Returns a dictionary object representing a new Backend Host.
+693    '''
+694    host_data = {
+695        "protocol": protocol,
+696        "hostName": name,
+697        "port": port
+698    }
+699    return host_data
 
@@ -2949,24 +2956,24 @@
Inherited Members
-
697def add_backend_group(gw_session: GatewaySession, beg_name: str,
-698                      be_hosts: list) -> str:
-699    '''
-700    Adds a new Backend Group with the name `beg_name` and the hosts
-701    contained in `be_hosts` to the Airlock Host.\n
-702    Returns the ID of the newly added Backend Group.
-703    '''
-704    beg_data = {
-705        "data": {
-706            "type": "back-end-group",
-707            "attributes": {
-708                "name": beg_name,
-709                "backendHosts": be_hosts
-710            }
-711        }
-712    }
-713    res = post(gw_session, "/configuration/back-end-groups", beg_data, 201)
-714    return res.json()['data']['id']
+            
702def add_backend_group(gw_session: GatewaySession, beg_name: str,
+703                      be_hosts: list) -> str:
+704    '''
+705    Adds a new Backend Group with the name `beg_name` and the hosts
+706    contained in `be_hosts` to the Airlock Host.\n
+707    Returns the ID of the newly added Backend Group.
+708    '''
+709    beg_data = {
+710        "data": {
+711            "type": "back-end-group",
+712            "attributes": {
+713                "name": beg_name,
+714                "backendHosts": be_hosts
+715            }
+716        }
+717    }
+718    res = post(gw_session, "/configuration/back-end-groups", beg_data, 201)
+719    return res.json()['data']['id']
 
@@ -2989,12 +2996,12 @@
Inherited Members
-
717def get_backend_groups(gw_session: GatewaySession) -> list:
-718    '''
-719    Returns a list containing all backend groups on the Airlock Host.
-720    '''
-721    res = get(gw_session, '/configuration/back-end-groups', exp_code=200)
-722    return res.json().get('data')
+            
722def get_backend_groups(gw_session: GatewaySession) -> list:
+723    '''
+724    Returns a list containing all backend groups on the Airlock Host.
+725    '''
+726    res = get(gw_session, '/configuration/back-end-groups', exp_code=200)
+727    return res.json().get('data')
 
@@ -3014,16 +3021,16 @@
Inherited Members
-
725def get_backend_group_by_id(gw_session: GatewaySession, beg_id: str) -> dict:
-726    '''
-727    Returns a dictionary object describing the backend group with ID
-728    `beg_id`, or None if no such group was found.
-729    '''
-730    path = f'/configuration/back-end-groups/{beg_id}'
-731    res = get(gw_session, path, exp_code=[200, 404])
-732    if res.status_code == 200:
-733        return res.json().get('data')
-734    return None
+            
730def get_backend_group_by_id(gw_session: GatewaySession, beg_id: str) -> dict:
+731    '''
+732    Returns a dictionary object describing the backend group with ID
+733    `beg_id`, or None if no such group was found.
+734    '''
+735    path = f'/configuration/back-end-groups/{beg_id}'
+736    res = get(gw_session, path, exp_code=[200, 404])
+737    if res.status_code == 200:
+738        return res.json().get('data')
+739    return None
 
@@ -3044,24 +3051,24 @@
Inherited Members
-
737def update_backend_group_by_id(gw_session: GatewaySession, beg_id: str,
-738                               attributes: dict) -> bool:
-739    '''
-740    Updates the Backend Group with ID `beg_id` with the given attributes,
-741    for example hostname or port. \n
-742    Returns True if the update was succesfull and False if no Backend Group
-743    with ID `beg_id` was found.
-744    '''
-745    beg_data = {
-746        "data": {
-747            "type": "back-end-group",
-748            "id": beg_id,
-749            "attributes": attributes
-750        }
-751    }
-752    path = f"/configuration/back-end-groups/{beg_id}"
-753    res = patch(gw_session, path, beg_data, [200, 404])
-754    return res.status_code == 200
+            
742def update_backend_group_by_id(gw_session: GatewaySession, beg_id: str,
+743                               attributes: dict) -> bool:
+744    '''
+745    Updates the Backend Group with ID `beg_id` with the given attributes,
+746    for example hostname or port. \n
+747    Returns True if the update was succesfull and False if no Backend Group
+748    with ID `beg_id` was found.
+749    '''
+750    beg_data = {
+751        "data": {
+752            "type": "back-end-group",
+753            "id": beg_id,
+754            "attributes": attributes
+755        }
+756    }
+757    path = f"/configuration/back-end-groups/{beg_id}"
+758    res = patch(gw_session, path, beg_data, [200, 404])
+759    return res.status_code == 200
 
@@ -3085,16 +3092,16 @@
Inherited Members
-
757def delete_backend_group_by_id(gw_session: GatewaySession,
-758                               beg_id: str) -> bool:
-759    '''
-760    Deletes the Backend Group with ID `beg_id` from the Airlock Host.\n
-761    Returns True if deletion was successful and False if no Backend
-762    Group with ID `beg_id` was found.
-763    '''
-764    path = f"/configuration/back-end-groups/{beg_id}"
-765    res = delete(gw_session, path, exp_code=[204, 404])
-766    return res.status_code == 204
+            
762def delete_backend_group_by_id(gw_session: GatewaySession,
+763                               beg_id: str) -> bool:
+764    '''
+765    Deletes the Backend Group with ID `beg_id` from the Airlock Host.\n
+766    Returns True if deletion was successful and False if no Backend
+767    Group with ID `beg_id` was found.
+768    '''
+769    path = f"/configuration/back-end-groups/{beg_id}"
+770    res = delete(gw_session, path, exp_code=[204, 404])
+771    return res.status_code == 204
 
@@ -3117,22 +3124,22 @@
Inherited Members
-
769def connect_virtual_host_to_map(gw_session: GatewaySession, vh_id: str,
-770                                mapping_id: str) -> bool:
-771    '''
-772    Connects Virtual Host with id `vh_id` to the Mapping with ID
-773    `mapping_id`.\n Returns True if the operation was successful
-774    and False if one of the provided IDs was not found.
-775    '''
-776    data = {
-777        "data": [{
-778            "type": 'mapping',
-779            "id": mapping_id
-780        }]
-781    }
-782    path = f'/configuration/virtual-hosts/{vh_id}/relationships/mappings'
-783    res = patch(gw_session, path, data, [204, 404])
-784    return res.status_code == 204
+            
774def connect_virtual_host_to_map(gw_session: GatewaySession, vh_id: str,
+775                                mapping_id: str) -> bool:
+776    '''
+777    Connects Virtual Host with id `vh_id` to the Mapping with ID
+778    `mapping_id`.\n Returns True if the operation was successful
+779    and False if one of the provided IDs was not found.
+780    '''
+781    data = {
+782        "data": [{
+783            "type": 'mapping',
+784            "id": mapping_id
+785        }]
+786    }
+787    path = f'/configuration/virtual-hosts/{vh_id}/relationships/mappings'
+788    res = patch(gw_session, path, data, [204, 404])
+789    return res.status_code == 204
 
@@ -3155,27 +3162,27 @@
Inherited Members
-
787def connect_map_to_beg(gw_session: GatewaySession, mapping_id: str,
-788                       beg_ids: list) -> bool:
-789    '''
-790    Connects Mapping with ID `mapping_id` to the Backend Groups
-791    with IDs in `beg_ids`.\n
-792    Returns True if the operation was successful and False if one of
-793    the provided IDs was not found.
-794    '''
-795    data = {
-796        "data": []
-797    }
-798    for beg_id in beg_ids:
-799        group = {
-800            "type": 'back-end-group',
-801            "id": beg_id
-802        }
-803        data['data'].append(group)
-804    map_id = mapping_id
-805    path = f'/configuration/mappings/{map_id}/relationships/back-end-groups'
-806    res = patch(gw_session, path, data, [204, 404])
-807    return res.status_code == 204
+            
792def connect_map_to_beg(gw_session: GatewaySession, mapping_id: str,
+793                       beg_ids: list) -> bool:
+794    '''
+795    Connects Mapping with ID `mapping_id` to the Backend Groups
+796    with IDs in `beg_ids`.\n
+797    Returns True if the operation was successful and False if one of
+798    the provided IDs was not found.
+799    '''
+800    data = {
+801        "data": []
+802    }
+803    for beg_id in beg_ids:
+804        group = {
+805            "type": 'back-end-group',
+806            "id": beg_id
+807        }
+808        data['data'].append(group)
+809    map_id = mapping_id
+810    path = f'/configuration/mappings/{map_id}/relationships/back-end-groups'
+811    res = patch(gw_session, path, data, [204, 404])
+812    return res.status_code == 204
 
@@ -3199,22 +3206,22 @@
Inherited Members
-
810def disconnect_virtual_host_to_map(gw_session: GatewaySession, vh_id: str,
-811                                   mapping_id: str) -> bool:
-812    '''
-813    Disconnects Virtual Host with id `vh_id` to the Mapping with
-814    ID `mapping_id`.\n Returns True if the operation was successful
-815    and False if one of the provided IDs was not found.
-816    '''
-817    data = {
-818        "data": [{
-819            "type": 'mapping',
-820            "id": mapping_id
-821        }]
-822    }
-823    path = f'/configuration/virtual-hosts/{vh_id}/relationships/mappings'
-824    res = delete(gw_session, path, data, [204, 404])
-825    return res.status_code == 204
+            
815def disconnect_virtual_host_to_map(gw_session: GatewaySession, vh_id: str,
+816                                   mapping_id: str) -> bool:
+817    '''
+818    Disconnects Virtual Host with id `vh_id` to the Mapping with
+819    ID `mapping_id`.\n Returns True if the operation was successful
+820    and False if one of the provided IDs was not found.
+821    '''
+822    data = {
+823        "data": [{
+824            "type": 'mapping',
+825            "id": mapping_id
+826        }]
+827    }
+828    path = f'/configuration/virtual-hosts/{vh_id}/relationships/mappings'
+829    res = delete(gw_session, path, data, [204, 404])
+830    return res.status_code == 204
 
@@ -3237,26 +3244,26 @@
Inherited Members
-
828def disconnect_map_to_beg(gw_session: GatewaySession, mapping_id: str,
-829                          beg_ids: list) -> bool:
-830    '''
-831    Disconnects Mapping with ID `mapping_id` from the Backend Groups
-832    with IDs in `beg_ids`.\n Returns True if the operation was successful
-833    and False if one of the provided IDs was not found.
-834    '''
-835    data = {
-836        "data": []
-837    }
-838    for beg_id in beg_ids:
-839        group = {
-840            "type": 'back-end-group',
-841            "id": beg_id
-842        }
-843        data['data'].append(group)
-844    map_id = mapping_id
-845    path = f'/configuration/mappings/{map_id}/relationships/back-end-groups'
-846    res = delete(gw_session, path, data, [204, 404])
-847    return res.status_code == 204
+            
833def disconnect_map_to_beg(gw_session: GatewaySession, mapping_id: str,
+834                          beg_ids: list) -> bool:
+835    '''
+836    Disconnects Mapping with ID `mapping_id` from the Backend Groups
+837    with IDs in `beg_ids`.\n Returns True if the operation was successful
+838    and False if one of the provided IDs was not found.
+839    '''
+840    data = {
+841        "data": []
+842    }
+843    for beg_id in beg_ids:
+844        group = {
+845            "type": 'back-end-group',
+846            "id": beg_id
+847        }
+848        data['data'].append(group)
+849    map_id = mapping_id
+850    path = f'/configuration/mappings/{map_id}/relationships/back-end-groups'
+851    res = delete(gw_session, path, data, [204, 404])
+852    return res.status_code == 204
 
@@ -3279,16 +3286,16 @@
Inherited Members
-
850def get_mapping_deny_rule_group(gw_session: GatewaySession, mapping_id: str,
-851                                denyrule_group_shortname: str) -> dict:
-852    '''
-853    Returns a dictionary object describing the deny rule group in the
-854    specified Mapping, or None if the mapping or shortname specified were not
-855    found.
-856    '''
-857    path = f'/configuration/mappings/{mapping_id}/deny-rule-groups/{denyrule_group_shortname}'
-858    res = get(gw_session, path, exp_code=[200, 404])
-859    return res.json().get('data')
+            
855def get_mapping_deny_rule_group(gw_session: GatewaySession, mapping_id: str,
+856                                denyrule_group_shortname: str) -> dict:
+857    '''
+858    Returns a dictionary object describing the deny rule group in the
+859    specified Mapping, or None if the mapping or shortname specified were not
+860    found.
+861    '''
+862    path = f'/configuration/mappings/{mapping_id}/deny-rule-groups/{denyrule_group_shortname}'
+863    res = get(gw_session, path, exp_code=[200, 404])
+864    return res.json().get('data')
 
@@ -3310,23 +3317,23 @@
Inherited Members
-
862def update_mapping_deny_rule_group(gw_session: GatewaySession, mapping_id: str,
-863                                   denyrule_group_shortname: str,
-864                                   attributes: dict) -> bool:
-865    '''
-866    Updates the settings for a deny rule group within a specified mapping.
-867    Returns True if successful, and False if if the mapping or shortname
-868    specified were not found.
-869    '''
-870    path = f'/configuration/mappings/{mapping_id}/deny-rule-groups/{denyrule_group_shortname}'
-871    data = {
-872        "data": {
-873            "type": "mapping-deny-rule-group",
-874            "attributes": attributes
-875        }
-876    }
-877    res = patch(gw_session, path, data, exp_code=[200, 404])
-878    return res.status_code == 200
+            
867def update_mapping_deny_rule_group(gw_session: GatewaySession, mapping_id: str,
+868                                   denyrule_group_shortname: str,
+869                                   attributes: dict) -> bool:
+870    '''
+871    Updates the settings for a deny rule group within a specified mapping.
+872    Returns True if successful, and False if if the mapping or shortname
+873    specified were not found.
+874    '''
+875    path = f'/configuration/mappings/{mapping_id}/deny-rule-groups/{denyrule_group_shortname}'
+876    data = {
+877        "data": {
+878            "type": "mapping-deny-rule-group",
+879            "attributes": attributes
+880        }
+881    }
+882    res = patch(gw_session, path, data, exp_code=[200, 404])
+883    return res.status_code == 200
 
@@ -3348,15 +3355,15 @@
Inherited Members
-
881def get_mapping_deny_rule(gw_session: GatewaySession, mapping_id: str,
-882                          denyrule_shortname: str) -> dict:
-883    '''
-884    Returns a dictionary object describing the deny rule in the specified
-885    Mapping, or None if the mapping or shortname specified were not found.
-886    '''
-887    path = f'/configuration/mappings/{mapping_id}/deny-rules/{denyrule_shortname}'
-888    res = get(gw_session, path, exp_code=[200, 404])
-889    return res.json().get("data")
+            
886def get_mapping_deny_rule(gw_session: GatewaySession, mapping_id: str,
+887                          denyrule_shortname: str) -> dict:
+888    '''
+889    Returns a dictionary object describing the deny rule in the specified
+890    Mapping, or None if the mapping or shortname specified were not found.
+891    '''
+892    path = f'/configuration/mappings/{mapping_id}/deny-rules/{denyrule_shortname}'
+893    res = get(gw_session, path, exp_code=[200, 404])
+894    return res.json().get("data")
 
@@ -3377,22 +3384,22 @@
Inherited Members
-
892def update_mapping_deny_rule(gw_session: GatewaySession, mapping_id: str,
-893                             denyrule_shortname: str, attributes: dict) -> bool:
-894    '''
-895    Updates the settings for a deny rule within a specified mapping. Returns
-896    True if successful, and False if if the mapping or shortname specified
-897    were not found.
-898    '''
-899    path = f'/configuration/mappings/{mapping_id}/deny-rules/{denyrule_shortname}'
-900    data = {
-901        "data": {
-902            "type": "mapping-deny-rule",
-903            "attributes": attributes
-904        }
-905    }
-906    res = patch(gw_session, path, data, exp_code=[200, 404])
-907    return res.status_code == 200
+            
897def update_mapping_deny_rule(gw_session: GatewaySession, mapping_id: str,
+898                             denyrule_shortname: str, attributes: dict) -> bool:
+899    '''
+900    Updates the settings for a deny rule within a specified mapping. Returns
+901    True if successful, and False if if the mapping or shortname specified
+902    were not found.
+903    '''
+904    path = f'/configuration/mappings/{mapping_id}/deny-rules/{denyrule_shortname}'
+905    data = {
+906        "data": {
+907            "type": "mapping-deny-rule",
+908            "attributes": attributes
+909        }
+910    }
+911    res = patch(gw_session, path, data, exp_code=[200, 404])
+912    return res.status_code == 200
 
@@ -3414,14 +3421,14 @@
Inherited Members
-
910def get_deny_rule_groups(gw_session: GatewaySession) -> dict:
-911    '''
-912    Returns a list of all deny rule groups on the Airlock Host.
-913    '''
-914
-915    path = '/configuration/deny-rule-groups'
-916    res = get(gw_session, path, exp_code=200)
-917    return res.json().get("data")
+            
915def get_deny_rule_groups(gw_session: GatewaySession) -> dict:
+916    '''
+917    Returns a list of all deny rule groups on the Airlock Host.
+918    '''
+919
+920    path = '/configuration/deny-rule-groups'
+921    res = get(gw_session, path, exp_code=200)
+922    return res.json().get("data")
 
@@ -3441,15 +3448,15 @@
Inherited Members
-
920def get_deny_rule_group(gw_session: GatewaySession, short_name: str) -> dict:
-921    '''
-922    Returns a dictionary object describing the specified deny rule group,
-923    or None if it does not exist.
-924    '''
-925
-926    path = f'/configuration/deny-rule-groups/{short_name}'
-927    res = get(gw_session, path, exp_code=[200, 404])
-928    return res.json().get("data")
+            
925def get_deny_rule_group(gw_session: GatewaySession, short_name: str) -> dict:
+926    '''
+927    Returns a dictionary object describing the specified deny rule group,
+928    or None if it does not exist.
+929    '''
+930
+931    path = f'/configuration/deny-rule-groups/{short_name}'
+932    res = get(gw_session, path, exp_code=[200, 404])
+933    return res.json().get("data")
 
@@ -3470,14 +3477,14 @@
Inherited Members
-
931def get_deny_rules(gw_session: GatewaySession) -> list:
-932    '''
-933    Returns a list of all deny-rules on the Airlock Host.
-934    '''
-935
-936    path = '/configuration/deny-rules'
-937    res = get(gw_session, path, exp_code=200)
-938    return res.json().get("data")
+            
936def get_deny_rules(gw_session: GatewaySession) -> list:
+937    '''
+938    Returns a list of all deny-rules on the Airlock Host.
+939    '''
+940
+941    path = '/configuration/deny-rules'
+942    res = get(gw_session, path, exp_code=200)
+943    return res.json().get("data")
 
@@ -3497,14 +3504,14 @@
Inherited Members
-
941def get_deny_rule(gw_session: GatewaySession, short_name: str) -> dict:
-942    '''
-943    Returns a dictionary object describing the specified deny-rule, or None
-944    if it does not exist.
-945    '''
-946    path = f'/configuration/deny-rules/{short_name}'
-947    res = get(gw_session, path, exp_code=[200, 404])
-948    return res.json().get("data")
+            
946def get_deny_rule(gw_session: GatewaySession, short_name: str) -> dict:
+947    '''
+948    Returns a dictionary object describing the specified deny-rule, or None
+949    if it does not exist.
+950    '''
+951    path = f'/configuration/deny-rules/{short_name}'
+952    res = get(gw_session, path, exp_code=[200, 404])
+953    return res.json().get("data")
 
@@ -3525,17 +3532,17 @@
Inherited Members
-
951def load_config(gw_session: GatewaySession, config_id: int,
-952                host_name: str = None) -> bool:
-953    '''
-954    Loads the configuration with ID `config_id` on the Airlock Host.\n
-955    Returns True if the operation was successful and False if no configuration
-956    with ID `config_id` was found.
-957    '''
-958    data = {"hostname": host_name or gw_session.host_name}
-959    path = f"/configuration/configurations/{config_id}/load"
-960    res = post(gw_session, path, data, [204, 404])
-961    return res.status_code == 204
+            
956def load_config(gw_session: GatewaySession, config_id: int,
+957                host_name: str = None) -> bool:
+958    '''
+959    Loads the configuration with ID `config_id` on the Airlock Host.\n
+960    Returns True if the operation was successful and False if no configuration
+961    with ID `config_id` was found.
+962    '''
+963    data = {"hostname": host_name or gw_session.host_name}
+964    path = f"/configuration/configurations/{config_id}/load"
+965    res = post(gw_session, path, data, [204, 404])
+966    return res.status_code == 204
 
@@ -3558,13 +3565,13 @@
Inherited Members
-
964def load_empty_config(gw_session: GatewaySession, host_name: str = None):
-965    '''
-966    Loads the empty configuration on the Airlock Host.
-967    '''
-968    data = {"hostname": host_name or gw_session.host_name}
-969    path = "/configuration/configurations/load-empty-config"
-970    post(gw_session, path, data, 204)
+            
969def load_empty_config(gw_session: GatewaySession, host_name: str = None):
+970    '''
+971    Loads the empty configuration on the Airlock Host.
+972    '''
+973    data = {"hostname": host_name or gw_session.host_name}
+974    path = "/configuration/configurations/load-empty-config"
+975    post(gw_session, path, data, 204)
 
@@ -3584,11 +3591,11 @@
Inherited Members
-
973def load_active_config(gw_session: GatewaySession):
-974    '''
-975    Loads the currently active configuration on the Airlock Host.
-976    '''
-977    post(gw_session, '/configuration/configurations/load-active', None, 204)
+            
978def load_active_config(gw_session: GatewaySession):
+979    '''
+980    Loads the currently active configuration on the Airlock Host.
+981    '''
+982    post(gw_session, '/configuration/configurations/load-active', None, 204)
 
@@ -3608,16 +3615,16 @@
Inherited Members
-
980def load_initial_config(gw_session: GatewaySession):
-981    '''
-982    Loads the initial configuration on the Airlock Host.
-983    '''
-984    res = get(gw_session, '/configuration/configurations', exp_code=200)
-985    data = res.json()['data']
-986    init_cfg_id = [x['id'] for x in data
-987                   if x['attributes']['configType'] == 'INITIAL'][0]
-988    path = f'/configuration/configurations/{init_cfg_id}/load'
-989    post(gw_session, path, None, 204)
+            
985def load_initial_config(gw_session: GatewaySession):
+986    '''
+987    Loads the initial configuration on the Airlock Host.
+988    '''
+989    res = get(gw_session, '/configuration/configurations', exp_code=200)
+990    data = res.json()['data']
+991    init_cfg_id = [x['id'] for x in data
+992                   if x['attributes']['configType'] == 'INITIAL'][0]
+993    path = f'/configuration/configurations/{init_cfg_id}/load'
+994    post(gw_session, path, None, 204)
 
@@ -3637,16 +3644,16 @@
Inherited Members
-
1007def import_config(gw_session: GatewaySession, cfg_zip: str):
-1008    '''
-1009    Imports the configuration zip file located at
-1010    `cfg_zip` to the Airlock Host.
-1011    '''
-1012    with open(cfg_zip, 'rb') as file:
-1013        cfg_host_name = _get_hostname_from_config_zip(cfg_zip)
-1014        load_empty_config(gw_session, cfg_host_name)
-1015        path = "/configuration/configurations/import/"
-1016        req_raw(gw_session, "PUT", path, "application/zip", file, 200)
+            
1012def import_config(gw_session: GatewaySession, cfg_zip: str):
+1013    '''
+1014    Imports the configuration zip file located at
+1015    `cfg_zip` to the Airlock Host.
+1016    '''
+1017    with open(cfg_zip, 'rb') as file:
+1018        cfg_host_name = _get_hostname_from_config_zip(cfg_zip)
+1019        load_empty_config(gw_session, cfg_host_name)
+1020        path = "/configuration/configurations/import/"
+1021        req_raw(gw_session, "PUT", path, "application/zip", file, 200)
 
@@ -3667,14 +3674,14 @@
Inherited Members
-
1029def export_current_config_file(gw_session: GatewaySession, cfg_zip: str):
-1030    '''
-1031    Exports the currently active configuration to a
-1032    zip file located at `cfg_zip`.
-1033    '''
-1034    data = _export_current_config_data(gw_session)
-1035    with open(cfg_zip, 'wb') as file:
-1036        file.write(data)
+            
1034def export_current_config_file(gw_session: GatewaySession, cfg_zip: str):
+1035    '''
+1036    Exports the currently active configuration to a
+1037    zip file located at `cfg_zip`.
+1038    '''
+1039    data = _export_current_config_data(gw_session)
+1040    with open(cfg_zip, 'wb') as file:
+1041        file.write(data)
 
@@ -3695,13 +3702,13 @@
Inherited Members
-
1039def get_error_page_settings(gw_session: GatewaySession) -> dict:
-1040    '''
-1041    Returns a dictionary object describing the current error page settings.
-1042    '''
-1043    path = '/configuration/error-pages'
-1044    res = get(gw_session, path, exp_code=200)
-1045    return res.json().get('data')
+            
1044def get_error_page_settings(gw_session: GatewaySession) -> dict:
+1045    '''
+1046    Returns a dictionary object describing the current error page settings.
+1047    '''
+1048    path = '/configuration/error-pages'
+1049    res = get(gw_session, path, exp_code=200)
+1050    return res.json().get('data')
 
@@ -3721,18 +3728,18 @@
Inherited Members
-
1048def set_error_page_settings(gw_session: GatewaySession, attributes: dict):
-1049    '''
-1050    Updates the error page settings with the given attributes.
-1051    '''
-1052    path = '/configuration/error-pages'
-1053    data = {
-1054        "data": {
-1055            "type": "error-pages",
-1056            "attributes": attributes
-1057        }
-1058    }
-1059    patch(gw_session, path, data, exp_code=200)
+            
1053def set_error_page_settings(gw_session: GatewaySession, attributes: dict):
+1054    '''
+1055    Updates the error page settings with the given attributes.
+1056    '''
+1057    path = '/configuration/error-pages'
+1058    data = {
+1059        "data": {
+1060            "type": "error-pages",
+1061            "attributes": attributes
+1062        }
+1063    }
+1064    patch(gw_session, path, data, exp_code=200)
 
@@ -3752,15 +3759,15 @@
Inherited Members
-
1062def get_error_pages(gw_session: GatewaySession) -> Union[bytes, None]:
-1063    '''
-1064    Returns a zip file containing the error pages
-1065    '''
-1066    path = '/configuration/error-pages/content'
-1067    res = get(gw_session, path, exp_code=[200, 404])
-1068    if res.status_code == 404:
-1069        return None
-1070    return res.content
+            
1067def get_error_pages(gw_session: GatewaySession) -> Union[bytes, None]:
+1068    '''
+1069    Returns a zip file containing the error pages
+1070    '''
+1071    path = '/configuration/error-pages/content'
+1072    res = get(gw_session, path, exp_code=[200, 404])
+1073    if res.status_code == 404:
+1074        return None
+1075    return res.content
 
@@ -3780,13 +3787,13 @@
Inherited Members
-
1073def set_error_pages(gw_session: GatewaySession, error_page_zip: str):
-1074    '''
-1075    Imports the error page zip-file located at `error_page_zip`.
-1076    '''
-1077    with open(error_page_zip, 'rb') as file:
-1078        path = "/configuration/error-pages/content"
-1079        req_raw(gw_session, "PUT", path, "application/zip", file, 200)
+            
1078def set_error_pages(gw_session: GatewaySession, error_page_zip: str):
+1079    '''
+1080    Imports the error page zip-file located at `error_page_zip`.
+1081    '''
+1082    with open(error_page_zip, 'rb') as file:
+1083        path = "/configuration/error-pages/content"
+1084        req_raw(gw_session, "PUT", path, "application/zip", file, 200)
 
@@ -3806,12 +3813,12 @@
Inherited Members
-
1082def delete_error_pages(gw_session: GatewaySession):
-1083    '''
-1084    Remove the custom error pages.
-1085    '''
-1086    path = '/configuration/error-pages/content'
-1087    delete(gw_session, path, exp_code=200)
+            
1087def delete_error_pages(gw_session: GatewaySession):
+1088    '''
+1089    Remove the custom error pages.
+1090    '''
+1091    path = '/configuration/error-pages/content'
+1092    delete(gw_session, path, exp_code=200)
 
@@ -3831,13 +3838,13 @@
Inherited Members
-
1090def get_default_error_pages(gw_session: GatewaySession) -> bytes:
-1091    '''
-1092    Returns a zip file containing the default error pages.
-1093    '''
-1094    path = '/configuration/error-pages/content/default'
-1095    res = get(gw_session, path, exp_code=200)
-1096    return res.content
+            
1095def get_default_error_pages(gw_session: GatewaySession) -> bytes:
+1096    '''
+1097    Returns a zip file containing the default error pages.
+1098    '''
+1099    path = '/configuration/error-pages/content/default'
+1100    res = get(gw_session, path, exp_code=200)
+1101    return res.content
 
@@ -3857,13 +3864,13 @@
Inherited Members
-
1099def get_expert_settings(gw_session: GatewaySession) -> dict:
-1100    '''
-1101    Returns a dict containing the global expert settings for the Gateway as well as for Apache
-1102    '''
-1103    path = '/configuration/expert-settings'
-1104    res = get(gw_session, path, exp_code=200)
-1105    return res.json().get('data')
+            
1104def get_expert_settings(gw_session: GatewaySession) -> dict:
+1105    '''
+1106    Returns a dict containing the global expert settings for the Gateway as well as for Apache
+1107    '''
+1108    path = '/configuration/expert-settings'
+1109    res = get(gw_session, path, exp_code=200)
+1110    return res.json().get('data')
 
@@ -3883,18 +3890,18 @@
Inherited Members
-
1108def set_expert_settings(gw_session: GatewaySession, attributes: dict) -> None:
-1109    '''
-1110    Updates the global expert settings with the given attributes.
-1111    '''
-1112    path = '/configuration/expert-settings'
-1113    data = {
-1114        "data": {
-1115            "type": 'expert-settings',
-1116            "attributes": attributes
-1117        }
-1118    }
-1119    patch(gw_session, path, data, exp_code=200)
+            
1113def set_expert_settings(gw_session: GatewaySession, attributes: dict) -> None:
+1114    '''
+1115    Updates the global expert settings with the given attributes.
+1116    '''
+1117    path = '/configuration/expert-settings'
+1118    data = {
+1119        "data": {
+1120            "type": 'expert-settings',
+1121            "attributes": attributes
+1122        }
+1123    }
+1124    patch(gw_session, path, data, exp_code=200)