syndicate/core/export/configuration_exporter.py (95 lines of code) (raw):
"""
Copyright 2024 EPAM Systems, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import os
from abc import ABC, abstractmethod
from syndicate.commons import deep_get
from syndicate.commons.log_helper import get_user_logger
from syndicate.core.constants import EXPORT_DIR_NAME
from syndicate.core.helper import build_path
USER_LOG = get_user_logger()
class ConfigurationExporter(ABC):
def __init__(self):
from syndicate.core import CONFIG, RESOURCES_PROVIDER
self.config = CONFIG
self.project_path = self.config.project_path
self.resources_provider = RESOURCES_PROVIDER
def prepare_output_directory(self, output_dir):
if not output_dir:
output_dir_path = build_path(
self.project_path, EXPORT_DIR_NAME)
elif not os.path.isabs(output_dir):
output_dir_path = build_path(
os.getcwd(), output_dir)
else:
output_dir_path = output_dir
os.makedirs(output_dir_path, exist_ok=True)
return output_dir_path
@staticmethod
def _remove_prefix_suffix_from_string(string: str,
prefix: str,
suffix: str) -> str:
if string.startswith(prefix) and prefix:
string = string[len(prefix):]
if string.endswith(suffix) and suffix:
string = string[:-len(suffix)]
return string
@abstractmethod
def export_configuration(self, *args, **kwargs):
pass
class OASV3Exporter(ConfigurationExporter):
def __init__(self):
super().__init__()
self.extended_prefix_mode = self.config.extended_prefix_mode
self.prefix = self.config.resources_prefix
self.suffix = self.config.resources_suffix
def export_configuration(self, arn, meta):
return self._export_api_gw_openapi_spec(arn, meta)
def _export_api_gw_openapi_spec(self, api_arn: str,
meta: dict) -> (str, dict):
api_id = api_arn.split('/')[-1]
api_stage = deep_get(meta, ['resource_meta', 'deploy_stage'])
specification = self.resources_provider.api_gw().describe_openapi(
api_id=api_id,
stage_name=api_stage)
if not specification:
USER_LOG.warning(f'API Gateway not found by the ARN: "{api_arn}"')
return api_id, None
if self.extended_prefix_mode:
specification['info']['title'] = \
self._remove_prefix_suffix_from_string(
string=specification['info']['title'],
prefix=self.prefix,
suffix=self.suffix,
)
self._remove_prefix_suffix_from_arn(
spec=specification,
prefix=self.prefix,
suffix=self.suffix,
)
# Add tags to the OpenAPI specification under 'x-syndicate-openapi-tags'
tags = self.resources_provider.api_gw().describe_tags(api_arn)
if tags:
syndicate_tags = {}
for key, value in tags.items():
syndicate_tags[key] = value
specification['x-syndicate-openapi-tags'] = syndicate_tags
return api_id, specification
def _remove_prefix_suffix_from_arn(self, spec: dict, prefix: str,
suffix: str) -> None:
def __remove_prefix_suffix(string: str, delimiter: str) -> str:
if delimiter in string:
origin_parts = string.split(delimiter)
new_parts = []
for part in origin_parts:
new_parts.append(
self._remove_prefix_suffix_from_string(
part, prefix, suffix))
string = delimiter.join(new_parts)
return string
if isinstance(spec, dict):
for key in spec.keys():
if isinstance(spec[key], dict):
self._remove_prefix_suffix_from_arn(spec[key],
prefix, suffix)
else:
if isinstance(spec[key], str):
if 'arn' in spec[key]:
spec[key] = __remove_prefix_suffix(spec[key], ':')
spec[key] = __remove_prefix_suffix(spec[key], '/')