insightconnect-plugin-runtime 5.4.9__tar.gz → 5.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {insightconnect_plugin_runtime-5.4.9/insightconnect_plugin_runtime.egg-info → insightconnect_plugin_runtime-5.5.0}/PKG-INFO +3 -2
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/README.md +1 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/api/endpoints.py +33 -9
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/clients/aws_client.py +41 -36
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/exceptions.py +64 -8
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/helper.py +259 -1
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/plugin.py +25 -5
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/server.py +37 -11
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/util.py +3 -1
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0/insightconnect_plugin_runtime.egg-info}/PKG-INFO +3 -2
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime.egg-info/requires.txt +1 -1
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/setup.py +2 -2
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/unit/test_helpers.py +215 -0
- insightconnect_plugin_runtime-5.5.0/tests/unit/utils.py +78 -0
- insightconnect_plugin_runtime-5.4.9/tests/unit/utils.py +0 -20
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/MANIFEST.in +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect-plugin-swagger.json +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/action.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/api/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/api/schemas.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/cli.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/clients/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/clients/oauth.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/connection.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/data/input_message_schema.json +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/data/output_message_schema.json +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/dispatcher.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/metrics.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/schema.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/step.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/task.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/trigger.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime/variables.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime.egg-info/SOURCES.txt +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime.egg-info/dependency_links.txt +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/insightconnect_plugin_runtime.egg-info/top_level.txt +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/setup.cfg +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/hello/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/hello/action.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/hello/schema.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/return_bad_json/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/return_bad_json/action.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/return_bad_json/schema.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/throw_exception/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/throw_exception/action.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/throw_exception/schema.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/connection/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/connection/connection.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/connection/schema.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/tasks/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/tasks/monitor_events/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/tasks/monitor_events/schema.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/tasks/monitor_events/task.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/hello_trigger/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/hello_trigger/schema.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/hello_trigger/trigger.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/return_bad_json_trigger/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/return_bad_json_trigger/schema.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/return_bad_json_trigger/trigger.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/throw_exception_trigger/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/throw_exception_trigger/schema.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/throw_exception_trigger/trigger.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/komand_hello_world/util/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/hello_world/setup.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/tests/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/tests/conftest.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/tests/test_cli.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/tests/test_hello_world.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/plugin/hello_world/tests/test_server.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/unit/__init__.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/unit/test_action.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/unit/test_api.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/unit/test_aws_action.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/unit/test_custom_encoder.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/unit/test_endpoints.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/unit/test_exceptions.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/unit/test_metrics.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/unit/test_oauth.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/unit/test_plugin.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/unit/test_schema.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/unit/test_server_cloud_plugins.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/unit/test_server_spec.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/unit/test_trigger.py +0 -0
- {insightconnect_plugin_runtime-5.4.9 → insightconnect_plugin_runtime-5.5.0}/tests/unit/test_variables.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: insightconnect-plugin-runtime
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.5.0
|
|
4
4
|
Summary: InsightConnect Plugin Runtime
|
|
5
5
|
Home-page: https://github.com/rapid7/komand-plugin-sdk-python
|
|
6
6
|
Author: Rapid7 Integrations Alliance
|
|
@@ -12,7 +12,7 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
12
12
|
Classifier: Natural Language :: English
|
|
13
13
|
Classifier: Topic :: Software Development :: Build Tools
|
|
14
14
|
Description-Content-Type: text/markdown
|
|
15
|
-
Requires-Dist: requests==2.
|
|
15
|
+
Requires-Dist: requests==2.32.0
|
|
16
16
|
Requires-Dist: python_jsonschema_objects==0.5.2
|
|
17
17
|
Requires-Dist: jsonschema==4.21.1
|
|
18
18
|
Requires-Dist: certifi==2024.2.2
|
|
@@ -211,6 +211,7 @@ contributed. Black is installed as a test dependency and the hook can be initial
|
|
|
211
211
|
after cloning this repository.
|
|
212
212
|
|
|
213
213
|
## Changelog
|
|
214
|
+
* 5.5.0 - Updated helper class to add `make_request`, `response_handler`, `extract_json`, and `request_error_handling` for HTTP requests, and `hash_sha1` and `compare_and_dedupe_hashes` to provide support for hash comparisons | Add `METHOD_NOT_ALLOWED`, `CONFLICT`, `REDIRECT_ERROR`, and `CONNECTION_ERROR` to PluginException presets
|
|
214
215
|
* 5.4.9 - Updated aws_client to clean assume role json object to remove any none or empty string values.
|
|
215
216
|
* 5.4.8 - Address vulnerabilities within `gunicorn` and `idna` python packages.
|
|
216
217
|
* 5.4.7 - Address vulnerabilities within `insightconnect-python-3-plugin` image.
|
|
@@ -182,6 +182,7 @@ contributed. Black is installed as a test dependency and the hook can be initial
|
|
|
182
182
|
after cloning this repository.
|
|
183
183
|
|
|
184
184
|
## Changelog
|
|
185
|
+
* 5.5.0 - Updated helper class to add `make_request`, `response_handler`, `extract_json`, and `request_error_handling` for HTTP requests, and `hash_sha1` and `compare_and_dedupe_hashes` to provide support for hash comparisons | Add `METHOD_NOT_ALLOWED`, `CONFLICT`, `REDIRECT_ERROR`, and `CONNECTION_ERROR` to PluginException presets
|
|
185
186
|
* 5.4.9 - Updated aws_client to clean assume role json object to remove any none or empty string values.
|
|
186
187
|
* 5.4.8 - Address vulnerabilities within `gunicorn` and `idna` python packages.
|
|
187
188
|
* 5.4.7 - Address vulnerabilities within `insightconnect-python-3-plugin` image.
|
|
@@ -83,7 +83,17 @@ def handle_errors(error: HTTPException):
|
|
|
83
83
|
|
|
84
84
|
|
|
85
85
|
class Endpoints:
|
|
86
|
-
def __init__(
|
|
86
|
+
def __init__(
|
|
87
|
+
self,
|
|
88
|
+
logger,
|
|
89
|
+
plugin,
|
|
90
|
+
spec,
|
|
91
|
+
debug,
|
|
92
|
+
workers,
|
|
93
|
+
threads,
|
|
94
|
+
master_pid,
|
|
95
|
+
config_options=None,
|
|
96
|
+
):
|
|
87
97
|
self.plugin = plugin
|
|
88
98
|
self.logger = structlog.get_logger("plugin")
|
|
89
99
|
self.spec = spec
|
|
@@ -167,7 +177,9 @@ class Endpoints:
|
|
|
167
177
|
Endpoints.validate_action_trigger_task_name(input_message, name, "task")
|
|
168
178
|
# No validation on the plugin custom config to leave this as configurable as possible.
|
|
169
179
|
# `add_plugin_custom_config` will pass any available values to the plugin for interpretation.
|
|
170
|
-
input_message = self.add_plugin_custom_config(
|
|
180
|
+
input_message = self.add_plugin_custom_config(
|
|
181
|
+
input_message, request.headers.get(ORG_ID)
|
|
182
|
+
)
|
|
171
183
|
output = self.run_action_trigger_task(input_message)
|
|
172
184
|
self.logger.info("Plugin task finished execution...")
|
|
173
185
|
return output
|
|
@@ -750,7 +762,9 @@ class Endpoints:
|
|
|
750
762
|
|
|
751
763
|
return version
|
|
752
764
|
|
|
753
|
-
def add_plugin_custom_config(
|
|
765
|
+
def add_plugin_custom_config(
|
|
766
|
+
self, input_data: Dict[str, Any], org_id: str
|
|
767
|
+
) -> Dict[str, Any]:
|
|
754
768
|
"""
|
|
755
769
|
Using the retrieved configs pulled from komand-props, pass the configuration that matches the requesting
|
|
756
770
|
Org ID which is passed to the task via a header (`X-IPIMS-ORGID`) from the plugin sidecar.
|
|
@@ -763,17 +777,27 @@ class Endpoints:
|
|
|
763
777
|
- all orgs for default runs will poll back 12 hours.
|
|
764
778
|
- all orgs in lookback mode will be 100 hours (task triggered with no state).
|
|
765
779
|
"""
|
|
766
|
-
additional_config = self.config_options.get(org_id) or self.config_options.get(
|
|
780
|
+
additional_config = self.config_options.get(org_id) or self.config_options.get(
|
|
781
|
+
"*"
|
|
782
|
+
)
|
|
767
783
|
if additional_config:
|
|
768
|
-
self.logger.info(
|
|
769
|
-
|
|
784
|
+
self.logger.info(
|
|
785
|
+
"Found config options; adding this to the request parameters..."
|
|
786
|
+
)
|
|
787
|
+
additional_config = (
|
|
788
|
+
additional_config.copy()
|
|
789
|
+
) # copy to preserve the referenced value in self.config_options
|
|
770
790
|
# As a safeguard we only pass the lookback config params if the plugin has no state
|
|
771
791
|
# This means we still need to manually delete the state for plugins on a per org basis.
|
|
772
792
|
# This also means first time customers for their 'initial' lookup would get the lookback value passed in.
|
|
773
|
-
if input_data.get("body", {}).get("state") and additional_config.get(
|
|
774
|
-
|
|
793
|
+
if input_data.get("body", {}).get("state") and additional_config.get(
|
|
794
|
+
"lookback"
|
|
795
|
+
):
|
|
796
|
+
self.logger.info(
|
|
797
|
+
"Found an existing plugin state, not passing lookback value..."
|
|
798
|
+
)
|
|
775
799
|
del additional_config["lookback"]
|
|
776
|
-
input_data.get("body", {}).update({
|
|
800
|
+
input_data.get("body", {}).update({"custom_config": additional_config})
|
|
777
801
|
self.logger.info(f"Custom config being sent to plugin: {additional_config}")
|
|
778
802
|
|
|
779
803
|
return input_data
|
|
@@ -29,13 +29,13 @@ class PaginationHelper:
|
|
|
29
29
|
"""
|
|
30
30
|
|
|
31
31
|
def __init__(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
self,
|
|
33
|
+
input_token: List[str],
|
|
34
|
+
output_token: List[str],
|
|
35
|
+
result_key: List[str],
|
|
36
|
+
limit_key: str = None,
|
|
37
|
+
more_results: str = None,
|
|
38
|
+
non_aggregate_keys: List[str] = None,
|
|
39
39
|
):
|
|
40
40
|
self.input_token = input_token
|
|
41
41
|
self.output_token = output_token
|
|
@@ -70,9 +70,9 @@ class PaginationHelper:
|
|
|
70
70
|
is_paginated = False
|
|
71
71
|
|
|
72
72
|
if (
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
self.more_results
|
|
74
|
+
and self.more_results in output.keys()
|
|
75
|
+
and output[self.more_results]
|
|
76
76
|
):
|
|
77
77
|
is_paginated = True
|
|
78
78
|
|
|
@@ -84,10 +84,10 @@ class PaginationHelper:
|
|
|
84
84
|
return is_paginated
|
|
85
85
|
|
|
86
86
|
def merge_responses(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
self,
|
|
88
|
+
input_: Dict[str, Any],
|
|
89
|
+
response_1: Dict[str, Any],
|
|
90
|
+
response_2: Dict[str, Any],
|
|
91
91
|
) -> Tuple[Dict[str, Any], bool]:
|
|
92
92
|
"""
|
|
93
93
|
Merges two output dictionaries together.
|
|
@@ -112,7 +112,8 @@ class PaginationHelper:
|
|
|
112
112
|
if len(response_1[response]) >= input_[self.limit_key]:
|
|
113
113
|
max_hit = True
|
|
114
114
|
response_1[response] = response_1[response][
|
|
115
|
-
|
|
115
|
+
: input_[self.limit_key]
|
|
116
|
+
]
|
|
116
117
|
|
|
117
118
|
return response_1, max_hit
|
|
118
119
|
|
|
@@ -302,7 +303,7 @@ class ActionHelper:
|
|
|
302
303
|
|
|
303
304
|
@classmethod
|
|
304
305
|
def format_output(
|
|
305
|
-
|
|
306
|
+
cls, output_schema: Union[Dict[str, Any], None], output: Dict[str, Any]
|
|
306
307
|
) -> Any:
|
|
307
308
|
"""
|
|
308
309
|
Formats a botocore response into a correct Komand response.
|
|
@@ -333,14 +334,14 @@ class AWSAction(Action):
|
|
|
333
334
|
"""
|
|
334
335
|
|
|
335
336
|
def __init__(
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
337
|
+
self,
|
|
338
|
+
name: str,
|
|
339
|
+
description: str,
|
|
340
|
+
input_: insightconnect_plugin_runtime.Input,
|
|
341
|
+
output: insightconnect_plugin_runtime.Output,
|
|
342
|
+
aws_service: str,
|
|
343
|
+
aws_command: str,
|
|
344
|
+
pagination_helper: PaginationHelper = None,
|
|
344
345
|
):
|
|
345
346
|
"""
|
|
346
347
|
|
|
@@ -362,7 +363,7 @@ class AWSAction(Action):
|
|
|
362
363
|
self.pagination_helper = pagination_helper
|
|
363
364
|
|
|
364
365
|
def _handle_botocore_function(
|
|
365
|
-
|
|
366
|
+
self, client_function: Callable, params: Dict
|
|
366
367
|
) -> Dict:
|
|
367
368
|
try:
|
|
368
369
|
response = client_function(**params)
|
|
@@ -480,11 +481,11 @@ class AWSAction(Action):
|
|
|
480
481
|
client_function = getattr(client, self.aws_command)
|
|
481
482
|
except AttributeError:
|
|
482
483
|
error_message = (
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
484
|
+
'Unable to find the command "'
|
|
485
|
+
+ self.aws_service
|
|
486
|
+
+ " "
|
|
487
|
+
+ self.aws_command
|
|
488
|
+
+ '"'
|
|
488
489
|
)
|
|
489
490
|
self.logger.error(error_message)
|
|
490
491
|
raise PluginException(cause=error_message)
|
|
@@ -533,17 +534,21 @@ class AWSAction(Action):
|
|
|
533
534
|
|
|
534
535
|
@staticmethod
|
|
535
536
|
def try_to_assume_role(
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
537
|
+
service_name: str,
|
|
538
|
+
assume_role_params: Dict[str, str],
|
|
539
|
+
auth_params: Dict[str, str],
|
|
539
540
|
):
|
|
540
541
|
session_name = str(uuid.uuid1())
|
|
541
542
|
sts_client = boto3.client("sts", **auth_params)
|
|
542
543
|
try:
|
|
543
544
|
assumed_role_object = sts_client.assume_role(
|
|
544
|
-
**clean(
|
|
545
|
-
|
|
546
|
-
|
|
545
|
+
**clean(
|
|
546
|
+
{
|
|
547
|
+
"RoleArn": assume_role_params.get(ROLE_ARN),
|
|
548
|
+
"RoleSessionName": session_name,
|
|
549
|
+
"ExternalId": assume_role_params.get(EXTERNAL_ID),
|
|
550
|
+
}
|
|
551
|
+
)
|
|
547
552
|
)
|
|
548
553
|
except ClientError as error:
|
|
549
554
|
raise PluginException(
|
|
@@ -1,6 +1,56 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
class ResponseExceptionData:
|
|
3
|
+
RESPONSE_TEXT = "response_text"
|
|
4
|
+
RESPONSE_JSON = "response_json"
|
|
5
|
+
RESPONSE = "response"
|
|
6
|
+
EXCEPTION = "exception"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class HTTPStatusCodes:
|
|
10
|
+
|
|
11
|
+
# 4xx Client Errors
|
|
12
|
+
BAD_REQUEST = 400
|
|
13
|
+
UNAUTHORIZED = 401
|
|
14
|
+
PAYMENT_REQUIRED = 402
|
|
15
|
+
FORBIDDEN = 403
|
|
16
|
+
NOT_FOUND = 404
|
|
17
|
+
METHOD_NOT_ALLOWED = 405
|
|
18
|
+
NOT_ACCEPTABLE = 406
|
|
19
|
+
PROXY_AUTHENTICATION_REQUIRED = 407
|
|
20
|
+
REQUEST_TIMEOUT = 408
|
|
21
|
+
CONFLICT = 409
|
|
22
|
+
GONE = 410
|
|
23
|
+
LENGTH_REQUIRED = 411
|
|
24
|
+
PRECONDITION_FAILED = 412
|
|
25
|
+
PAYLOAD_TOO_LARGE = 413
|
|
26
|
+
URI_TOO_LONG = 414
|
|
27
|
+
UNSUPPORTED_MEDIA_TYPE = 415
|
|
28
|
+
RANGE_NOT_SATISFIABLE = 416
|
|
29
|
+
EXPECTATION_FAILED = 417
|
|
30
|
+
I_AM_A_TEAPOT = 418
|
|
31
|
+
MISDIRECTED_REQUEST = 421
|
|
32
|
+
UNPROCESSABLE_ENTITY = 422
|
|
33
|
+
LOCKED = 423
|
|
34
|
+
FAILED_DEPENDENCY = 424
|
|
35
|
+
TOO_EARLY = 425
|
|
36
|
+
UPGRADE_REQUIRED = 426
|
|
37
|
+
PRECONDITION_REQUIRED = 428
|
|
38
|
+
TOO_MANY_REQUESTS = 429
|
|
39
|
+
REQUEST_HEADER_FIELDS_TOO_LARGE = 431
|
|
40
|
+
UNAVAILABLE_FOR_LEGAL_REASONS = 451
|
|
41
|
+
|
|
42
|
+
# 5xx Server Errors
|
|
43
|
+
INTERNAL_SERVER_ERROR = 500
|
|
44
|
+
NOT_IMPLEMENTED = 501
|
|
45
|
+
BAD_GATEWAY = 502
|
|
46
|
+
SERVICE_UNAVAILABLE = 503
|
|
47
|
+
GATEWAY_TIMEOUT = 504
|
|
48
|
+
HTTP_VERSION_NOT_SUPPORTED = 505
|
|
49
|
+
VARIANT_ALSO_NEGOTIATES = 506
|
|
50
|
+
INSUFFICIENT_STORAGE = 507
|
|
51
|
+
LOOP_DETECTED = 508
|
|
52
|
+
NOT_EXTENDED = 510
|
|
53
|
+
NETWORK_AUTHENTICATION_REQUIRED = 511
|
|
4
54
|
|
|
5
55
|
|
|
6
56
|
class ClientException(Exception):
|
|
@@ -65,6 +115,10 @@ class ConnectionTestException(Exception):
|
|
|
65
115
|
TIMEOUT = "timeout"
|
|
66
116
|
BAD_REQUEST = "bad_request"
|
|
67
117
|
INVALID_CREDENTIALS = "invalid_credentials"
|
|
118
|
+
METHOD_NOT_ALLOWED = "method_not_allowed"
|
|
119
|
+
CONFLICT = "conflict"
|
|
120
|
+
CONNECTION_ERROR = "connection_error"
|
|
121
|
+
REDIRECT_ERROR = "redirect_error"
|
|
68
122
|
|
|
69
123
|
# Dictionary of cause messages
|
|
70
124
|
causes = {
|
|
@@ -82,6 +136,10 @@ class ConnectionTestException(Exception):
|
|
|
82
136
|
Preset.TIMEOUT: "The connection timed out.",
|
|
83
137
|
Preset.BAD_REQUEST: "The server is unable to process the request.",
|
|
84
138
|
Preset.INVALID_CREDENTIALS: "Authentication failed: invalid credentials.",
|
|
139
|
+
Preset.METHOD_NOT_ALLOWED: "The request method is not allowed for this resource.",
|
|
140
|
+
Preset.CONFLICT: "Request cannot be completed due to a conflict with the current state of the resource.",
|
|
141
|
+
Preset.CONNECTION_ERROR: "Failed to connect to the server.",
|
|
142
|
+
Preset.REDIRECT_ERROR: "Request redirected more than the set limit for the server.",
|
|
85
143
|
}
|
|
86
144
|
|
|
87
145
|
# Dictionary of assistance/remediation messages
|
|
@@ -103,6 +161,10 @@ class ConnectionTestException(Exception):
|
|
|
103
161
|
Preset.BAD_REQUEST: "Verify your plugin input is correct and not malformed and try again. "
|
|
104
162
|
"If the issue persists, please contact support.",
|
|
105
163
|
Preset.INVALID_CREDENTIALS: "Please verify the credentials for your account and try again.",
|
|
164
|
+
Preset.METHOD_NOT_ALLOWED: "Please try a supported method for this resource.",
|
|
165
|
+
Preset.CONFLICT: "Please check your request, and try again.",
|
|
166
|
+
Preset.CONNECTION_ERROR: "Please check your network connection and try again.",
|
|
167
|
+
Preset.REDIRECT_ERROR: "Please check your request and try again.",
|
|
106
168
|
}
|
|
107
169
|
|
|
108
170
|
def __init__(self, cause=None, assistance=None, data=None, preset=None):
|
|
@@ -124,12 +186,6 @@ class ConnectionTestException(Exception):
|
|
|
124
186
|
|
|
125
187
|
self.data = str(data) if data else ""
|
|
126
188
|
|
|
127
|
-
# Safeguard to ensure the exception is logged across all plugins even if the plugin
|
|
128
|
-
# itself does not call `self.logger.error(<error info>)`
|
|
129
|
-
params = ["cause", "assistance", "data", "preset"]
|
|
130
|
-
info_log = ", ".join([f"{atr}='{getattr(self, atr)}'" for atr in params if getattr(self, atr)])
|
|
131
|
-
logger.error(f"Plugin exception instantiated. {info_log}")
|
|
132
|
-
|
|
133
189
|
def __str__(self):
|
|
134
190
|
if self.data:
|
|
135
191
|
return "Connection test failed!\n\n{cause} {assistance} Response was: {data}".format(
|
|
@@ -12,18 +12,276 @@ from datetime import datetime, timedelta
|
|
|
12
12
|
from io import IOBase
|
|
13
13
|
from typing import Any, Callable, Dict, List, Union
|
|
14
14
|
from urllib import request
|
|
15
|
+
from hashlib import sha1
|
|
16
|
+
from json import JSONDecodeError
|
|
15
17
|
|
|
16
18
|
import requests
|
|
17
19
|
|
|
18
|
-
from insightconnect_plugin_runtime.exceptions import
|
|
20
|
+
from insightconnect_plugin_runtime.exceptions import (
|
|
21
|
+
PluginException,
|
|
22
|
+
HTTPStatusCodes,
|
|
23
|
+
ResponseExceptionData,
|
|
24
|
+
)
|
|
19
25
|
|
|
20
26
|
CAMEL_CASE_REGEX = r"\b[a-z0-9]+([A-Z][a-z]+[0-9]*)*\b"
|
|
21
27
|
CAMEL_CASE_ACRONYM_REGEX = r"\b[a-z0-9]+([A-Z]+[0-9]*)*\b"
|
|
22
28
|
PASCAL_CASE_REGEX = r"\b[A-Z][a-z]+[0-9]*([A-Z][a-z]+[0-9]*)*\b"
|
|
29
|
+
ENCODE_TYPE = "utf-8"
|
|
23
30
|
|
|
24
31
|
DEFAULTS_HOURS_AGO = 24
|
|
25
32
|
|
|
26
33
|
|
|
34
|
+
def hash_sha1(log: dict) -> str:
|
|
35
|
+
"""
|
|
36
|
+
Iterate through a dictionary and hash each value.
|
|
37
|
+
:param log: Dictionary to be hashed.
|
|
38
|
+
:type dict:
|
|
39
|
+
:return: Hex digest of hash.
|
|
40
|
+
:rtype: str
|
|
41
|
+
"""
|
|
42
|
+
hash_ = sha1() # nosec B303
|
|
43
|
+
for key, value in log.items():
|
|
44
|
+
hash_.update(f"{key}{value}".encode(ENCODE_TYPE))
|
|
45
|
+
return hash_.hexdigest()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def compare_and_dedupe_hashes(
|
|
49
|
+
previous_logs_hashes: list, new_logs: list
|
|
50
|
+
) -> tuple[list, list]:
|
|
51
|
+
"""
|
|
52
|
+
Iterate through two lists of values, hashing each. Compare hash value to a list of existing hash values.
|
|
53
|
+
If the hash exists, return both it and the value in separate lists once iterated.
|
|
54
|
+
:param previous_logs_hashes: List of existing hashes to compare against.
|
|
55
|
+
:type list:
|
|
56
|
+
:param new_logs: New values to hash and compare to existing list of hashes.
|
|
57
|
+
:type list:
|
|
58
|
+
:return: Hex digest of hash.
|
|
59
|
+
:rtype: tuple[list, list]
|
|
60
|
+
"""
|
|
61
|
+
new_logs_hashes = []
|
|
62
|
+
logs_to_return = []
|
|
63
|
+
for log in new_logs:
|
|
64
|
+
hash_ = hash_sha1(log)
|
|
65
|
+
if hash_ not in previous_logs_hashes:
|
|
66
|
+
new_logs_hashes.append(hash_)
|
|
67
|
+
logs_to_return.append(log)
|
|
68
|
+
logging.info(
|
|
69
|
+
f"Original number of logs:{len(new_logs)}. Number of logs after de-duplication:{len(logs_to_return)}"
|
|
70
|
+
)
|
|
71
|
+
return logs_to_return, new_logs_hashes
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def make_request(
|
|
75
|
+
_request: requests.Request,
|
|
76
|
+
timeout: int = 60,
|
|
77
|
+
verify: bool = True,
|
|
78
|
+
cert: Union[str, tuple]=None,
|
|
79
|
+
stream: bool = False,
|
|
80
|
+
allow_redirects: bool = True,
|
|
81
|
+
exception_custom_configs: Dict[int, Exception]={},
|
|
82
|
+
exception_data_location: str = None,
|
|
83
|
+
allowed_status_codes: list[str] = [],
|
|
84
|
+
) -> tuple[requests.Response, dict]:
|
|
85
|
+
"""
|
|
86
|
+
Makes a HTTP request while checking for RequestErrors and JSONDecodeErrors
|
|
87
|
+
Returns the request response and the response JSON if required.
|
|
88
|
+
:param _request: Request object to utilize in request
|
|
89
|
+
:type Request:
|
|
90
|
+
:param timeout: Requests timeout paramater
|
|
91
|
+
:type int:
|
|
92
|
+
:param verify: Whether to verify the server's TLS certificate
|
|
93
|
+
:type bool:
|
|
94
|
+
:param cert: Certificate to include with request, str location or key/value pair
|
|
95
|
+
:type Union[str, dict]:
|
|
96
|
+
:param stream: Whether to immediately download the response content
|
|
97
|
+
:type bool:
|
|
98
|
+
:param allow_redirects: Set to true by default
|
|
99
|
+
:type bool:
|
|
100
|
+
:param exception_custom_configs: Custom exception values to be raised per HTTPStatusCode.
|
|
101
|
+
:type Dict[str, Exception]:
|
|
102
|
+
:param exception_data_location: Where the returned data should be retrieved. Can provide ResponseExceptionData values.
|
|
103
|
+
:type str:
|
|
104
|
+
:param allowed_status_codes: Status codes that will not raise an exception.
|
|
105
|
+
:type list[str]:
|
|
106
|
+
|
|
107
|
+
:return: The request response and the response JSON.
|
|
108
|
+
:rtype: tuple[Response, dict]
|
|
109
|
+
"""
|
|
110
|
+
try:
|
|
111
|
+
with requests.Session() as session:
|
|
112
|
+
prepared_request = session.prepare_request(request=_request)
|
|
113
|
+
response = session.send(
|
|
114
|
+
prepared_request,
|
|
115
|
+
verify=verify,
|
|
116
|
+
timeout=timeout,
|
|
117
|
+
allow_redirects=allow_redirects,
|
|
118
|
+
cert=cert,
|
|
119
|
+
stream=stream,
|
|
120
|
+
)
|
|
121
|
+
except requests.exceptions.Timeout as exception:
|
|
122
|
+
raise PluginException(
|
|
123
|
+
preset=PluginException.Preset.TIMEOUT, data=str(exception)
|
|
124
|
+
)
|
|
125
|
+
except requests.exceptions.ConnectionError as exception:
|
|
126
|
+
raise PluginException(
|
|
127
|
+
preset=PluginException.Preset.CONNECTION_ERROR, data=str(exception)
|
|
128
|
+
)
|
|
129
|
+
except requests.exceptions.TooManyRedirects as exception:
|
|
130
|
+
raise PluginException(
|
|
131
|
+
preset=PluginException.Preset.REDIRECT_ERROR, data=str(exception)
|
|
132
|
+
)
|
|
133
|
+
except requests.exceptions.RequestException as exception:
|
|
134
|
+
if not isinstance(exception, requests.exceptions.HTTPError):
|
|
135
|
+
raise PluginException(
|
|
136
|
+
preset=PluginException.Preset.UNKNOWN, data=str(exception)
|
|
137
|
+
)
|
|
138
|
+
response_handler(response, exception_custom_configs, exception_data_location, allowed_status_codes)
|
|
139
|
+
return response
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def extract_json(response: requests.Response) -> dict:
|
|
143
|
+
"""Extract JSON from a request object while error handling a JSONDecodeError.
|
|
144
|
+
:param response: Response object ot utilize in extract
|
|
145
|
+
:type Response:
|
|
146
|
+
:returns: Dictionary of response JSON
|
|
147
|
+
:rtype: Dict
|
|
148
|
+
"""
|
|
149
|
+
try:
|
|
150
|
+
response_json = response.json()
|
|
151
|
+
return response_json
|
|
152
|
+
except JSONDecodeError as exception:
|
|
153
|
+
raise PluginException(
|
|
154
|
+
preset=PluginException.Preset.INVALID_JSON, data=str(exception)
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def request_error_handling() -> Union[Any, None]:
|
|
159
|
+
"""request_error_handling. This decorator allows a method that makes a request to complete with error handling.
|
|
160
|
+
A plugin exception will be raised whenever an error is caught. Response.raise_for_status() must be called in the
|
|
161
|
+
wrapped method to handle HTTPErrors.
|
|
162
|
+
|
|
163
|
+
:returns: API call function data or None.
|
|
164
|
+
:rtype: Union[Any, None]
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
def _decorate(func: Callable):
|
|
168
|
+
def _wrapper(self, *args, **kwargs):
|
|
169
|
+
try:
|
|
170
|
+
return func(self, *args, **kwargs)
|
|
171
|
+
except requests.exceptions.Timeout as exception:
|
|
172
|
+
raise PluginException(
|
|
173
|
+
preset=PluginException.Preset.TIMEOUT, data=str(exception)
|
|
174
|
+
)
|
|
175
|
+
except requests.exceptions.ConnectionError as exception:
|
|
176
|
+
raise PluginException(
|
|
177
|
+
preset=PluginException.Preset.CONNECTION_ERROR, data=str(exception)
|
|
178
|
+
)
|
|
179
|
+
except requests.exceptions.TooManyRedirects as exception:
|
|
180
|
+
raise PluginException(
|
|
181
|
+
preset=PluginException.Preset.REDIRECT_ERROR, data=str(exception)
|
|
182
|
+
)
|
|
183
|
+
except requests.exceptions.RequestException as exception:
|
|
184
|
+
if isinstance(exception, requests.exceptions.HTTPError):
|
|
185
|
+
response_handler(exception.response)
|
|
186
|
+
else:
|
|
187
|
+
raise PluginException(
|
|
188
|
+
preset=PluginException.Preset.UNKNOWN, data=str(exception)
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
return _wrapper
|
|
192
|
+
|
|
193
|
+
return _decorate
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def response_handler(
|
|
197
|
+
response: requests.Response,
|
|
198
|
+
custom_configs: Dict[int, Exception]={},
|
|
199
|
+
data_location: str = None,
|
|
200
|
+
allowed_status_codes: list[str] = [],
|
|
201
|
+
) -> None:
|
|
202
|
+
"""
|
|
203
|
+
Check response status codes and return a generic PluginException preset if a HTTPError is raised.
|
|
204
|
+
Excetion cause, assistance, and data can be overwritten by supplied parameters.
|
|
205
|
+
|
|
206
|
+
:param response: Response object whose status should be checked.
|
|
207
|
+
:type Response:
|
|
208
|
+
:param custom_configs: Custom exception values to be raised per HTTPStatusCode.
|
|
209
|
+
:type Dict[str, Exception]:
|
|
210
|
+
:param data_location: Where the returned data should be retrieved. Can provide ResponseExceptionData values.
|
|
211
|
+
:type str:
|
|
212
|
+
:param allowed_status_codes: Status codes that will not raise an exception.
|
|
213
|
+
:type list[str]:
|
|
214
|
+
|
|
215
|
+
:return: None.
|
|
216
|
+
:rtype: None
|
|
217
|
+
"""
|
|
218
|
+
try:
|
|
219
|
+
response.raise_for_status()
|
|
220
|
+
except requests.exceptions.HTTPError as exception:
|
|
221
|
+
|
|
222
|
+
data = _return_response_data(response, exception, data_location)
|
|
223
|
+
status_code = response.status_code
|
|
224
|
+
if status_code in allowed_status_codes:
|
|
225
|
+
return
|
|
226
|
+
status_code_presets = {
|
|
227
|
+
HTTPStatusCodes.BAD_REQUEST: PluginException.Preset.BAD_REQUEST,
|
|
228
|
+
HTTPStatusCodes.UNAUTHORIZED: PluginException.Preset.INVALID_CREDENTIALS,
|
|
229
|
+
HTTPStatusCodes.FORBIDDEN: PluginException.Preset.UNAUTHORIZED,
|
|
230
|
+
HTTPStatusCodes.NOT_FOUND: PluginException.Preset.NOT_FOUND,
|
|
231
|
+
HTTPStatusCodes.METHOD_NOT_ALLOWED: PluginException.Preset.METHOD_NOT_ALLOWED,
|
|
232
|
+
HTTPStatusCodes.REQUEST_TIMEOUT: PluginException.Preset.TIMEOUT,
|
|
233
|
+
HTTPStatusCodes.CONFLICT: PluginException.Preset.CONFLICT,
|
|
234
|
+
HTTPStatusCodes.TOO_MANY_REQUESTS: PluginException.Preset.RATE_LIMIT,
|
|
235
|
+
HTTPStatusCodes.INTERNAL_SERVER_ERROR: PluginException.Preset.SERVER_ERROR,
|
|
236
|
+
HTTPStatusCodes.SERVICE_UNAVAILABLE: PluginException.Preset.SERVICE_UNAVAILABLE,
|
|
237
|
+
}
|
|
238
|
+
status_code_preset = status_code_presets.get(status_code)
|
|
239
|
+
exception = PluginException(preset=PluginException.Preset.UNKNOWN, data=data)
|
|
240
|
+
logging.info(f"Request to {response.url} failed. Status code: {status_code}")
|
|
241
|
+
if status_code in custom_configs.keys():
|
|
242
|
+
exception = custom_configs.get(status_code)
|
|
243
|
+
if hasattr(exception, "data") and data is not None:
|
|
244
|
+
exception.data = data
|
|
245
|
+
elif status_code_preset:
|
|
246
|
+
exception = PluginException(preset=status_code_preset, data=data)
|
|
247
|
+
|
|
248
|
+
raise exception
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def _return_response_data(
|
|
252
|
+
response: requests.Response,
|
|
253
|
+
exception: requests.HTTPError,
|
|
254
|
+
data_location: str = None,
|
|
255
|
+
) -> str:
|
|
256
|
+
"""
|
|
257
|
+
Retrieve data from HTTP Error given a provided data location
|
|
258
|
+
|
|
259
|
+
:param response: Response object whose status should be checked.
|
|
260
|
+
:type Response:
|
|
261
|
+
:param exception: HTTPError exception to retrieve data.
|
|
262
|
+
:type HTTPError:
|
|
263
|
+
:param data_location: Where the returned data should be retrieved. Can provide ResponseExceptionData values.
|
|
264
|
+
:type str:
|
|
265
|
+
|
|
266
|
+
:return: Exception data.
|
|
267
|
+
:rtype: str
|
|
268
|
+
"""
|
|
269
|
+
data = None
|
|
270
|
+
if data_location == ResponseExceptionData.EXCEPTION:
|
|
271
|
+
data = str(exception)
|
|
272
|
+
elif data_location == ResponseExceptionData.RESPONSE:
|
|
273
|
+
data = response
|
|
274
|
+
elif data_location == ResponseExceptionData.RESPONSE_TEXT:
|
|
275
|
+
data = response.text
|
|
276
|
+
elif data_location == ResponseExceptionData.RESPONSE_JSON:
|
|
277
|
+
try:
|
|
278
|
+
data = response.json()
|
|
279
|
+
except JSONDecodeError:
|
|
280
|
+
# Return full exception if JSON cannot be resolved
|
|
281
|
+
data = exception
|
|
282
|
+
return data
|
|
283
|
+
|
|
284
|
+
|
|
27
285
|
def extract_value(begin, key, end, s):
|
|
28
286
|
"""
|
|
29
287
|
Returns a string from a given key/pattern using provided regular expressions.
|