stoobly-agent 0.33.7__py3-none-any.whl → 0.34.0__py3-none-any.whl
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.
- stoobly_agent/__init__.py +1 -1
- stoobly_agent/app/cli/endpoint_cli.py +24 -1
- stoobly_agent/app/cli/helpers/endpoint_facade.py +22 -1
- stoobly_agent/app/cli/helpers/endpoints_import_context.py +57 -0
- stoobly_agent/app/cli/helpers/endpoints_import_service.py +147 -0
- stoobly_agent/app/cli/helpers/openapi_endpoint_adapter.py +111 -6
- stoobly_agent/app/models/types/endpoint.py +28 -2
- stoobly_agent/app/settings/intercept_settings.py +1 -1
- stoobly_agent/lib/api/api.py +4 -0
- stoobly_agent/lib/api/body_param_names_resource.py +36 -0
- stoobly_agent/lib/api/endpoints_resource.py +9 -2
- stoobly_agent/lib/api/header_names_resource.py +36 -0
- stoobly_agent/lib/api/interfaces/endpoints.py +2 -0
- stoobly_agent/lib/api/query_param_names_resource.py +36 -0
- stoobly_agent/lib/api/response_header_names_resource.py +36 -0
- stoobly_agent/lib/api/response_param_names_resource.py +36 -0
- stoobly_agent/public/0-es2015.a7e60cafc0868f87a771.js +1 -0
- stoobly_agent/public/0-es5.a7e60cafc0868f87a771.js +1 -0
- stoobly_agent/public/1-es2015.cb071776436f10954db5.js +1 -0
- stoobly_agent/public/1-es5.cb071776436f10954db5.js +1 -0
- stoobly_agent/public/10-es2015.bb1702aaf3968a2cb521.js +1 -0
- stoobly_agent/public/10-es5.bb1702aaf3968a2cb521.js +1 -0
- stoobly_agent/public/12-es2015.591ec692afb8f8d13842.js +1 -0
- stoobly_agent/public/12-es5.591ec692afb8f8d13842.js +1 -0
- stoobly_agent/public/13-es2015.f381e7d6ff361b669e12.js +1 -0
- stoobly_agent/public/13-es5.f381e7d6ff361b669e12.js +1 -0
- stoobly_agent/public/14-es2015.1ffb225a16d6292dbddd.js +1 -0
- stoobly_agent/public/14-es5.1ffb225a16d6292dbddd.js +1 -0
- stoobly_agent/public/15-es2015.2cf39bcaeb0ea2c52297.js +1 -0
- stoobly_agent/public/15-es5.2cf39bcaeb0ea2c52297.js +1 -0
- stoobly_agent/public/16-es2015.0e9422b274e642f95e41.js +1 -0
- stoobly_agent/public/16-es5.0e9422b274e642f95e41.js +1 -0
- stoobly_agent/public/17-es2015.7fb08367a22d1e34aed7.js +1 -0
- stoobly_agent/public/17-es5.7fb08367a22d1e34aed7.js +1 -0
- stoobly_agent/public/18-es2015.5caa4789d1c335e628f2.js +1 -0
- stoobly_agent/public/18-es5.5caa4789d1c335e628f2.js +1 -0
- stoobly_agent/public/19-es2015.8049aef58c329c500f9b.js +1 -0
- stoobly_agent/public/19-es5.8049aef58c329c500f9b.js +1 -0
- stoobly_agent/public/2-es2015.8f184ac63348ba447b1f.js +1 -0
- stoobly_agent/public/2-es5.8f184ac63348ba447b1f.js +1 -0
- stoobly_agent/public/20-es2015.473486aabfa4d4a6431b.js +1 -0
- stoobly_agent/public/20-es5.473486aabfa4d4a6431b.js +1 -0
- stoobly_agent/public/21-es2015.63ed4e6b242fbc047bd6.js +1 -0
- stoobly_agent/public/21-es5.63ed4e6b242fbc047bd6.js +1 -0
- stoobly_agent/public/22-es2015.df183804415330639987.js +1 -0
- stoobly_agent/public/22-es5.df183804415330639987.js +1 -0
- stoobly_agent/public/23-es2015.0da63b056fabde91bb0b.js +1 -0
- stoobly_agent/public/23-es5.0da63b056fabde91bb0b.js +1 -0
- stoobly_agent/public/28-es2015.9fe030e9d3b0e52239aa.js +1 -0
- stoobly_agent/public/28-es5.9fe030e9d3b0e52239aa.js +1 -0
- stoobly_agent/public/29-es2015.9b440f22de725732e5ab.js +1 -0
- stoobly_agent/public/29-es5.9b440f22de725732e5ab.js +1 -0
- stoobly_agent/public/30-es2015.6ad2a5126b0a27c1e7c6.js +1 -0
- stoobly_agent/public/30-es5.6ad2a5126b0a27c1e7c6.js +1 -0
- stoobly_agent/public/31-es2015.f4291150f35d54ff19ca.js +1 -0
- stoobly_agent/public/31-es5.f4291150f35d54ff19ca.js +1 -0
- stoobly_agent/public/32-es2015.c8f6ccb43bdba0adf199.js +1 -0
- stoobly_agent/public/32-es5.c8f6ccb43bdba0adf199.js +1 -0
- stoobly_agent/public/33-es2015.f985e93402ebf86322ef.js +1 -0
- stoobly_agent/public/33-es5.f985e93402ebf86322ef.js +1 -0
- stoobly_agent/public/34-es2015.0e1961fb3cf649a52d49.js +1 -0
- stoobly_agent/public/34-es5.0e1961fb3cf649a52d49.js +1 -0
- stoobly_agent/public/35-es2015.a4ae56a89c0324397624.js +1 -0
- stoobly_agent/public/35-es5.a4ae56a89c0324397624.js +1 -0
- stoobly_agent/public/36-es2015.b8fdd25590a79c820119.js +1 -0
- stoobly_agent/public/36-es5.b8fdd25590a79c820119.js +1 -0
- stoobly_agent/public/37-es2015.6567a0ce4cf87ad7287b.js +1 -0
- stoobly_agent/public/37-es5.6567a0ce4cf87ad7287b.js +1 -0
- stoobly_agent/public/38-es2015.6f6d751bff41d84d727a.js +1 -0
- stoobly_agent/public/38-es5.6f6d751bff41d84d727a.js +1 -0
- stoobly_agent/public/39-es2015.47f63177e7d4509a22fa.js +1 -0
- stoobly_agent/public/39-es5.47f63177e7d4509a22fa.js +1 -0
- stoobly_agent/public/3rdpartylicenses.txt +2418 -0
- stoobly_agent/public/4-es2015.182e1ce1811ef67571fb.js +1 -0
- stoobly_agent/public/4-es5.182e1ce1811ef67571fb.js +1 -0
- stoobly_agent/public/40-es2015.5333067cdc4077c7495a.js +1 -0
- stoobly_agent/public/40-es5.5333067cdc4077c7495a.js +1 -0
- stoobly_agent/public/41-es2015.7a2434380c81c11ff2c5.js +1 -0
- stoobly_agent/public/41-es5.7a2434380c81c11ff2c5.js +1 -0
- stoobly_agent/public/42-es2015.5dde662fe1e3b4e4bdd1.js +1 -0
- stoobly_agent/public/42-es5.5dde662fe1e3b4e4bdd1.js +1 -0
- stoobly_agent/public/43-es2015.608e917d689b9bb762cb.js +1 -0
- stoobly_agent/public/43-es5.608e917d689b9bb762cb.js +1 -0
- stoobly_agent/public/44-es2015.2ae5fea15b5e8c2681d3.js +1 -0
- stoobly_agent/public/44-es5.2ae5fea15b5e8c2681d3.js +1 -0
- stoobly_agent/public/45-es2015.e46f228c795174428515.js +1 -0
- stoobly_agent/public/45-es5.e46f228c795174428515.js +1 -0
- stoobly_agent/public/46-es2015.22a0d8e0b4bbfb513741.js +1 -0
- stoobly_agent/public/46-es5.22a0d8e0b4bbfb513741.js +1 -0
- stoobly_agent/public/47-es2015.3878e5d1d692107748f3.js +1 -0
- stoobly_agent/public/47-es5.3878e5d1d692107748f3.js +1 -0
- stoobly_agent/public/5-es2015.aba7173be56fc19b4b6f.js +1 -0
- stoobly_agent/public/5-es5.aba7173be56fc19b4b6f.js +1 -0
- stoobly_agent/public/6-es2015.5fb726c0555664300974.js +1 -0
- stoobly_agent/public/6-es5.5fb726c0555664300974.js +1 -0
- stoobly_agent/public/7-es2015.9b9ab4adf24d13bdc2f8.js +1 -0
- stoobly_agent/public/7-es5.9b9ab4adf24d13bdc2f8.js +1 -0
- stoobly_agent/public/8-es2015.cdd7dce2a24aaf9d974f.js +1 -0
- stoobly_agent/public/8-es5.cdd7dce2a24aaf9d974f.js +1 -0
- stoobly_agent/public/9-es2015.cdde98f2537997afbf0f.js +1 -0
- stoobly_agent/public/9-es5.cdde98f2537997afbf0f.js +1 -0
- stoobly_agent/public/CHANGELOG.md +58 -0
- stoobly_agent/public/README.md +264 -0
- stoobly_agent/public/_redirects +1 -0
- stoobly_agent/public/assets/img/demo/1.jpg +0 -0
- stoobly_agent/public/assets/img/demo/2.jpg +0 -0
- stoobly_agent/public/assets/img/demo/3.jpg +0 -0
- stoobly_agent/public/assets/img/demo/4.jpg +0 -0
- stoobly_agent/public/assets/img/demo/5.jpg +0 -0
- stoobly_agent/public/assets/img/demo/6.jpg +0 -0
- stoobly_agent/public/assets/img/demo/7.jpg +0 -0
- stoobly_agent/public/assets/img/demo/8.jpg +0 -0
- stoobly_agent/public/assets/img/demo/landscape.jpg +0 -0
- stoobly_agent/public/assets/img/demo/mountain-cinematic.jpg +0 -0
- stoobly_agent/public/assets/img/illustrations/checklist.svg +164 -0
- stoobly_agent/public/assets/img/illustrations/data_center.svg +150 -0
- stoobly_agent/public/assets/img/illustrations/idea.svg +213 -0
- stoobly_agent/public/assets/img/illustrations/it_support.svg +168 -0
- stoobly_agent/public/assets/img/illustrations/peak_mountain_3.svg +262 -0
- stoobly_agent/public/assets/img/illustrations/under_constructions_1.svg +282 -0
- stoobly_agent/public/assets/img/logo/colored.png +0 -0
- stoobly_agent/public/assets/img/logo/colored.svg +9 -0
- stoobly_agent/public/assets/img/logo/white.png +0 -0
- stoobly_agent/public/assets/img/logo/white.svg +8 -0
- stoobly_agent/public/common-es2015.6f230354b12587f9be81.js +1 -0
- stoobly_agent/public/common-es5.6f230354b12587f9be81.js +1 -0
- stoobly_agent/public/favicon.ico +0 -0
- stoobly_agent/public/index.html +118 -0
- stoobly_agent/public/main-es2015.081bbd2709f22e95933e.js +1 -0
- stoobly_agent/public/main-es5.081bbd2709f22e95933e.js +1 -0
- stoobly_agent/public/polyfills-es2015.8ce2adc69f283f6c4c5e.js +1 -0
- stoobly_agent/public/polyfills-es5.7530172ddcec11a10eb3.js +1 -0
- stoobly_agent/public/runtime-es2015.362e49d383fb724f5414.js +1 -0
- stoobly_agent/public/runtime-es5.362e49d383fb724f5414.js +1 -0
- stoobly_agent/public/styles.ca104d947fbb2eebbeca.css +6 -0
- stoobly_agent/test/app/cli/helpers/openapi_endpoint_adapter_additional_props_test.py +34 -0
- stoobly_agent/test/app/cli/helpers/openapi_endpoint_adapter_missing_info_test.py +80 -3
- stoobly_agent/test/app/cli/helpers/openapi_endpoint_adapter_missing_oauth2_scopes_test.py +82 -1
- stoobly_agent/test/app/cli/helpers/openapi_endpoint_adapter_missing_servers_test.py +80 -3
- stoobly_agent/test/app/cli/helpers/openapi_endpoint_adapter_test.py +617 -4
- {stoobly_agent-0.33.7.dist-info → stoobly_agent-0.34.0.dist-info}/METADATA +1 -1
- {stoobly_agent-0.33.7.dist-info → stoobly_agent-0.34.0.dist-info}/RECORD +145 -19
- {stoobly_agent-0.33.7.dist-info → stoobly_agent-0.34.0.dist-info}/LICENSE +0 -0
- {stoobly_agent-0.33.7.dist-info → stoobly_agent-0.34.0.dist-info}/WHEEL +0 -0
- {stoobly_agent-0.33.7.dist-info → stoobly_agent-0.34.0.dist-info}/entry_points.txt +0 -0
stoobly_agent/__init__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
COMMAND = 'stoobly-agent'
|
2
|
-
VERSION = '0.
|
2
|
+
VERSION = '0.34.0'
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import click
|
1
|
+
import click, sys
|
2
2
|
|
3
3
|
from stoobly_agent.app.models.types import OPENAPI_FORMAT
|
4
4
|
from stoobly_agent.app.settings import Settings
|
@@ -7,6 +7,7 @@ from stoobly_agent.lib.utils.conditional_decorator import ConditionalDecorator
|
|
7
7
|
|
8
8
|
from .helpers.endpoint_facade import EndpointFacade
|
9
9
|
from .helpers.endpoints_apply_context import EndpointsApplyContext
|
10
|
+
from .helpers.endpoints_import_context import EndpointsImportContext
|
10
11
|
from .helpers.feature_flags import local, remote
|
11
12
|
from .helpers.validations import validate_project_key, validate_scenario_key
|
12
13
|
|
@@ -54,3 +55,25 @@ def apply(**kwargs):
|
|
54
55
|
|
55
56
|
facade = EndpointFacade(settings)
|
56
57
|
facade.apply(context)
|
58
|
+
|
59
|
+
@endpoint.command(
|
60
|
+
"import",
|
61
|
+
help="Import endpoints"
|
62
|
+
)
|
63
|
+
@click.option('--source-format', required=True, type=click.Choice([OPENAPI_FORMAT]), help="Spec file format.")
|
64
|
+
@click.option('--source-path', help='Path to spec file.')
|
65
|
+
def import_endpoint(**kwargs):
|
66
|
+
context = EndpointsImportContext()
|
67
|
+
|
68
|
+
project_key = settings.proxy.intercept.project_key
|
69
|
+
if project_key:
|
70
|
+
project_key = validate_project_key(project_key)
|
71
|
+
context.with_project(project_key.id)
|
72
|
+
|
73
|
+
context.with_source(kwargs.get('source_path'), kwargs.get('source_format'))
|
74
|
+
|
75
|
+
endpoint_handler = lambda endpoint: print(f"{bcolors.OKBLUE}Importing Endpoint: {endpoint['method']} {endpoint['path']}{bcolors.ENDC}")
|
76
|
+
context.with_endpoint_handler(endpoint_handler)
|
77
|
+
|
78
|
+
facade = EndpointFacade(settings)
|
79
|
+
facade.import_endpoints(context)
|
@@ -2,9 +2,17 @@ import pdb
|
|
2
2
|
|
3
3
|
from stoobly_agent.app.models.factories.resource.request import RequestResourceFactory
|
4
4
|
from stoobly_agent.app.settings import Settings
|
5
|
+
from stoobly_agent.lib.api.endpoints_resource import EndpointsResource
|
6
|
+
from stoobly_agent.lib.api.header_names_resource import HeaderNamesResource
|
7
|
+
from stoobly_agent.lib.api.body_param_names_resource import BodyParamNamesResource
|
8
|
+
from stoobly_agent.lib.api.query_param_names_resource import QueryParamNamesResource
|
9
|
+
from stoobly_agent.lib.api.response_param_names_resource import ResponseParamNamesResource
|
10
|
+
from stoobly_agent.lib.api.response_header_names_resource import ResponseHeaderNamesResource
|
5
11
|
|
6
12
|
from .endpoints_apply_context import EndpointsApplyContext
|
13
|
+
from .endpoints_import_context import EndpointsImportContext
|
7
14
|
from .endpoints_apply_service import apply_endpoints
|
15
|
+
from .endpoints_import_service import import_endpoints
|
8
16
|
from .synchronize_request_service import SynchronizeRequestService
|
9
17
|
|
10
18
|
class EndpointFacade():
|
@@ -22,4 +30,17 @@ class EndpointFacade():
|
|
22
30
|
)
|
23
31
|
context.with_request_handler(request_handler)
|
24
32
|
|
25
|
-
apply_endpoints(context)
|
33
|
+
apply_endpoints(context)
|
34
|
+
|
35
|
+
def import_endpoints(self, context: EndpointsImportContext):
|
36
|
+
api_url = self.__settings.remote.api_url
|
37
|
+
api_key = self.__settings.remote.api_key
|
38
|
+
|
39
|
+
context.with_endpoint_resource(EndpointsResource(api_url, api_key))
|
40
|
+
context.with_header_name_resource(HeaderNamesResource(api_url, api_key))
|
41
|
+
context.with_body_param_name_resource(BodyParamNamesResource(api_url, api_key))
|
42
|
+
context.with_query_param_name_resource(QueryParamNamesResource(api_url, api_key))
|
43
|
+
context.with_response_param_name_resource(ResponseParamNamesResource(api_url, api_key))
|
44
|
+
context.with_response_header_name_resource(ResponseHeaderNamesResource(api_url, api_key))
|
45
|
+
|
46
|
+
import_endpoints(context)
|
@@ -0,0 +1,57 @@
|
|
1
|
+
from typing import Callable, TypedDict
|
2
|
+
|
3
|
+
from .openapi_endpoint_adapter import OpenApiEndpointAdapter
|
4
|
+
from stoobly_agent.app.models.types import OPENAPI_FORMAT
|
5
|
+
from stoobly_agent.lib.api.body_param_names_resource import BodyParamNamesResource
|
6
|
+
from stoobly_agent.lib.api.endpoints_resource import EndpointsResource
|
7
|
+
from stoobly_agent.lib.api.header_names_resource import HeaderNamesResource
|
8
|
+
from stoobly_agent.lib.api.interfaces.endpoints import EndpointShowResponse
|
9
|
+
from stoobly_agent.lib.api.query_param_names_resource import QueryParamNamesResource
|
10
|
+
from stoobly_agent.lib.api.response_param_names_resource import ResponseParamNamesResource
|
11
|
+
from stoobly_agent.lib.api.response_header_names_resource import ResponseHeaderNamesResource
|
12
|
+
|
13
|
+
class EndpointsImportContext:
|
14
|
+
def __init__(self):
|
15
|
+
self.endpoints = []
|
16
|
+
self.endpoint_handlers = []
|
17
|
+
self.resources = {}
|
18
|
+
self.project_id = None
|
19
|
+
|
20
|
+
def with_endpoint_handler(self, handler: Callable[[EndpointShowResponse], None]):
|
21
|
+
self.endpoint_handlers.append(handler)
|
22
|
+
return self
|
23
|
+
|
24
|
+
def with_project(self, project_id: int):
|
25
|
+
self.project_id = project_id
|
26
|
+
return self
|
27
|
+
|
28
|
+
def with_endpoint_resource(self, resource: EndpointsResource):
|
29
|
+
self.resources['endpoint'] = resource
|
30
|
+
return self
|
31
|
+
|
32
|
+
def with_header_name_resource(self, resource: HeaderNamesResource):
|
33
|
+
self.resources['header_name'] = resource
|
34
|
+
return self
|
35
|
+
|
36
|
+
def with_body_param_name_resource(self, resource: BodyParamNamesResource):
|
37
|
+
self.resources['body_param_name'] = resource
|
38
|
+
return self
|
39
|
+
|
40
|
+
def with_query_param_name_resource(self, resource: QueryParamNamesResource):
|
41
|
+
self.resources['query_param_name'] = resource
|
42
|
+
return self
|
43
|
+
|
44
|
+
def with_response_param_name_resource(self, resource: ResponseParamNamesResource):
|
45
|
+
self.resources['response_param_name'] = resource
|
46
|
+
return self
|
47
|
+
|
48
|
+
def with_response_header_name_resource(self, resource: ResponseHeaderNamesResource):
|
49
|
+
self.resources['response_header_name'] = resource
|
50
|
+
return self
|
51
|
+
|
52
|
+
def with_source(self, path: str, format: str):
|
53
|
+
if format == OPENAPI_FORMAT:
|
54
|
+
endpoint_adapter = OpenApiEndpointAdapter()
|
55
|
+
self.endpoints += endpoint_adapter.adapt_from_file(path)
|
56
|
+
|
57
|
+
return self
|
@@ -0,0 +1,147 @@
|
|
1
|
+
import json
|
2
|
+
import requests
|
3
|
+
import sys
|
4
|
+
from typing import Dict
|
5
|
+
|
6
|
+
from .endpoints_import_context import EndpointsImportContext
|
7
|
+
from stoobly_agent.app.models.types import ENDPOINT_COMPONENT_NAMES
|
8
|
+
from stoobly_agent.lib.api.body_param_names_resource import BodyParamNamesResource
|
9
|
+
from stoobly_agent.lib.api.endpoints_resource import EndpointsResource
|
10
|
+
from stoobly_agent.lib.api.header_names_resource import HeaderNamesResource
|
11
|
+
from stoobly_agent.lib.api.interfaces.endpoints import BodyParamName
|
12
|
+
from stoobly_agent.lib.api.interfaces.endpoints import EndpointShowResponse
|
13
|
+
from stoobly_agent.lib.api.interfaces.endpoints import RequestComponentName
|
14
|
+
from stoobly_agent.lib.api.query_param_names_resource import QueryParamNamesResource
|
15
|
+
from stoobly_agent.lib.api.response_header_names_resource import ResponseHeaderNamesResource
|
16
|
+
from stoobly_agent.lib.api.response_param_names_resource import ResponseParamNamesResource
|
17
|
+
from stoobly_agent.lib.logger import bcolors
|
18
|
+
|
19
|
+
def import_endpoints(context: EndpointsImportContext):
|
20
|
+
for endpoint in context.endpoints:
|
21
|
+
for endpoint_handler in context.endpoint_handlers:
|
22
|
+
endpoint_handler(endpoint)
|
23
|
+
|
24
|
+
try:
|
25
|
+
res = import_endpoint(context.project_id, context.resources['endpoint'], endpoint)
|
26
|
+
except requests.HTTPError as e:
|
27
|
+
error_handler(endpoint, e)
|
28
|
+
return
|
29
|
+
|
30
|
+
if res.status_code == 409: # Endpoint already created
|
31
|
+
continue
|
32
|
+
|
33
|
+
endpoint_id = res.json()['id']
|
34
|
+
try:
|
35
|
+
res = import_component_names(context.project_id, endpoint_id, endpoint, context.resources)
|
36
|
+
except requests.HTTPError as e:
|
37
|
+
error_handler(endpoint, e)
|
38
|
+
try:
|
39
|
+
cleanup_endpoint(context.project_id, endpoint_id, context.resources['endpoint'])
|
40
|
+
except requests.HTTPError as e:
|
41
|
+
print(f"{bcolors.FAIL}Encountered {e.response.status_code} {e.response.reason}: {e.response.text} - Failed to delete endpoint: {endpoint['method']} {endpoint['path']}{bcolors.ENDC}", file=sys.stderr)
|
42
|
+
return
|
43
|
+
|
44
|
+
def import_endpoint(project_id: int, endpoint_resource: EndpointsResource, endpoint: EndpointShowResponse):
|
45
|
+
res: requests.Response = endpoint_resource.create(**{
|
46
|
+
'host': endpoint.get('host'),
|
47
|
+
'method': endpoint.get('method'),
|
48
|
+
'path_segments': json.dumps(endpoint.get('path_segment_names', [])),
|
49
|
+
'path': endpoint.get('path'),
|
50
|
+
'port': endpoint.get('port'),
|
51
|
+
'project_id': project_id,
|
52
|
+
})
|
53
|
+
|
54
|
+
if res.ok or res.status_code == 409: # Endpoint already created
|
55
|
+
return res
|
56
|
+
|
57
|
+
res.raise_for_status()
|
58
|
+
|
59
|
+
def import_header_name(project_id: int, endpoint_id: int, header_name_resource: HeaderNamesResource, header_name: RequestComponentName):
|
60
|
+
res: requests.Response = header_name_resource.create(endpoint_id, {
|
61
|
+
'name': header_name.get('name'),
|
62
|
+
'is_deterministic': header_name.get('is_deterministic', True),
|
63
|
+
'is_required': header_name.get('is_required', False),
|
64
|
+
'endpoint_id': endpoint_id,
|
65
|
+
'project_id': project_id,
|
66
|
+
})
|
67
|
+
|
68
|
+
res.raise_for_status()
|
69
|
+
|
70
|
+
def import_body_param_name(project_id: int, endpoint_id: int, body_param_name_resource: BodyParamNamesResource, body_param_name: BodyParamName):
|
71
|
+
res: requests.Response = body_param_name_resource.create(endpoint_id, {
|
72
|
+
'name': body_param_name.get('name'),
|
73
|
+
'is_deterministic': body_param_name.get('is_deterministic', True),
|
74
|
+
'is_required': body_param_name.get('is_required', False),
|
75
|
+
'inferred_type': body_param_name.get('inferred_type'),
|
76
|
+
'query': body_param_name.get('query'),
|
77
|
+
'endpoint_id': endpoint_id,
|
78
|
+
'project_id': project_id,
|
79
|
+
})
|
80
|
+
|
81
|
+
res.raise_for_status()
|
82
|
+
|
83
|
+
def import_query_param_name(project_id: int, endpoint_id: int, query_param_name_resource: QueryParamNamesResource, query_param_name: RequestComponentName):
|
84
|
+
res: requests.Response = query_param_name_resource.create(endpoint_id, {
|
85
|
+
'name': query_param_name.get('name'),
|
86
|
+
'is_deterministic': query_param_name.get('is_deterministic', True),
|
87
|
+
'is_required': query_param_name.get('is_required', False),
|
88
|
+
'endpoint_id': endpoint_id,
|
89
|
+
'project_id': project_id,
|
90
|
+
})
|
91
|
+
|
92
|
+
res.raise_for_status()
|
93
|
+
|
94
|
+
def import_response_param_name(project_id: int, endpoint_id: int, response_param_name_resource: ResponseParamNamesResource, response_param_name: RequestComponentName):
|
95
|
+
res: requests.Response = response_param_name_resource.create(endpoint_id, {
|
96
|
+
'name': response_param_name.get('name'),
|
97
|
+
'is_deterministic': response_param_name.get('is_deterministic', True),
|
98
|
+
'is_required': response_param_name.get('is_required', False),
|
99
|
+
'inferred_type': response_param_name.get('inferred_type'),
|
100
|
+
'query': response_param_name.get('query'),
|
101
|
+
'endpoint_id': endpoint_id,
|
102
|
+
'project_id': project_id,
|
103
|
+
})
|
104
|
+
|
105
|
+
res.raise_for_status()
|
106
|
+
|
107
|
+
def import_response_header_name(project_id: int, endpoint_id: int, response_header_name_resource: ResponseHeaderNamesResource, response_header_name: RequestComponentName):
|
108
|
+
res: requests.Response = response_header_name_resource.create(endpoint_id, {
|
109
|
+
'name': response_header_name.get('name'),
|
110
|
+
'is_deterministic': response_header_name.get('is_deterministic', True),
|
111
|
+
'is_required': response_header_name.get('is_required', False),
|
112
|
+
'endpoint_id': endpoint_id,
|
113
|
+
'project_id': project_id,
|
114
|
+
})
|
115
|
+
|
116
|
+
res.raise_for_status()
|
117
|
+
|
118
|
+
component_name_import_dispatch = {
|
119
|
+
ENDPOINT_COMPONENT_NAMES[0]: import_header_name,
|
120
|
+
ENDPOINT_COMPONENT_NAMES[1]: import_body_param_name,
|
121
|
+
ENDPOINT_COMPONENT_NAMES[2]: import_query_param_name,
|
122
|
+
ENDPOINT_COMPONENT_NAMES[3]: import_response_header_name,
|
123
|
+
ENDPOINT_COMPONENT_NAMES[4]: import_response_param_name
|
124
|
+
}
|
125
|
+
|
126
|
+
def process_import(component_name: str, *args):
|
127
|
+
return component_name_import_dispatch[component_name](*args)
|
128
|
+
|
129
|
+
def import_component_names(project_id: int, endpoint_id: int, endpoint: EndpointShowResponse, resources: Dict[str, EndpointsResource]):
|
130
|
+
for component_name in ENDPOINT_COMPONENT_NAMES:
|
131
|
+
for component in endpoint.get(f'{component_name}s', {}):
|
132
|
+
resource = resources[component_name]
|
133
|
+
process_import(component_name, project_id, endpoint_id, resource, component)
|
134
|
+
|
135
|
+
def cleanup_endpoint(project_id: int, endpoint_id: int, resource: EndpointsResource):
|
136
|
+
print(f"{bcolors.FAIL}Cleaning up partial import...{bcolors.ENDC}")
|
137
|
+
res: requests.Response = resource.destroy(endpoint_id, **{
|
138
|
+
'project_id': project_id
|
139
|
+
})
|
140
|
+
|
141
|
+
res.raise_for_status()
|
142
|
+
|
143
|
+
def error_handler(endpoint: EndpointShowResponse, error: requests.HTTPError):
|
144
|
+
print(
|
145
|
+
f"{bcolors.FAIL}Encountered {error.response.status_code} {error.response.reason}: {error.response.text} - Failed to import endpoint: {endpoint['method']} {endpoint['path']} - Aborting operation{bcolors.ENDC}",
|
146
|
+
file=sys.stderr
|
147
|
+
)
|
@@ -73,19 +73,32 @@ class OpenApiEndpointAdapter():
|
|
73
73
|
endpoint: EndpointShowResponse = {}
|
74
74
|
endpoint['id'] = endpoint_counter
|
75
75
|
endpoint['method'] = http_method.upper()
|
76
|
-
endpoint['host'] = parsed_url.netloc
|
76
|
+
endpoint['host'] = '-' if parsed_url.netloc == '' else parsed_url.netloc
|
77
77
|
|
78
78
|
joined_path = self.__urljoin(parsed_url.path, path_name)
|
79
79
|
split_parts = joined_path.split('/')
|
80
80
|
pattern_path = []
|
81
|
+
segment_names = []
|
81
82
|
for part in split_parts:
|
82
83
|
sanitized_part = part
|
84
|
+
segment_name = part
|
83
85
|
if part.startswith('{') and part.endswith('}'):
|
84
86
|
sanitized_part = '%'
|
87
|
+
segment_name = f":{part[1:-1]}"
|
85
88
|
pattern_path.append(sanitized_part)
|
89
|
+
segment_names.append(segment_name)
|
86
90
|
pattern_path_str = '/'.join(pattern_path)
|
87
91
|
endpoint['match_pattern'] = pattern_path_str
|
88
92
|
endpoint['path'] = joined_path
|
93
|
+
|
94
|
+
endpoint['path_segment_names'] = []
|
95
|
+
for segment_name in segment_names:
|
96
|
+
if segment_name == "":
|
97
|
+
continue
|
98
|
+
path_component_name: RequestComponentName = {}
|
99
|
+
path_component_name['name'] = segment_name
|
100
|
+
path_component_name['type'] = "alias" if segment_name.startswith(':') else "static"
|
101
|
+
endpoint['path_segment_names'].append(path_component_name)
|
89
102
|
|
90
103
|
endpoint['port'] = str(parsed_url.port)
|
91
104
|
if endpoint['port'] is None or endpoint['port'] == 'None':
|
@@ -94,7 +107,7 @@ class OpenApiEndpointAdapter():
|
|
94
107
|
elif parsed_url.scheme == 'http':
|
95
108
|
endpoint['port'] = '80'
|
96
109
|
else:
|
97
|
-
endpoint['port'] = ''
|
110
|
+
endpoint['port'] = '0'
|
98
111
|
|
99
112
|
alias_counter = 0
|
100
113
|
header_param_counter = 0
|
@@ -142,7 +155,10 @@ class OpenApiEndpointAdapter():
|
|
142
155
|
param_value = self.__open_api_to_default_python_type(open_api_type)
|
143
156
|
|
144
157
|
literal_query_param = {
|
145
|
-
parameter['name']: {
|
158
|
+
parameter['name']: {
|
159
|
+
'value': param_value,
|
160
|
+
'required': parameter.get('required', False),
|
161
|
+
}
|
146
162
|
}
|
147
163
|
|
148
164
|
if not endpoint.get('literal_query_params'):
|
@@ -238,6 +254,11 @@ class OpenApiEndpointAdapter():
|
|
238
254
|
else:
|
239
255
|
self.__convert_literal_component_param(endpoint, required_body_params, [literal_body_params], 'body_param_name', 'literal_body_params')
|
240
256
|
|
257
|
+
# Responses -> construct lists of response header and response param name resources
|
258
|
+
responses = operation.get('responses', {})
|
259
|
+
if responses:
|
260
|
+
self.__parse_responses(endpoint, responses, components)
|
261
|
+
|
241
262
|
endpoints.append(endpoint)
|
242
263
|
|
243
264
|
return endpoints
|
@@ -391,11 +412,30 @@ class OpenApiEndpointAdapter():
|
|
391
412
|
component_name = component_data[1]
|
392
413
|
component = components.get(component_type, {})
|
393
414
|
|
415
|
+
# If component_type is 'headers'
|
416
|
+
# Example: '#components/headers/X-RateLimit-Limit'
|
417
|
+
if component_type == "headers":
|
418
|
+
# In this case, literal_body_params represents a header rather than request or response body params
|
419
|
+
literal_body_params['name'] = component_name
|
420
|
+
header_example = component.get('example')
|
421
|
+
if header_example:
|
422
|
+
literal_body_params['values'].append(header_example)
|
423
|
+
literal_body_params['is_required'] = component.get('is_required', False)
|
424
|
+
literal_body_params['is_deterministic'] = True
|
425
|
+
return literal_body_params
|
426
|
+
|
394
427
|
# Example: {'type': 'object', 'required': ['name'], 'properties': {'name': {'type': 'string'}, 'tag': {'type': 'string'}}}
|
395
428
|
body_spec = component.content()[component_name]
|
396
429
|
required_body_params += body_spec.get('required', [])
|
397
430
|
|
398
|
-
param_properties =
|
431
|
+
param_properties = {}
|
432
|
+
schema_type = body_spec.get('type')
|
433
|
+
if schema_type:
|
434
|
+
if schema_type == 'object':
|
435
|
+
param_properties = body_spec.get('properties', {})
|
436
|
+
elif schema_type == 'array':
|
437
|
+
param_properties = {'tmp': body_spec['items']}
|
438
|
+
|
399
439
|
all_of = body_spec.get('allOf')
|
400
440
|
any_of = body_spec.get('anyOf')
|
401
441
|
one_of = body_spec.get('oneOf')
|
@@ -421,7 +461,7 @@ class OpenApiEndpointAdapter():
|
|
421
461
|
# elif any_of or one_of:
|
422
462
|
|
423
463
|
return param_properties
|
424
|
-
|
464
|
+
|
425
465
|
def __convert_literal_component_param(self, endpoint: EndpointShowResponse,
|
426
466
|
required_component_params: List[str], literal_component_params: Union[dict, list],
|
427
467
|
component_name: str, literal_component_name: str) -> None:
|
@@ -444,7 +484,11 @@ class OpenApiEndpointAdapter():
|
|
444
484
|
else:
|
445
485
|
param['is_required'] = False
|
446
486
|
|
447
|
-
endpoint
|
487
|
+
if not endpoint.get(component_name + 's'):
|
488
|
+
endpoint[component_name + 's'] = built_params_list
|
489
|
+
else:
|
490
|
+
endpoint[component_name + 's'].extend(built_params_list)
|
491
|
+
|
448
492
|
del endpoint[literal_component_name]
|
449
493
|
|
450
494
|
# urllib.parse.urljoin() doesn't work for some of our edge cases
|
@@ -557,3 +601,64 @@ class OpenApiEndpointAdapter():
|
|
557
601
|
|
558
602
|
return result
|
559
603
|
|
604
|
+
def __parse_responses(self, endpoint: EndpointShowResponse, responses: Spec, components: Spec):
|
605
|
+
for response_code, response_definition in responses.items():
|
606
|
+
# Construct response param name components
|
607
|
+
literal_response_params = {}
|
608
|
+
response_body_array = False
|
609
|
+
required_response_params = []
|
610
|
+
response_content = response_definition.get('content', {})
|
611
|
+
for mimetype, media_type in response_content.items():
|
612
|
+
param_properties = {}
|
613
|
+
schema = media_type['schema']
|
614
|
+
|
615
|
+
if '$ref' in schema:
|
616
|
+
reference = schema['$ref']
|
617
|
+
self.__dereference(components, reference, required_response_params, literal_response_params)
|
618
|
+
else:
|
619
|
+
schema_type = schema.get('type')
|
620
|
+
if schema_type:
|
621
|
+
if schema_type == 'object':
|
622
|
+
param_properties = schema.get('properties', {})
|
623
|
+
elif schema_type == 'array':
|
624
|
+
response_body_array = True
|
625
|
+
param_properties = {'tmp': schema['items']}
|
626
|
+
|
627
|
+
for property_key, property_value in param_properties.items():
|
628
|
+
if property_key in required_response_params:
|
629
|
+
param_properties[property_key]['required'] = True
|
630
|
+
|
631
|
+
self.__extract_param_properties(components, None, required_response_params, param_properties, literal_response_params)
|
632
|
+
|
633
|
+
if literal_response_params:
|
634
|
+
endpoint['literal_response_params'] = literal_response_params
|
635
|
+
|
636
|
+
# Only support first media type
|
637
|
+
break
|
638
|
+
|
639
|
+
literal_response_params = endpoint.get('literal_response_params')
|
640
|
+
if literal_response_params:
|
641
|
+
if not response_body_array:
|
642
|
+
self.__convert_literal_component_param(endpoint, required_response_params, literal_response_params, 'response_param_name', 'literal_response_params')
|
643
|
+
else:
|
644
|
+
self.__convert_literal_component_param(endpoint, required_response_params, [literal_response_params], 'response_param_name', 'literal_response_params')
|
645
|
+
|
646
|
+
# Construct response header name components
|
647
|
+
response_headers = response_definition.get('headers', {})
|
648
|
+
for header_name, header_definition in response_headers.items():
|
649
|
+
response_header_name: RequestComponentName = {}
|
650
|
+
response_header_name['name'] = header_name
|
651
|
+
|
652
|
+
if '$ref' in header_definition:
|
653
|
+
reference = header_definition['$ref']
|
654
|
+
self.__dereference(components, reference, [], response_header_name)
|
655
|
+
else:
|
656
|
+
header_example = header_definition.get('example')
|
657
|
+
if header_example:
|
658
|
+
response_header_name['values'].append(header_example)
|
659
|
+
response_header_name['is_required'] = header_definition.get('is_required', False)
|
660
|
+
response_header_name['is_deterministic'] = True
|
661
|
+
|
662
|
+
if not endpoint.get('response_header_names'):
|
663
|
+
endpoint['response_header_names'] = []
|
664
|
+
endpoint['response_header_names'].append(response_header_name)
|
@@ -1,7 +1,33 @@
|
|
1
|
-
from typing import
|
1
|
+
from typing import TypedDict
|
2
2
|
|
3
3
|
OPENAPI_FORMAT = 'openapi'
|
4
4
|
|
5
|
+
ENDPOINT_COMPONENT_NAMES = [
|
6
|
+
"header_name",
|
7
|
+
"body_param_name",
|
8
|
+
"query_param_name",
|
9
|
+
"response_header_name",
|
10
|
+
"response_param_name"
|
11
|
+
]
|
12
|
+
|
5
13
|
class EndpointCreateParams(TypedDict):
|
6
|
-
|
14
|
+
host: str
|
15
|
+
method: str
|
16
|
+
path_segments: str
|
7
17
|
path: str
|
18
|
+
port: str
|
19
|
+
project_id: str
|
20
|
+
|
21
|
+
class HeaderNameCreateParams(TypedDict):
|
22
|
+
name: str
|
23
|
+
is_required: bool
|
24
|
+
is_deterministic: bool
|
25
|
+
project_id: str
|
26
|
+
endpoint_id: int
|
27
|
+
|
28
|
+
class ParamNameCreateParams(TypedDict):
|
29
|
+
name: str
|
30
|
+
project_id: str
|
31
|
+
endpoint_id: int
|
32
|
+
inferred_type: str
|
33
|
+
query: str
|
stoobly_agent/lib/api/api.py
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
import requests
|
2
|
+
import urllib
|
3
|
+
import pdb
|
4
|
+
|
5
|
+
from stoobly_agent.app.models.types import ParamNameCreateParams
|
6
|
+
|
7
|
+
from ..logger import Logger
|
8
|
+
from .endpoints_resource import EndpointsResource
|
9
|
+
|
10
|
+
class BodyParamNamesResource(EndpointsResource):
|
11
|
+
BODY_PARAM_NAMES_ENDPOINT = 'body_param_names'
|
12
|
+
|
13
|
+
def create(self, endpoint_id: int, params: ParamNameCreateParams = {}):
|
14
|
+
url = f"{self.service_url}/{self.ENDPOINTS_ENDPOINT}/{endpoint_id}/{self.BODY_PARAM_NAMES_ENDPOINT}"
|
15
|
+
return self.post(url, headers=self.default_headers, json=params)
|
16
|
+
|
17
|
+
def index(self, endpoint_id: int, query_params = {}) -> requests.Response:
|
18
|
+
url = f"{self.service_url}/{self.ENDPOINTS_ENDPOINT}/{endpoint_id}/{self.BODY_PARAM_NAMES_ENDPOINT}"
|
19
|
+
|
20
|
+
Logger.instance().debug(f"{self.LOG_ID}.request_response:{url}?{urllib.parse.urlencode(query_params)}")
|
21
|
+
|
22
|
+
return self.get(url, headers=self.default_headers, params=query_params)
|
23
|
+
|
24
|
+
def show(self, endpoint_id: int, body_param_name_id: int, query_params = {}) -> requests.Response:
|
25
|
+
url = f"{self.service_url}/{self.ENDPOINTS_ENDPOINT}/{endpoint_id}/{self.BODY_PARAM_NAMES_ENDPOINT}/{body_param_name_id}"
|
26
|
+
|
27
|
+
Logger.instance().debug(f"{self.LOG_ID}.request_response:{url}?{urllib.parse.urlencode(query_params)}")
|
28
|
+
|
29
|
+
return self.get(url, headers=self.default_headers, params=query_params)
|
30
|
+
|
31
|
+
def destroy(self, endpoint_id, body_param_name_id: int, query_params = {}) -> requests.Response:
|
32
|
+
url = f"{self.service_url}/{self.ENDPOINTS_ENDPOINT}/{endpoint_id}/{self.BODY_PARAM_NAMES_ENDPOINT}/{body_param_name_id}"
|
33
|
+
|
34
|
+
Logger.instance().debug(f"{self.LOG_ID}.request_response:{url}?{urllib.parse.urlencode(query_params)}")
|
35
|
+
|
36
|
+
return self.delete(url, headers=self.default_headers, params=query_params)
|
@@ -11,7 +11,7 @@ class EndpointsResource(StooblyApi):
|
|
11
11
|
|
12
12
|
def create(self, **params):
|
13
13
|
url = f"{self.service_url}/{self.ENDPOINTS_ENDPOINT}"
|
14
|
-
return self.post(url, headers=self.default_headers,
|
14
|
+
return self.post(url, headers=self.default_headers, json=params)
|
15
15
|
|
16
16
|
def index(self, **query_params: EndpointsIndexQueryParams) -> requests.Response:
|
17
17
|
url = f"{self.service_url}/{self.ENDPOINTS_ENDPOINT}"
|
@@ -25,4 +25,11 @@ class EndpointsResource(StooblyApi):
|
|
25
25
|
|
26
26
|
Logger.instance().debug(f"{self.LOG_ID}.request_response:{url}?{urllib.parse.urlencode(query_params)}")
|
27
27
|
|
28
|
-
return self.get(url, headers=self.default_headers, params=query_params)
|
28
|
+
return self.get(url, headers=self.default_headers, params=query_params)
|
29
|
+
|
30
|
+
def destroy(self, endpoint_id: int, **query_params) -> requests.Response:
|
31
|
+
url = f"{self.service_url}/{self.ENDPOINTS_ENDPOINT}/{endpoint_id}"
|
32
|
+
|
33
|
+
Logger.instance().debug(f"{self.LOG_ID}.request_response:{url}?{urllib.parse.urlencode(query_params)}")
|
34
|
+
|
35
|
+
return self.delete(url, headers=self.default_headers, params=query_params)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import requests
|
2
|
+
import urllib
|
3
|
+
import pdb
|
4
|
+
|
5
|
+
from stoobly_agent.app.models.types import HeaderNameCreateParams
|
6
|
+
|
7
|
+
from ..logger import Logger
|
8
|
+
from .endpoints_resource import EndpointsResource
|
9
|
+
|
10
|
+
class HeaderNamesResource(EndpointsResource):
|
11
|
+
HEADER_NAMES_ENDPOINT = 'header_names'
|
12
|
+
|
13
|
+
def create(self, endpoint_id: int, params: HeaderNameCreateParams = {}):
|
14
|
+
url = f"{self.service_url}/{self.ENDPOINTS_ENDPOINT}/{endpoint_id}/{self.HEADER_NAMES_ENDPOINT}"
|
15
|
+
return self.post(url, headers=self.default_headers, json=params)
|
16
|
+
|
17
|
+
def index(self, endpoint_id: int, query_params = {}) -> requests.Response:
|
18
|
+
url = f"{self.service_url}/{self.ENDPOINTS_ENDPOINT}/{endpoint_id}/{self.HEADER_NAMES_ENDPOINT}"
|
19
|
+
|
20
|
+
Logger.instance().debug(f"{self.LOG_ID}.request_response:{url}?{urllib.parse.urlencode(query_params)}")
|
21
|
+
|
22
|
+
return self.get(url, headers=self.default_headers, params=query_params)
|
23
|
+
|
24
|
+
def show(self, endpoint_id: int, header_name_id: int, query_params = {}) -> requests.Response:
|
25
|
+
url = f"{self.service_url}/{self.ENDPOINTS_ENDPOINT}/{endpoint_id}/{self.HEADER_NAMES_ENDPOINT}/{header_name_id}"
|
26
|
+
|
27
|
+
Logger.instance().debug(f"{self.LOG_ID}.request_response:{url}?{urllib.parse.urlencode(query_params)}")
|
28
|
+
|
29
|
+
return self.get(url, headers=self.default_headers, params=query_params)
|
30
|
+
|
31
|
+
def destroy(self, endpoint_id: int, header_name_id: int, query_params = {}) -> requests.Response:
|
32
|
+
url = f"{self.service_url}/{self.ENDPOINTS_ENDPOINT}/{endpoint_id}/{self.HEADER_NAMES_ENDPOINT}/{header_name_id}"
|
33
|
+
|
34
|
+
Logger.instance().debug(f"{self.LOG_ID}.request_response:{url}?{urllib.parse.urlencode(query_params)}")
|
35
|
+
|
36
|
+
return self.delete(url, headers=self.default_headers, params=query_params)
|
@@ -43,8 +43,10 @@ class EndpointShowResponse(TypedDict):
|
|
43
43
|
path_segment_names: List[RequestComponentName]
|
44
44
|
query_param_names: List[RequestComponentName]
|
45
45
|
response_param_names: List[ResponseParamName]
|
46
|
+
response_header_names: List[RequestComponentName]
|
46
47
|
literal_query_params: Optional[dict]
|
47
48
|
literal_body_params: Optional[dict]
|
49
|
+
literal_response_params: Optional[dict]
|
48
50
|
|
49
51
|
ARRAY_TYPE = 'Array'
|
50
52
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import requests
|
2
|
+
import urllib
|
3
|
+
import pdb
|
4
|
+
|
5
|
+
from stoobly_agent.app.models.types import ParamNameCreateParams
|
6
|
+
|
7
|
+
from ..logger import Logger
|
8
|
+
from .endpoints_resource import EndpointsResource
|
9
|
+
|
10
|
+
class QueryParamNamesResource(EndpointsResource):
|
11
|
+
QUERY_PARAM_NAMES_ENDPOINT = 'query_param_names'
|
12
|
+
|
13
|
+
def create(self, endpoint_id: int, params: ParamNameCreateParams = {}):
|
14
|
+
url = f"{self.service_url}/{self.ENDPOINTS_ENDPOINT}/{endpoint_id}/{self.QUERY_PARAM_NAMES_ENDPOINT}"
|
15
|
+
return self.post(url, headers=self.default_headers, json=params)
|
16
|
+
|
17
|
+
def index(self, endpoint_id: int, query_params = {}) -> requests.Response:
|
18
|
+
url = f"{self.service_url}/{self.ENDPOINTS_ENDPOINT}/{endpoint_id}/{self.QUERY_PARAM_NAMES_ENDPOINT}"
|
19
|
+
|
20
|
+
Logger.instance().debug(f"{self.LOG_ID}.request_response:{url}?{urllib.parse.urlencode(query_params)}")
|
21
|
+
|
22
|
+
return self.get(url, headers=self.default_headers, params=query_params)
|
23
|
+
|
24
|
+
def show(self, endpoint_id: int, query_param_name_id: int, query_params = {}) -> requests.Response:
|
25
|
+
url = f"{self.service_url}/{self.ENDPOINTS_ENDPOINT}/{endpoint_id}/{self.QUERY_PARAM_NAMES_ENDPOINT}/{query_param_name_id}"
|
26
|
+
|
27
|
+
Logger.instance().debug(f"{self.LOG_ID}.request_response:{url}?{urllib.parse.urlencode(query_params)}")
|
28
|
+
|
29
|
+
return self.get(url, headers=self.default_headers, params=query_params)
|
30
|
+
|
31
|
+
def destroy(self, endpoint_id: int, query_param_name_id: int, query_params = {}) -> requests.Response:
|
32
|
+
url = f"{self.service_url}/{self.ENDPOINTS_ENDPOINT}/{endpoint_id}/{self.QUERY_PARAM_NAMES_ENDPOINT}/{query_param_name_id}"
|
33
|
+
|
34
|
+
Logger.instance().debug(f"{self.LOG_ID}.request_response:{url}?{urllib.parse.urlencode(query_params)}")
|
35
|
+
|
36
|
+
return self.delete(url, headers=self.default_headers, params=query_params)
|