insightconnect-plugin-runtime 6.2.6__tar.gz → 6.3.1__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-6.2.6/insightconnect_plugin_runtime.egg-info → insightconnect_plugin_runtime-6.3.1}/PKG-INFO +9 -2
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/README.md +2 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/api/endpoints.py +137 -9
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/server.py +29 -19
- insightconnect_plugin_runtime-6.3.1/insightconnect_plugin_runtime/telemetry.py +73 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/util.py +1 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1/insightconnect_plugin_runtime.egg-info}/PKG-INFO +9 -2
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime.egg-info/SOURCES.txt +1 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime.egg-info/requires.txt +5 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/setup.py +6 -1
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/test_endpoints.py +144 -4
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/test_server_cloud_plugins.py +9 -4
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/MANIFEST.in +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect-plugin-swagger.json +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/action.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/api/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/api/schemas.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/cli.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/clients/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/clients/aws_client.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/clients/oauth.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/connection.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/data/input_message_schema.json +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/data/output_message_schema.json +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/dispatcher.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/exceptions.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/helper.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/metrics.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/plugin.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/schema.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/step.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/task.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/trigger.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime/variables.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime.egg-info/dependency_links.txt +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/insightconnect_plugin_runtime.egg-info/top_level.txt +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/setup.cfg +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/hello/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/hello/action.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/hello/schema.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/return_bad_json/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/return_bad_json/action.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/return_bad_json/schema.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/throw_exception/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/throw_exception/action.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/throw_exception/schema.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/connection/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/connection/connection.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/connection/schema.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/tasks/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/tasks/monitor_events/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/tasks/monitor_events/schema.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/tasks/monitor_events/task.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/hello_trigger/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/hello_trigger/schema.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/hello_trigger/trigger.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/return_bad_json_trigger/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/return_bad_json_trigger/schema.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/return_bad_json_trigger/trigger.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/throw_exception_trigger/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/throw_exception_trigger/schema.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/throw_exception_trigger/trigger.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/komand_hello_world/util/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/hello_world/setup.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/tests/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/tests/conftest.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/tests/test_cli.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/tests/test_hello_world.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/hello_world/tests/test_server.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/__init__.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/test_action.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/test_api.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/test_aws_action.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/test_custom_encoder.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/test_exceptions.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/test_helpers.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/test_metrics.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/test_oauth.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/test_plugin.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/test_schema.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/test_server_spec.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/test_trigger.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/test_variables.py +0 -0
- {insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: insightconnect-plugin-runtime
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.3.1
|
|
4
4
|
Summary: InsightConnect Plugin Runtime
|
|
5
5
|
Home-page: https://github.com/rapid7/komand-plugin-sdk-python
|
|
6
6
|
Author: Rapid7 Integrations Alliance
|
|
@@ -26,6 +26,11 @@ Requires-Dist: apispec-webframeworks==1.0.0
|
|
|
26
26
|
Requires-Dist: blinker==1.9.0
|
|
27
27
|
Requires-Dist: structlog==24.4.0
|
|
28
28
|
Requires-Dist: python-json-logger==2.0.7
|
|
29
|
+
Requires-Dist: Jinja2==3.1.6
|
|
30
|
+
Requires-Dist: opentelemetry-sdk==1.31.1
|
|
31
|
+
Requires-Dist: opentelemetry-instrumentation-flask==0.52b1
|
|
32
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http==1.31.1
|
|
33
|
+
Requires-Dist: opentelemetry-instrumentation-requests==0.52b1
|
|
29
34
|
Dynamic: author
|
|
30
35
|
Dynamic: author-email
|
|
31
36
|
Dynamic: classifier
|
|
@@ -219,6 +224,8 @@ contributed. Black is installed as a test dependency and the hook can be initial
|
|
|
219
224
|
after cloning this repository.
|
|
220
225
|
|
|
221
226
|
## Changelog
|
|
227
|
+
* 6.3.1 - Improved filtering for `custom_config` parameters for plugin tasks
|
|
228
|
+
* 6.3.0 - Add Tracing Instrumentation
|
|
222
229
|
* 6.2.6 - Remove setuptools after installation
|
|
223
230
|
* 6.2.5 - Fixed bug related to failure to set default region to assume role method in `aws_client` for newer versions of boto3 | Updated alpine image packages on build
|
|
224
231
|
* 6.2.4 - Update `make_request` helper to support extra parameter of `max_response_size` to cap the response
|
|
@@ -182,6 +182,8 @@ 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
|
+
* 6.3.1 - Improved filtering for `custom_config` parameters for plugin tasks
|
|
186
|
+
* 6.3.0 - Add Tracing Instrumentation
|
|
185
187
|
* 6.2.6 - Remove setuptools after installation
|
|
186
188
|
* 6.2.5 - Fixed bug related to failure to set default region to assume role method in `aws_client` for newer versions of boto3 | Updated alpine image packages on build
|
|
187
189
|
* 6.2.4 - Update `make_request` helper to support extra parameter of `max_response_size` to cap the response
|
|
@@ -24,9 +24,11 @@ from insightconnect_plugin_runtime.exceptions import (
|
|
|
24
24
|
ServerException,
|
|
25
25
|
)
|
|
26
26
|
from insightconnect_plugin_runtime.util import OutputMasker
|
|
27
|
+
from uuid import UUID
|
|
27
28
|
|
|
28
29
|
logger = structlog.get_logger("plugin")
|
|
29
30
|
ORG_ID = "X-IPIMS-ORGID"
|
|
31
|
+
INT_ID = "X-INTEGRATION-ID"
|
|
30
32
|
|
|
31
33
|
PLUGIN_SPEC_DOCKERFILE = "/python/src/plugin.spec.yaml"
|
|
32
34
|
PLUGIN_SPEC_PACK = "/workspace/plugin.spec.yaml"
|
|
@@ -173,15 +175,20 @@ class Endpoints:
|
|
|
173
175
|
500:
|
|
174
176
|
description: Unexpected error
|
|
175
177
|
"""
|
|
178
|
+
|
|
176
179
|
self.logger.info("Plugin task beginning execution...")
|
|
177
180
|
input_message = request.get_json(force=True)
|
|
178
181
|
self.logger.debug("Request input: %s", input_message)
|
|
179
182
|
Endpoints.validate_action_trigger_task_empty_input(input_message)
|
|
180
183
|
Endpoints.validate_action_trigger_task_name(input_message, name, "task")
|
|
184
|
+
|
|
181
185
|
# No validation on the plugin custom config to leave this as configurable as possible.
|
|
182
186
|
# `add_plugin_custom_config` will pass any available values to the plugin for interpretation.
|
|
183
187
|
input_message = self.add_plugin_custom_config(
|
|
184
|
-
input_message,
|
|
188
|
+
input_message,
|
|
189
|
+
request.headers.get(ORG_ID, ""),
|
|
190
|
+
request.headers.get(INT_ID, ""),
|
|
191
|
+
name,
|
|
185
192
|
)
|
|
186
193
|
output = self.run_action_trigger_task(input_message, mask_output=False)
|
|
187
194
|
self.logger.info("Plugin task finished execution...")
|
|
@@ -787,7 +794,7 @@ class Endpoints:
|
|
|
787
794
|
return version
|
|
788
795
|
|
|
789
796
|
def add_plugin_custom_config(
|
|
790
|
-
self, input_data: Dict[str, Any], org_id: str
|
|
797
|
+
self, input_data: Dict[str, Any], org_id: str, int_id: str, task_name: str
|
|
791
798
|
) -> Dict[str, Any]:
|
|
792
799
|
"""
|
|
793
800
|
Using the retrieved configs pulled from komand-props, pass the configuration that matches the requesting
|
|
@@ -800,17 +807,95 @@ class Endpoints:
|
|
|
800
807
|
- org 1 when in lookback mode will pull back 108 hours (task triggered with no state).
|
|
801
808
|
- all orgs for default runs will poll back 12 hours.
|
|
802
809
|
- all orgs in lookback mode will be 100 hours (task triggered with no state).
|
|
810
|
+
|
|
811
|
+
When Int ID is specified or task name. Then it can be used across all orgs (global config) or specific Org ID.
|
|
812
|
+
There's a hierarchy between task related config and Int ID related, where Int ID will always
|
|
813
|
+
replace task related config due to its higher priority.
|
|
814
|
+
|
|
815
|
+
Config example:
|
|
816
|
+
{
|
|
817
|
+
"org_1": {
|
|
818
|
+
"task_name_1": {
|
|
819
|
+
"default": 12,
|
|
820
|
+
"lookback": "100"
|
|
821
|
+
},
|
|
822
|
+
"int_1": {
|
|
823
|
+
"default": 6,
|
|
824
|
+
"lookback": "50"
|
|
825
|
+
},
|
|
826
|
+
{
|
|
827
|
+
"default": 24,
|
|
828
|
+
"lookback": "108"
|
|
829
|
+
}
|
|
830
|
+
},
|
|
831
|
+
"*": {
|
|
832
|
+
"default": 24,
|
|
833
|
+
"lookback": 200
|
|
834
|
+
"task_name_2": {
|
|
835
|
+
"default": 2,
|
|
836
|
+
"lookback": "10"
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
In this config example the following we be applied:
|
|
842
|
+
- org 1 to has a custom default time of 24 hours for their timings.
|
|
843
|
+
- org 1 when in lookback mode will pull back 108 hours (task triggered with no state).
|
|
844
|
+
- org 1 all integrations that uses task with 'task_name_1' will pull back 100 hours
|
|
845
|
+
and have a custom default time of 12 hours for their timings.
|
|
846
|
+
- org 1 specific integration 'int_1' will pull back 50 hours and have a custom
|
|
847
|
+
default time of 6 hours for their timings.
|
|
848
|
+
- all orgs for default runs will poll back 24 hours.
|
|
849
|
+
- all orgs in lookback mode will be 200 hours (task triggered with no state).
|
|
850
|
+
- all orgs that uses task with 'task_name_2' will pull back 2 hours
|
|
851
|
+
- all orgs that uses task with 'task_name_2' in lookback mode will be 10 hours
|
|
803
852
|
"""
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
)
|
|
853
|
+
|
|
854
|
+
# Parse configuration based on organization or global. Use its copies, not to modify original dict.
|
|
855
|
+
organization_config, global_config = self.config_options.get(org_id, {}).copy(), self.config_options.get("*", {}).copy()
|
|
856
|
+
|
|
857
|
+
# Definition of additional config and its type variables.
|
|
858
|
+
additional_config, config_type = {}, ""
|
|
859
|
+
|
|
860
|
+
# Check if we have a global config.
|
|
861
|
+
# Also, use "config_type" variable just for logging purposes to have an indicator from where the config was pulled.
|
|
862
|
+
if global_config:
|
|
863
|
+
# Setup global config as starting point.
|
|
864
|
+
additional_config, config_type = global_config, "GLOBAL"
|
|
865
|
+
|
|
866
|
+
# If task configuration was found under global config, update it with task config to replace necessary values.
|
|
867
|
+
if task_config := global_config.get(task_name):
|
|
868
|
+
additional_config.update(task_config)
|
|
869
|
+
config_type = "GLOBAL_TASK"
|
|
870
|
+
|
|
871
|
+
# If organization config is present, then replace its values with the ones coming from global config.
|
|
872
|
+
if organization_config:
|
|
873
|
+
# Update additional config with values coming from organization config.
|
|
874
|
+
additional_config.update(organization_config)
|
|
875
|
+
config_type = "ORG"
|
|
876
|
+
|
|
877
|
+
# If task configuration was found under organization, replace its values with organization config.
|
|
878
|
+
if task_config := organization_config.get(task_name):
|
|
879
|
+
additional_config.update(task_config)
|
|
880
|
+
config_type = "ORG_TASK"
|
|
881
|
+
|
|
882
|
+
# If integration config was found under organization replace its values with organization
|
|
883
|
+
# and task config (higher priority).
|
|
884
|
+
if integration_config := organization_config.get(int_id):
|
|
885
|
+
additional_config.update(integration_config)
|
|
886
|
+
config_type = "ORG_INT"
|
|
887
|
+
|
|
807
888
|
if additional_config:
|
|
808
889
|
self.logger.info(
|
|
809
|
-
"Found config options; adding this to the request parameters..."
|
|
890
|
+
f"Found config options ({config_type}); adding this to the request parameters..."
|
|
810
891
|
)
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
892
|
+
|
|
893
|
+
# Sopy to preserve the referenced value in self.config_options.
|
|
894
|
+
# Also, remove unnecessary fields from that config (int_ids, or task_names) that occurs
|
|
895
|
+
# when updated global dictionary above. This thing is that we use global config as base
|
|
896
|
+
# and then updating some fields depending on the configuration.
|
|
897
|
+
additional_config = self._remove_unnecessary_fields_from_custom_config(additional_config)
|
|
898
|
+
|
|
814
899
|
# As a safeguard we only pass the lookback config params if the plugin has no state
|
|
815
900
|
# This means we still need to manually delete the state for plugins on a per org basis.
|
|
816
901
|
# This also means first time customers for their 'initial' lookup would get the lookback value passed in.
|
|
@@ -878,3 +963,46 @@ class Endpoints:
|
|
|
878
963
|
return 501
|
|
879
964
|
else:
|
|
880
965
|
return 500
|
|
966
|
+
|
|
967
|
+
def _remove_unnecessary_fields_from_custom_config(self, additional_config: Dict[str, Any]) -> Dict[str, Any]:
|
|
968
|
+
"""
|
|
969
|
+
Removes unnecessary fields from custom config such as other task names, and int_ids,
|
|
970
|
+
leaving only the fields that needs to be parsed.
|
|
971
|
+
|
|
972
|
+
:param additional_config: The custom config dictionary on which, unnecessary fields will be removed.
|
|
973
|
+
:type additional_config: Dict[str, Any]
|
|
974
|
+
|
|
975
|
+
:return: New custom config dictionary with unnecessary fields removed.
|
|
976
|
+
:rtype: Dict[str, Any]
|
|
977
|
+
"""
|
|
978
|
+
|
|
979
|
+
# Copy 'additional_config' not to operate on it
|
|
980
|
+
config_copy = additional_config.copy()
|
|
981
|
+
|
|
982
|
+
# Remove other task names from config
|
|
983
|
+
for task_ in self.plugin.tasks.keys():
|
|
984
|
+
config_copy.pop(task_, None)
|
|
985
|
+
|
|
986
|
+
# Remove other int_ids from config
|
|
987
|
+
for key_ in additional_config.keys():
|
|
988
|
+
if self._check_if_uuid(key_):
|
|
989
|
+
config_copy.pop(key_, None)
|
|
990
|
+
return config_copy
|
|
991
|
+
|
|
992
|
+
@staticmethod
|
|
993
|
+
def _check_if_uuid(input_string: str) -> bool:
|
|
994
|
+
"""
|
|
995
|
+
Validates whether the provided string matches UUID format specifications.
|
|
996
|
+
|
|
997
|
+
:param input_string: The string to validate against UUID format standards
|
|
998
|
+
:type input_string: str
|
|
999
|
+
|
|
1000
|
+
:return: True if the string is a valid UUID, False otherwise
|
|
1001
|
+
:rtype: bool
|
|
1002
|
+
"""
|
|
1003
|
+
|
|
1004
|
+
try:
|
|
1005
|
+
UUID(input_string)
|
|
1006
|
+
return True
|
|
1007
|
+
except (TypeError, ValueError):
|
|
1008
|
+
return False
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import sys
|
|
3
1
|
import json
|
|
4
2
|
import logging
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
from time import sleep
|
|
5
6
|
|
|
7
|
+
import gunicorn.app.base
|
|
8
|
+
import structlog
|
|
6
9
|
from apispec import APISpec
|
|
7
10
|
from apispec.ext.marshmallow import MarshmallowPlugin
|
|
8
11
|
from apispec_webframeworks.flask import FlaskPlugin
|
|
9
|
-
|
|
10
12
|
from flask import Flask, request_started, request
|
|
11
|
-
import gunicorn.app.base
|
|
12
13
|
from gunicorn.arbiter import Arbiter
|
|
13
|
-
|
|
14
|
-
import structlog
|
|
15
14
|
from pythonjsonlogger.jsonlogger import JsonFormatter
|
|
16
15
|
from requests import get as request_get
|
|
17
16
|
from requests.exceptions import (
|
|
@@ -21,9 +20,9 @@ from requests.exceptions import (
|
|
|
21
20
|
JSONDecodeError,
|
|
22
21
|
ConnectionError,
|
|
23
22
|
)
|
|
24
|
-
from time import sleep
|
|
25
23
|
from werkzeug.utils import secure_filename
|
|
26
24
|
|
|
25
|
+
from insightconnect_plugin_runtime.api.endpoints import Endpoints, handle_errors
|
|
27
26
|
from insightconnect_plugin_runtime.api.schemas import (
|
|
28
27
|
PluginInfoSchema,
|
|
29
28
|
ActionTriggerOutputBodySchema,
|
|
@@ -39,9 +38,9 @@ from insightconnect_plugin_runtime.api.schemas import (
|
|
|
39
38
|
ConnectionDetailsSchema,
|
|
40
39
|
ConnectionTestSchema,
|
|
41
40
|
)
|
|
42
|
-
from insightconnect_plugin_runtime.api.endpoints import Endpoints, handle_errors
|
|
43
|
-
from insightconnect_plugin_runtime.util import is_running_in_cloud
|
|
44
41
|
from insightconnect_plugin_runtime.helper import clean_dict
|
|
42
|
+
from insightconnect_plugin_runtime.telemetry import create_post_fork
|
|
43
|
+
from insightconnect_plugin_runtime.util import is_running_in_cloud, OTEL_ENDPOINT
|
|
45
44
|
|
|
46
45
|
API_TITLE = "InsightConnect Plugin Runtime API"
|
|
47
46
|
API_VERSION = "1.0"
|
|
@@ -72,14 +71,14 @@ class PluginServer(gunicorn.app.base.BaseApplication):
|
|
|
72
71
|
"""
|
|
73
72
|
|
|
74
73
|
def __init__(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
74
|
+
self,
|
|
75
|
+
plugin,
|
|
76
|
+
port=10001,
|
|
77
|
+
workers=1,
|
|
78
|
+
threads=4,
|
|
79
|
+
debug=False,
|
|
80
|
+
worker_class="sync",
|
|
81
|
+
worker_connections=200,
|
|
83
82
|
):
|
|
84
83
|
|
|
85
84
|
gunicorn_file = os.environ.get("GUNICORN_CONFIG_FILE")
|
|
@@ -120,6 +119,9 @@ class PluginServer(gunicorn.app.base.BaseApplication):
|
|
|
120
119
|
self.get_plugin_properties_from_cps()
|
|
121
120
|
self.app, self.blueprints = self.create_flask_app()
|
|
122
121
|
|
|
122
|
+
if os.environ.get(OTEL_ENDPOINT):
|
|
123
|
+
self.config_options[OTEL_ENDPOINT] = os.environ[OTEL_ENDPOINT]
|
|
124
|
+
|
|
123
125
|
@staticmethod
|
|
124
126
|
def configure_structlog_instance(is_debug: bool) -> None:
|
|
125
127
|
structlog.configure(
|
|
@@ -166,6 +168,9 @@ class PluginServer(gunicorn.app.base.BaseApplication):
|
|
|
166
168
|
for key, value in config.items():
|
|
167
169
|
self.cfg.set(key.lower(), value)
|
|
168
170
|
|
|
171
|
+
post_fork = create_post_fork(lambda: self.app, lambda: self.plugin, lambda: self.config_options)
|
|
172
|
+
self.cfg.set("post_fork", post_fork)
|
|
173
|
+
|
|
169
174
|
def create_flask_app(self):
|
|
170
175
|
app = Flask(__name__)
|
|
171
176
|
|
|
@@ -193,7 +198,7 @@ class PluginServer(gunicorn.app.base.BaseApplication):
|
|
|
193
198
|
|
|
194
199
|
def get_plugin_properties_from_cps(self):
|
|
195
200
|
# Call out to komand-props to get configurations related to only the plugin pod running.
|
|
196
|
-
if is_running_in_cloud()
|
|
201
|
+
if is_running_in_cloud():
|
|
197
202
|
for attempt in range(1, CPS_RETRY + 1):
|
|
198
203
|
self.logger.info(
|
|
199
204
|
f"Getting plugin configuration information... (attempt {attempt}/{CPS_RETRY})"
|
|
@@ -206,7 +211,12 @@ class PluginServer(gunicorn.app.base.BaseApplication):
|
|
|
206
211
|
) # match how we name our images
|
|
207
212
|
plugin_config = resp_json.get("plugins", {}).get(plugin, {})
|
|
208
213
|
|
|
209
|
-
self.
|
|
214
|
+
if self.plugin.tasks:
|
|
215
|
+
self.config_options = plugin_config
|
|
216
|
+
|
|
217
|
+
if resp_json.get(OTEL_ENDPOINT, {}):
|
|
218
|
+
self.config_options[OTEL_ENDPOINT] = resp_json.get(OTEL_ENDPOINT, {})
|
|
219
|
+
|
|
210
220
|
self.logger.info("Plugin configuration successfully retrieved...")
|
|
211
221
|
return
|
|
212
222
|
except MissingSchema as missing_schema:
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
from typing import Any, Callable
|
|
3
|
+
from flask.app import Flask
|
|
4
|
+
|
|
5
|
+
from opentelemetry import trace
|
|
6
|
+
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
|
|
7
|
+
from opentelemetry.instrumentation.flask import FlaskInstrumentor
|
|
8
|
+
from opentelemetry.instrumentation.requests import RequestsInstrumentor
|
|
9
|
+
from opentelemetry.sdk.resources import Resource
|
|
10
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
11
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
12
|
+
from opentelemetry.trace import Status, StatusCode
|
|
13
|
+
|
|
14
|
+
from insightconnect_plugin_runtime.plugin import Plugin
|
|
15
|
+
from insightconnect_plugin_runtime.util import is_running_in_cloud, OTEL_ENDPOINT
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def init_tracing(app: Flask, plugin: Plugin, endpoint: str) -> None:
|
|
19
|
+
"""
|
|
20
|
+
Initialize OpenTelemetry Tracing
|
|
21
|
+
|
|
22
|
+
The function sets up the tracer provider, span processor and exporter with auto-instrumentation
|
|
23
|
+
|
|
24
|
+
:param app: The Flask Application
|
|
25
|
+
:param plugin: The plugin to derive the service name from
|
|
26
|
+
:param endpoint: The Otel Endpoint to emit traces to
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
if not is_running_in_cloud():
|
|
30
|
+
return
|
|
31
|
+
|
|
32
|
+
resource = Resource(attributes={"service.name": f'{plugin.name.lower().replace(" ", "_")}-{plugin.version}'})
|
|
33
|
+
|
|
34
|
+
trace_provider = TracerProvider(resource=resource)
|
|
35
|
+
exporter = OTLPSpanExporter(endpoint=endpoint)
|
|
36
|
+
trace_provider.add_span_processor(BatchSpanProcessor(exporter))
|
|
37
|
+
trace.set_tracer_provider(trace_provider)
|
|
38
|
+
|
|
39
|
+
FlaskInstrumentor().instrument_app(app)
|
|
40
|
+
|
|
41
|
+
def requests_callback(span: trace.Span, _: Any, response: Any) -> None:
|
|
42
|
+
if hasattr(response, "status_code"):
|
|
43
|
+
span.set_status(Status(StatusCode.OK if response.status_code < 400 else StatusCode.ERROR))
|
|
44
|
+
|
|
45
|
+
RequestsInstrumentor().instrument(trace_provider=trace_provider, response_hook=requests_callback)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def auto_instrument(func: Callable) -> Callable:
|
|
49
|
+
"""
|
|
50
|
+
Decorator that auto-instruments a function with a trace
|
|
51
|
+
|
|
52
|
+
:param func: function to instrument
|
|
53
|
+
:return:
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
@functools.wraps(func)
|
|
57
|
+
def wrapper(*args, **kwargs):
|
|
58
|
+
tracer = trace.get_tracer(__name__)
|
|
59
|
+
with tracer.start_as_current_span(func.__name__):
|
|
60
|
+
return func(*args, **kwargs)
|
|
61
|
+
|
|
62
|
+
return wrapper
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def create_post_fork(app_getter: Callable, plugin_getter: Callable, config_getter: Callable) -> Callable:
|
|
66
|
+
def post_fork(server, worker):
|
|
67
|
+
app = app_getter()
|
|
68
|
+
plugin = plugin_getter()
|
|
69
|
+
endpoint = config_getter().get(OTEL_ENDPOINT, None)
|
|
70
|
+
if endpoint:
|
|
71
|
+
init_tracing(app, plugin, endpoint)
|
|
72
|
+
|
|
73
|
+
return post_fork
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: insightconnect-plugin-runtime
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.3.1
|
|
4
4
|
Summary: InsightConnect Plugin Runtime
|
|
5
5
|
Home-page: https://github.com/rapid7/komand-plugin-sdk-python
|
|
6
6
|
Author: Rapid7 Integrations Alliance
|
|
@@ -26,6 +26,11 @@ Requires-Dist: apispec-webframeworks==1.0.0
|
|
|
26
26
|
Requires-Dist: blinker==1.9.0
|
|
27
27
|
Requires-Dist: structlog==24.4.0
|
|
28
28
|
Requires-Dist: python-json-logger==2.0.7
|
|
29
|
+
Requires-Dist: Jinja2==3.1.6
|
|
30
|
+
Requires-Dist: opentelemetry-sdk==1.31.1
|
|
31
|
+
Requires-Dist: opentelemetry-instrumentation-flask==0.52b1
|
|
32
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http==1.31.1
|
|
33
|
+
Requires-Dist: opentelemetry-instrumentation-requests==0.52b1
|
|
29
34
|
Dynamic: author
|
|
30
35
|
Dynamic: author-email
|
|
31
36
|
Dynamic: classifier
|
|
@@ -219,6 +224,8 @@ contributed. Black is installed as a test dependency and the hook can be initial
|
|
|
219
224
|
after cloning this repository.
|
|
220
225
|
|
|
221
226
|
## Changelog
|
|
227
|
+
* 6.3.1 - Improved filtering for `custom_config` parameters for plugin tasks
|
|
228
|
+
* 6.3.0 - Add Tracing Instrumentation
|
|
222
229
|
* 6.2.6 - Remove setuptools after installation
|
|
223
230
|
* 6.2.5 - Fixed bug related to failure to set default region to assume role method in `aws_client` for newer versions of boto3 | Updated alpine image packages on build
|
|
224
231
|
* 6.2.4 - Update `make_request` helper to support extra parameter of `max_response_size` to cap the response
|
|
@@ -15,6 +15,7 @@ insightconnect_plugin_runtime/schema.py
|
|
|
15
15
|
insightconnect_plugin_runtime/server.py
|
|
16
16
|
insightconnect_plugin_runtime/step.py
|
|
17
17
|
insightconnect_plugin_runtime/task.py
|
|
18
|
+
insightconnect_plugin_runtime/telemetry.py
|
|
18
19
|
insightconnect_plugin_runtime/trigger.py
|
|
19
20
|
insightconnect_plugin_runtime/util.py
|
|
20
21
|
insightconnect_plugin_runtime/variables.py
|
|
@@ -12,3 +12,8 @@ apispec-webframeworks==1.0.0
|
|
|
12
12
|
blinker==1.9.0
|
|
13
13
|
structlog==24.4.0
|
|
14
14
|
python-json-logger==2.0.7
|
|
15
|
+
Jinja2==3.1.6
|
|
16
|
+
opentelemetry-sdk==1.31.1
|
|
17
|
+
opentelemetry-instrumentation-flask==0.52b1
|
|
18
|
+
opentelemetry-exporter-otlp-proto-http==1.31.1
|
|
19
|
+
opentelemetry-instrumentation-requests==0.52b1
|
|
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name="insightconnect-plugin-runtime",
|
|
8
|
-
version="6.
|
|
8
|
+
version="6.3.1",
|
|
9
9
|
description="InsightConnect Plugin Runtime",
|
|
10
10
|
long_description=long_description,
|
|
11
11
|
long_description_content_type="text/markdown",
|
|
@@ -28,6 +28,11 @@ setup(
|
|
|
28
28
|
"blinker==1.9.0",
|
|
29
29
|
"structlog==24.4.0",
|
|
30
30
|
"python-json-logger==2.0.7",
|
|
31
|
+
"Jinja2==3.1.6",
|
|
32
|
+
"opentelemetry-sdk==1.31.1",
|
|
33
|
+
"opentelemetry-instrumentation-flask==0.52b1",
|
|
34
|
+
"opentelemetry-exporter-otlp-proto-http==1.31.1",
|
|
35
|
+
"opentelemetry-instrumentation-requests==0.52b1",
|
|
31
36
|
],
|
|
32
37
|
tests_require=[
|
|
33
38
|
"pytest",
|
|
@@ -1,11 +1,42 @@
|
|
|
1
|
-
import unittest
|
|
2
1
|
import json
|
|
2
|
+
import unittest
|
|
3
|
+
from typing import Any, Dict
|
|
3
4
|
|
|
4
|
-
from insightconnect_plugin_runtime.api.endpoints import Endpoints
|
|
5
|
-
from insightconnect_plugin_runtime.plugin import Plugin
|
|
6
|
-
from insightconnect_plugin_runtime.action import Action
|
|
7
5
|
from insightconnect_plugin_runtime import Input
|
|
6
|
+
from insightconnect_plugin_runtime.action import Action
|
|
7
|
+
from insightconnect_plugin_runtime.api.endpoints import Endpoints
|
|
8
8
|
from insightconnect_plugin_runtime.connection import Connection
|
|
9
|
+
from insightconnect_plugin_runtime.plugin import Plugin
|
|
10
|
+
from insightconnect_plugin_runtime.task import Task
|
|
11
|
+
from parameterized import parameterized
|
|
12
|
+
|
|
13
|
+
MOCKED_CONFIG = {
|
|
14
|
+
"*": {
|
|
15
|
+
"first_property": "first_property_global",
|
|
16
|
+
"second_property": "second_property_global",
|
|
17
|
+
"task_name_1": {"second_property": "second_property_global_task_name_1"},
|
|
18
|
+
},
|
|
19
|
+
"org_1": {
|
|
20
|
+
"first_property": "first_property_org_1",
|
|
21
|
+
"11111111-1111-1111-1111-111111111111": {
|
|
22
|
+
"first_property": "first_property_org_1_11111111-1111-1111-1111-111111111111"
|
|
23
|
+
},
|
|
24
|
+
"task_name_2": {"second_property": "second_property_task_name_2"},
|
|
25
|
+
"task_name_3": {
|
|
26
|
+
"first_property": "first_property_task_name_3",
|
|
27
|
+
"second_property": "second_property_task_name_3",
|
|
28
|
+
},
|
|
29
|
+
"22222222-2222-2222-2222-222222222222": {
|
|
30
|
+
"first_property": "first_property_org_1_22222222-2222-2222-2222-222222222222",
|
|
31
|
+
"second_property": "second_property_org_1_22222222-2222-2222-2222-222222222222",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
"org_2": {
|
|
35
|
+
"first_property": "first_property_org_2",
|
|
36
|
+
"second_property": "second_property_org_2",
|
|
37
|
+
"task_name_1": {"first_property": "first_property_org_1_task_name_1"},
|
|
38
|
+
},
|
|
39
|
+
}
|
|
9
40
|
|
|
10
41
|
|
|
11
42
|
class TestDefinitionsAllActions(unittest.TestCase):
|
|
@@ -18,6 +49,7 @@ class TestDefinitionsAllActions(unittest.TestCase):
|
|
|
18
49
|
workers=None,
|
|
19
50
|
threads=None,
|
|
20
51
|
master_pid=None,
|
|
52
|
+
config_options=MOCKED_CONFIG,
|
|
21
53
|
)
|
|
22
54
|
|
|
23
55
|
plugin = Plugin(
|
|
@@ -28,6 +60,11 @@ class TestDefinitionsAllActions(unittest.TestCase):
|
|
|
28
60
|
connection=Connection(input=None),
|
|
29
61
|
)
|
|
30
62
|
|
|
63
|
+
# Add example tasks
|
|
64
|
+
for task in ("task_name_1", "task_name_2", "task_name_3"):
|
|
65
|
+
plugin.add_task(
|
|
66
|
+
Task(name=task, description="Test", input=None, output=None)
|
|
67
|
+
)
|
|
31
68
|
self.endpoints.plugin = plugin
|
|
32
69
|
|
|
33
70
|
def test_input_good(self):
|
|
@@ -213,3 +250,106 @@ class TestDefinitionsAllActions(unittest.TestCase):
|
|
|
213
250
|
actual = self.endpoints._create_action_definitions_payload()
|
|
214
251
|
|
|
215
252
|
self.assertNotEqual(expected, actual)
|
|
253
|
+
|
|
254
|
+
@parameterized.expand(
|
|
255
|
+
[
|
|
256
|
+
(
|
|
257
|
+
"",
|
|
258
|
+
"",
|
|
259
|
+
"no_task_in_properties",
|
|
260
|
+
{
|
|
261
|
+
"first_property": "first_property_global",
|
|
262
|
+
"second_property": "second_property_global",
|
|
263
|
+
},
|
|
264
|
+
),
|
|
265
|
+
(
|
|
266
|
+
"",
|
|
267
|
+
"",
|
|
268
|
+
"task_name_1",
|
|
269
|
+
{
|
|
270
|
+
"first_property": "first_property_global",
|
|
271
|
+
"second_property": "second_property_global_task_name_1",
|
|
272
|
+
},
|
|
273
|
+
),
|
|
274
|
+
(
|
|
275
|
+
"org_1",
|
|
276
|
+
"",
|
|
277
|
+
"no_task_in_properties",
|
|
278
|
+
{
|
|
279
|
+
"first_property": "first_property_org_1",
|
|
280
|
+
"second_property": "second_property_global",
|
|
281
|
+
},
|
|
282
|
+
),
|
|
283
|
+
(
|
|
284
|
+
"org_1",
|
|
285
|
+
"11111111-1111-1111-1111-111111111111",
|
|
286
|
+
"no_task_in_properties",
|
|
287
|
+
{
|
|
288
|
+
"first_property": "first_property_org_1_11111111-1111-1111-1111-111111111111",
|
|
289
|
+
"second_property": "second_property_global",
|
|
290
|
+
},
|
|
291
|
+
),
|
|
292
|
+
(
|
|
293
|
+
"org_1",
|
|
294
|
+
"11111111-1111-1111-1111-111111111111",
|
|
295
|
+
"task_name_2",
|
|
296
|
+
{
|
|
297
|
+
"first_property": "first_property_org_1_11111111-1111-1111-1111-111111111111",
|
|
298
|
+
"second_property": "second_property_task_name_2",
|
|
299
|
+
},
|
|
300
|
+
),
|
|
301
|
+
(
|
|
302
|
+
"org_1",
|
|
303
|
+
"11111111-1111-1111-1111-111111111111",
|
|
304
|
+
"task_name_3",
|
|
305
|
+
{
|
|
306
|
+
"first_property": "first_property_org_1_11111111-1111-1111-1111-111111111111",
|
|
307
|
+
"second_property": "second_property_task_name_3",
|
|
308
|
+
},
|
|
309
|
+
),
|
|
310
|
+
(
|
|
311
|
+
"org_1",
|
|
312
|
+
"22222222-2222-2222-2222-222222222222",
|
|
313
|
+
"no_task_in_properties",
|
|
314
|
+
{
|
|
315
|
+
"first_property": "first_property_org_1_22222222-2222-2222-2222-222222222222",
|
|
316
|
+
"second_property": "second_property_org_1_22222222-2222-2222-2222-222222222222",
|
|
317
|
+
},
|
|
318
|
+
),
|
|
319
|
+
(
|
|
320
|
+
"org_1",
|
|
321
|
+
"22222222-2222-2222-2222-222222222222",
|
|
322
|
+
"task_name_2",
|
|
323
|
+
{
|
|
324
|
+
"first_property": "first_property_org_1_22222222-2222-2222-2222-222222222222",
|
|
325
|
+
"second_property": "second_property_org_1_22222222-2222-2222-2222-222222222222",
|
|
326
|
+
},
|
|
327
|
+
),
|
|
328
|
+
(
|
|
329
|
+
"org_2",
|
|
330
|
+
"",
|
|
331
|
+
"",
|
|
332
|
+
{
|
|
333
|
+
"first_property": "first_property_org_2",
|
|
334
|
+
"second_property": "second_property_org_2",
|
|
335
|
+
},
|
|
336
|
+
),
|
|
337
|
+
(
|
|
338
|
+
"org_2",
|
|
339
|
+
"",
|
|
340
|
+
"task_name_1",
|
|
341
|
+
{
|
|
342
|
+
"first_property": "first_property_org_1_task_name_1",
|
|
343
|
+
"second_property": "second_property_org_2",
|
|
344
|
+
},
|
|
345
|
+
),
|
|
346
|
+
]
|
|
347
|
+
)
|
|
348
|
+
def test_add_plugin_custom_config(
|
|
349
|
+
self, org_id: str, int_id: str, task_name: str, expected: Dict[str, Any]
|
|
350
|
+
) -> None:
|
|
351
|
+
response = self.endpoints.add_plugin_custom_config(
|
|
352
|
+
{"body": {}}, org_id, int_id, task_name
|
|
353
|
+
)
|
|
354
|
+
custom_config = response.get("body", {}).get("custom_config", {})
|
|
355
|
+
self.assertEqual(custom_config, expected)
|
|
@@ -4,6 +4,7 @@ from unittest import TestCase, skip
|
|
|
4
4
|
from unittest.mock import patch, MagicMock
|
|
5
5
|
|
|
6
6
|
from insightconnect_plugin_runtime.server import PluginServer
|
|
7
|
+
from insightconnect_plugin_runtime.util import OTEL_ENDPOINT
|
|
7
8
|
from tests.plugin.hello_world import KomandHelloWorld
|
|
8
9
|
from .utils import MockResponse, Logger
|
|
9
10
|
|
|
@@ -20,15 +21,19 @@ class TestServerCloudPlugins(TestCase):
|
|
|
20
21
|
@parameterized.expand([["Set cloud to false", False], ["Set cloud to true", True]])
|
|
21
22
|
@patch("insightconnect_plugin_runtime.server.request_get")
|
|
22
23
|
def test_cloud_plugin_no_tasks_ignore_cps(self, _test_name, cloud, mocked_req, mock_cloud, _run):
|
|
24
|
+
fake_endpoint = "http://fake.endpoint.com"
|
|
25
|
+
mocked_req.return_value = MockResponse({OTEL_ENDPOINT: fake_endpoint}) if cloud else MockResponse({})
|
|
23
26
|
mock_cloud.return_value = cloud # Mock plugin running in cloud vs not
|
|
24
27
|
self.plugin.tasks = None # ensure still no tasks as other tests edit this and could fail before reverting
|
|
25
|
-
plugin_server = PluginServer(self.plugin) # this plugin has no tasks by default
|
|
26
28
|
|
|
29
|
+
plugin_server = PluginServer(self.plugin) # this plugin has no tasks by default
|
|
27
30
|
plugin_server.start()
|
|
28
|
-
self.assertEqual(plugin_server.config_options, {})
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
self.assertEqual(plugin_server.config_options, {OTEL_ENDPOINT: fake_endpoint} if cloud else {})
|
|
33
|
+
|
|
34
|
+
# Plugin server calls out to CPS when cloud to get tracing endpoint
|
|
35
|
+
self.assertEqual(mocked_req.called, cloud)
|
|
36
|
+
|
|
32
37
|
|
|
33
38
|
@patch("insightconnect_plugin_runtime.server.request_get")
|
|
34
39
|
def test_cloud_plugin_calls_cps(self, mocked_req, _mock_cloud, _run):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/__init__.py
RENAMED
|
File without changes
|
{insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/plugin/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/test_api.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/test_oauth.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{insightconnect_plugin_runtime-6.2.6 → insightconnect_plugin_runtime-6.3.1}/tests/unit/utils.py
RENAMED
|
File without changes
|