cosmotech-acceleration-library 1.1.0__py3-none-any.whl → 2.1.0rc1__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.
- cosmotech/coal/__init__.py +1 -1
- cosmotech/coal/aws/__init__.py +1 -9
- cosmotech/coal/aws/s3.py +181 -214
- cosmotech/coal/azure/__init__.py +5 -5
- cosmotech/coal/azure/adx/__init__.py +24 -10
- cosmotech/coal/azure/adx/auth.py +2 -2
- cosmotech/coal/azure/adx/ingestion.py +10 -14
- cosmotech/coal/azure/adx/query.py +1 -1
- cosmotech/coal/azure/adx/runner.py +13 -14
- cosmotech/coal/azure/adx/store.py +5 -86
- cosmotech/coal/azure/adx/tables.py +2 -2
- cosmotech/coal/azure/adx/utils.py +2 -2
- cosmotech/coal/azure/blob.py +20 -26
- cosmotech/coal/azure/storage.py +3 -3
- cosmotech/coal/cosmotech_api/__init__.py +0 -28
- cosmotech/coal/cosmotech_api/apis/__init__.py +14 -0
- cosmotech/coal/cosmotech_api/apis/dataset.py +222 -0
- cosmotech/coal/cosmotech_api/apis/meta.py +25 -0
- cosmotech/coal/cosmotech_api/apis/organization.py +24 -0
- cosmotech/coal/cosmotech_api/apis/run.py +38 -0
- cosmotech/coal/cosmotech_api/apis/runner.py +75 -0
- cosmotech/coal/cosmotech_api/apis/solution.py +23 -0
- cosmotech/coal/cosmotech_api/apis/workspace.py +108 -0
- cosmotech/coal/cosmotech_api/objects/__init__.py +9 -0
- cosmotech/coal/cosmotech_api/objects/connection.py +125 -0
- cosmotech/coal/cosmotech_api/objects/parameters.py +127 -0
- cosmotech/coal/postgresql/runner.py +58 -41
- cosmotech/coal/postgresql/store.py +56 -15
- cosmotech/coal/postgresql/utils.py +255 -0
- cosmotech/coal/singlestore/store.py +3 -2
- cosmotech/coal/store/__init__.py +16 -13
- cosmotech/coal/store/output/__init__.py +0 -0
- cosmotech/coal/store/output/aws_channel.py +74 -0
- cosmotech/coal/store/output/az_storage_channel.py +33 -0
- cosmotech/coal/store/output/channel_interface.py +38 -0
- cosmotech/coal/store/output/channel_spliter.py +61 -0
- cosmotech/coal/store/output/postgres_channel.py +37 -0
- cosmotech/coal/store/pandas.py +1 -1
- cosmotech/coal/store/pyarrow.py +2 -2
- cosmotech/coal/store/store.py +4 -7
- cosmotech/coal/utils/configuration.py +197 -0
- cosmotech/coal/utils/decorator.py +4 -7
- cosmotech/csm_data/commands/adx_send_data.py +1 -1
- cosmotech/csm_data/commands/adx_send_runnerdata.py +3 -2
- cosmotech/csm_data/commands/api/api.py +6 -19
- cosmotech/csm_data/commands/api/postgres_send_runner_metadata.py +20 -16
- cosmotech/csm_data/commands/api/run_load_data.py +15 -52
- cosmotech/csm_data/commands/api/wsf_load_file.py +13 -16
- cosmotech/csm_data/commands/api/wsf_send_file.py +11 -14
- cosmotech/csm_data/commands/az_storage_upload.py +3 -2
- cosmotech/csm_data/commands/s3_bucket_delete.py +16 -15
- cosmotech/csm_data/commands/s3_bucket_download.py +16 -16
- cosmotech/csm_data/commands/s3_bucket_upload.py +16 -14
- cosmotech/csm_data/commands/store/dump_to_azure.py +3 -2
- cosmotech/csm_data/commands/store/dump_to_postgresql.py +3 -2
- cosmotech/csm_data/commands/store/dump_to_s3.py +18 -16
- cosmotech/csm_data/commands/store/list_tables.py +3 -2
- cosmotech/csm_data/commands/store/load_csv_folder.py +10 -4
- cosmotech/csm_data/commands/store/load_from_singlestore.py +3 -2
- cosmotech/csm_data/commands/store/output.py +35 -0
- cosmotech/csm_data/commands/store/reset.py +8 -3
- cosmotech/csm_data/commands/store/store.py +3 -3
- cosmotech/csm_data/main.py +4 -4
- cosmotech/csm_data/utils/decorators.py +4 -3
- cosmotech/translation/coal/en-US/coal/cosmotech_api/initialization.yml +8 -0
- cosmotech/translation/coal/en-US/coal/services/dataset.yml +10 -14
- cosmotech/translation/coal/en-US/coal/store/output/data_interface.yml +1 -0
- cosmotech/translation/coal/en-US/coal/store/output/split.yml +6 -0
- cosmotech/translation/coal/en-US/coal/utils/configuration.yml +2 -0
- cosmotech/translation/csm_data/en-US/csm_data/commands/store/output.yml +7 -0
- {cosmotech_acceleration_library-1.1.0.dist-info → cosmotech_acceleration_library-2.1.0rc1.dist-info}/METADATA +29 -33
- cosmotech_acceleration_library-2.1.0rc1.dist-info/RECORD +153 -0
- {cosmotech_acceleration_library-1.1.0.dist-info → cosmotech_acceleration_library-2.1.0rc1.dist-info}/WHEEL +1 -1
- cosmotech/coal/azure/functions.py +0 -72
- cosmotech/coal/cosmotech_api/connection.py +0 -96
- cosmotech/coal/cosmotech_api/dataset/__init__.py +0 -26
- cosmotech/coal/cosmotech_api/dataset/converters.py +0 -164
- cosmotech/coal/cosmotech_api/dataset/download/__init__.py +0 -19
- cosmotech/coal/cosmotech_api/dataset/download/adt.py +0 -119
- cosmotech/coal/cosmotech_api/dataset/download/common.py +0 -140
- cosmotech/coal/cosmotech_api/dataset/download/file.py +0 -229
- cosmotech/coal/cosmotech_api/dataset/download/twingraph.py +0 -185
- cosmotech/coal/cosmotech_api/dataset/upload.py +0 -41
- cosmotech/coal/cosmotech_api/dataset/utils.py +0 -132
- cosmotech/coal/cosmotech_api/parameters.py +0 -48
- cosmotech/coal/cosmotech_api/run.py +0 -25
- cosmotech/coal/cosmotech_api/run_data.py +0 -173
- cosmotech/coal/cosmotech_api/run_template.py +0 -108
- cosmotech/coal/cosmotech_api/runner/__init__.py +0 -28
- cosmotech/coal/cosmotech_api/runner/data.py +0 -38
- cosmotech/coal/cosmotech_api/runner/datasets.py +0 -416
- cosmotech/coal/cosmotech_api/runner/download.py +0 -135
- cosmotech/coal/cosmotech_api/runner/metadata.py +0 -42
- cosmotech/coal/cosmotech_api/runner/parameters.py +0 -157
- cosmotech/coal/cosmotech_api/twin_data_layer.py +0 -512
- cosmotech/coal/cosmotech_api/workspace.py +0 -127
- cosmotech/coal/utils/postgresql.py +0 -236
- cosmotech/coal/utils/semver.py +0 -6
- cosmotech/csm_data/commands/api/rds_load_csv.py +0 -90
- cosmotech/csm_data/commands/api/rds_send_csv.py +0 -74
- cosmotech/csm_data/commands/api/rds_send_store.py +0 -74
- cosmotech/csm_data/commands/api/runtemplate_load_handler.py +0 -66
- cosmotech/csm_data/commands/api/tdl_load_files.py +0 -76
- cosmotech/csm_data/commands/api/tdl_send_files.py +0 -82
- cosmotech/orchestrator_plugins/csm-data/templates/api/rds_load_csv.json +0 -27
- cosmotech/orchestrator_plugins/csm-data/templates/api/rds_send_csv.json +0 -27
- cosmotech/orchestrator_plugins/csm-data/templates/api/rds_send_store.json +0 -27
- cosmotech/orchestrator_plugins/csm-data/templates/api/runtemplate_load_handler.json +0 -27
- cosmotech/orchestrator_plugins/csm-data/templates/api/tdl_load_files.json +0 -32
- cosmotech/orchestrator_plugins/csm-data/templates/api/tdl_send_files.json +0 -27
- cosmotech/translation/coal/en-US/coal/cosmotech_api/run_data.yml +0 -2
- cosmotech/translation/csm_data/en-US/csm_data/commands/api/rds_load_csv.yml +0 -13
- cosmotech/translation/csm_data/en-US/csm_data/commands/api/rds_send_csv.yml +0 -12
- cosmotech/translation/csm_data/en-US/csm_data/commands/api/rds_send_store.yml +0 -12
- cosmotech/translation/csm_data/en-US/csm_data/commands/api/tdl_load_files.yml +0 -14
- cosmotech/translation/csm_data/en-US/csm_data/commands/api/tdl_send_files.yml +0 -18
- cosmotech_acceleration_library-1.1.0.dist-info/RECORD +0 -171
- {cosmotech_acceleration_library-1.1.0.dist-info → cosmotech_acceleration_library-2.1.0rc1.dist-info}/entry_points.txt +0 -0
- {cosmotech_acceleration_library-1.1.0.dist-info → cosmotech_acceleration_library-2.1.0rc1.dist-info}/licenses/LICENSE +0 -0
- {cosmotech_acceleration_library-1.1.0.dist-info → cosmotech_acceleration_library-2.1.0rc1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Copyright (C) - 2023 - 2025 - Cosmo Tech
|
|
2
|
+
# This document and all information contained herein is the exclusive property -
|
|
3
|
+
# including all intellectual property rights pertaining thereto - of Cosmo Tech.
|
|
4
|
+
# Any use, reproduction, translation, broadcasting, transmission, distribution,
|
|
5
|
+
# etc., to any person is prohibited unless it has been previously and
|
|
6
|
+
# specifically authorized by written means by Cosmo Tech.
|
|
7
|
+
from typing import Any, Optional
|
|
8
|
+
|
|
9
|
+
from cosmotech.orchestrator.utils.translate import T
|
|
10
|
+
from cosmotech_api import RunnerApi as BaseRunnerApi
|
|
11
|
+
|
|
12
|
+
from cosmotech.coal.cosmotech_api.apis.dataset import DatasetApi
|
|
13
|
+
from cosmotech.coal.cosmotech_api.objects.connection import Connection
|
|
14
|
+
from cosmotech.coal.cosmotech_api.objects.parameters import Parameters
|
|
15
|
+
from cosmotech.coal.utils.configuration import ENVIRONMENT_CONFIGURATION, Configuration
|
|
16
|
+
from cosmotech.coal.utils.logger import LOGGER
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class RunnerApi(BaseRunnerApi, Connection):
|
|
20
|
+
|
|
21
|
+
def __init__(
|
|
22
|
+
self,
|
|
23
|
+
configuration: Configuration = ENVIRONMENT_CONFIGURATION,
|
|
24
|
+
):
|
|
25
|
+
Connection.__init__(self, configuration)
|
|
26
|
+
BaseRunnerApi.__init__(self, self.api_client)
|
|
27
|
+
|
|
28
|
+
LOGGER.debug(T("coal.cosmotech_api.initialization.runner_api_initialized"))
|
|
29
|
+
|
|
30
|
+
def get_runner_metadata(
|
|
31
|
+
self,
|
|
32
|
+
runner_id: Optional[str] = None,
|
|
33
|
+
include: Optional[list[str]] = None,
|
|
34
|
+
exclude: Optional[list[str]] = None,
|
|
35
|
+
) -> dict[str, Any]:
|
|
36
|
+
runner = self.get_runner(
|
|
37
|
+
self.configuration.cosmotech.organization_id,
|
|
38
|
+
self.configuration.cosmotech.workspace_id,
|
|
39
|
+
runner_id or self.configuration.cosmotech.runner_id,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
return runner.model_dump(by_alias=True, exclude_none=True, include=include, exclude=exclude, mode="json")
|
|
43
|
+
|
|
44
|
+
def download_runner_data(
|
|
45
|
+
self,
|
|
46
|
+
download_datasets: Optional[str] = None,
|
|
47
|
+
):
|
|
48
|
+
LOGGER.info(T("coal.cosmotech_api.runner.starting_download"))
|
|
49
|
+
|
|
50
|
+
# Get runner data
|
|
51
|
+
runner = self.get_runner(
|
|
52
|
+
self.configuration.cosmotech.organization_id,
|
|
53
|
+
self.configuration.cosmotech.workspace_id,
|
|
54
|
+
self.configuration.cosmotech.runner_id,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# Skip if no parameters found
|
|
58
|
+
if not runner.parameters_values:
|
|
59
|
+
LOGGER.warning(T("coal.cosmotech_api.runner.no_parameters"))
|
|
60
|
+
else:
|
|
61
|
+
LOGGER.info(T("coal.cosmotech_api.runner.loaded_data"))
|
|
62
|
+
parameters = Parameters(runner)
|
|
63
|
+
parameters.write_parameters_to_json(self.configuration.cosmotech.parameters_absolute_path)
|
|
64
|
+
|
|
65
|
+
if runner.datasets.parameter:
|
|
66
|
+
ds_api = DatasetApi(self.configuration)
|
|
67
|
+
ds_api.download_parameter(runner.datasets.parameter)
|
|
68
|
+
|
|
69
|
+
# Download datasets if requested
|
|
70
|
+
if download_datasets:
|
|
71
|
+
LOGGER.info(T("coal.cosmotech_api.runner.downloading_datasets").format(count=len(runner.datasets.bases)))
|
|
72
|
+
if runner.datasets.bases:
|
|
73
|
+
ds_api = DatasetApi(self.configuration)
|
|
74
|
+
for dataset_id in runner.datasets.bases:
|
|
75
|
+
ds_api.download_dataset(dataset_id)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Copyright (C) - 2023 - 2025 - Cosmo Tech
|
|
2
|
+
# This document and all information contained herein is the exclusive property -
|
|
3
|
+
# including all intellectual property rights pertaining thereto - of Cosmo Tech.
|
|
4
|
+
# Any use, reproduction, translation, broadcasting, transmission, distribution,
|
|
5
|
+
# etc., to any person is prohibited unless it has been previously and
|
|
6
|
+
# specifically authorized by written means by Cosmo Tech.
|
|
7
|
+
from cosmotech.orchestrator.utils.translate import T
|
|
8
|
+
from cosmotech_api import SolutionApi as BaseSolutionApi
|
|
9
|
+
|
|
10
|
+
from cosmotech.coal.cosmotech_api.objects.connection import Connection
|
|
11
|
+
from cosmotech.coal.utils.configuration import ENVIRONMENT_CONFIGURATION, Configuration
|
|
12
|
+
from cosmotech.coal.utils.logger import LOGGER
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SolutionApi(BaseSolutionApi, Connection):
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
configuration: Configuration = ENVIRONMENT_CONFIGURATION,
|
|
19
|
+
):
|
|
20
|
+
Connection.__init__(self, configuration)
|
|
21
|
+
BaseSolutionApi.__init__(self, self.api_client)
|
|
22
|
+
|
|
23
|
+
LOGGER.debug(T("coal.cosmotech_api.initialization.solution_api_initialized"))
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Copyright (C) - 2023 - 2025 - Cosmo Tech
|
|
2
|
+
# This document and all information contained herein is the exclusive property -
|
|
3
|
+
# including all intellectual property rights pertaining thereto - of Cosmo Tech.
|
|
4
|
+
# Any use, reproduction, translation, broadcasting, transmission, distribution,
|
|
5
|
+
# etc., to any person is prohibited unless it has been previously and
|
|
6
|
+
# specifically authorized by written means by Cosmo Tech.
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from cosmotech.orchestrator.utils.translate import T
|
|
10
|
+
from cosmotech_api import ApiException
|
|
11
|
+
from cosmotech_api import WorkspaceApi as BaseWorkspaceApi
|
|
12
|
+
|
|
13
|
+
from cosmotech.coal.cosmotech_api.objects.connection import Connection
|
|
14
|
+
from cosmotech.coal.utils.configuration import ENVIRONMENT_CONFIGURATION, Configuration
|
|
15
|
+
from cosmotech.coal.utils.logger import LOGGER
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class WorkspaceApi(BaseWorkspaceApi, Connection):
|
|
19
|
+
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
configuration: Configuration = ENVIRONMENT_CONFIGURATION,
|
|
23
|
+
):
|
|
24
|
+
Connection.__init__(self, configuration)
|
|
25
|
+
BaseWorkspaceApi.__init__(self, self.api_client)
|
|
26
|
+
|
|
27
|
+
LOGGER.debug(T("coal.cosmotech_api.initialization.workspace_api_initialized"))
|
|
28
|
+
|
|
29
|
+
def list_filtered_workspace_files(
|
|
30
|
+
self,
|
|
31
|
+
organization_id: str,
|
|
32
|
+
workspace_id: str,
|
|
33
|
+
file_prefix: str,
|
|
34
|
+
) -> list[str]:
|
|
35
|
+
target_list = []
|
|
36
|
+
LOGGER.info(T("coal.cosmotech_api.workspace.target_is_folder"))
|
|
37
|
+
wsf = self.list_workspace_files(organization_id, workspace_id)
|
|
38
|
+
for workspace_file in wsf:
|
|
39
|
+
if workspace_file.file_name.startswith(file_prefix):
|
|
40
|
+
target_list.append(workspace_file.file_name)
|
|
41
|
+
|
|
42
|
+
if not target_list:
|
|
43
|
+
LOGGER.error(
|
|
44
|
+
T("coal.common.errors.data_no_workspace_files").format(
|
|
45
|
+
file_prefix=file_prefix, workspace_id=workspace_id
|
|
46
|
+
)
|
|
47
|
+
)
|
|
48
|
+
raise ValueError(
|
|
49
|
+
T("coal.common.errors.data_no_workspace_files").format(
|
|
50
|
+
file_prefix=file_prefix, workspace_id=workspace_id
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
return target_list
|
|
55
|
+
|
|
56
|
+
def download_workspace_file(
|
|
57
|
+
self,
|
|
58
|
+
organization_id: str,
|
|
59
|
+
workspace_id: str,
|
|
60
|
+
file_name: str,
|
|
61
|
+
target_dir: Path,
|
|
62
|
+
) -> Path:
|
|
63
|
+
if target_dir.is_file():
|
|
64
|
+
raise ValueError(T("coal.common.file_operations.not_directory").format(target_dir=target_dir))
|
|
65
|
+
|
|
66
|
+
LOGGER.info(T("coal.cosmotech_api.workspace.loading_file").format(file_name=file_name))
|
|
67
|
+
|
|
68
|
+
_file_content = self.get_workspace_file(organization_id, workspace_id, file_name)
|
|
69
|
+
|
|
70
|
+
local_target_file = target_dir / file_name
|
|
71
|
+
local_target_file.parent.mkdir(parents=True, exist_ok=True)
|
|
72
|
+
|
|
73
|
+
with open(local_target_file, "wb") as _file:
|
|
74
|
+
_file.write(_file_content)
|
|
75
|
+
|
|
76
|
+
LOGGER.info(T("coal.cosmotech_api.workspace.file_loaded").format(file=local_target_file))
|
|
77
|
+
|
|
78
|
+
return local_target_file
|
|
79
|
+
|
|
80
|
+
def upload_workspace_file(
|
|
81
|
+
self,
|
|
82
|
+
organization_id: str,
|
|
83
|
+
workspace_id: str,
|
|
84
|
+
file_path: str,
|
|
85
|
+
workspace_path: str,
|
|
86
|
+
overwrite: bool = True,
|
|
87
|
+
) -> str:
|
|
88
|
+
target_file = Path(file_path)
|
|
89
|
+
if not target_file.exists():
|
|
90
|
+
LOGGER.error(T("coal.common.file_operations.not_exists").format(file_path=file_path))
|
|
91
|
+
raise ValueError(T("coal.common.file_operations.not_exists").format(file_path=file_path))
|
|
92
|
+
if not target_file.is_file():
|
|
93
|
+
LOGGER.error(T("coal.common.file_operations.not_single_file").format(file_path=file_path))
|
|
94
|
+
raise ValueError(T("coal.common.file_operations.not_single_file").format(file_path=file_path))
|
|
95
|
+
|
|
96
|
+
destination = workspace_path + target_file.name if workspace_path.endswith("/") else workspace_path
|
|
97
|
+
|
|
98
|
+
LOGGER.info(T("coal.cosmotech_api.workspace.sending_to_api").format(destination=destination))
|
|
99
|
+
try:
|
|
100
|
+
_file = self.create_workspace_file(
|
|
101
|
+
organization_id, workspace_id, file_path, overwrite, destination=destination
|
|
102
|
+
)
|
|
103
|
+
except ApiException as e:
|
|
104
|
+
LOGGER.error(T("coal.common.file_operations.already_exists").format(csv_path=destination))
|
|
105
|
+
raise e
|
|
106
|
+
|
|
107
|
+
LOGGER.info(T("coal.cosmotech_api.workspace.file_sent").format(file=_file.file_name))
|
|
108
|
+
return _file.file_name
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Copyright (C) - 2023 - 2025 - Cosmo Tech
|
|
2
|
+
# This document and all information contained herein is the exclusive property -
|
|
3
|
+
# including all intellectual property rights pertaining thereto - of Cosmo Tech.
|
|
4
|
+
# Any use, reproduction, translation, broadcasting, transmission, distribution,
|
|
5
|
+
# etc., to any person is prohibited unless it has been previously and
|
|
6
|
+
# specifically authorized by written means by Cosmo Tech.
|
|
7
|
+
|
|
8
|
+
from cosmotech.coal.cosmotech_api.objects.connection import Connection
|
|
9
|
+
from cosmotech.coal.cosmotech_api.objects.parameters import Parameters
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Copyright (C) - 2023 - 2025 - Cosmo Tech
|
|
2
|
+
# This document and all information contained herein is the exclusive property -
|
|
3
|
+
# including all intellectual property rights pertaining thereto - of Cosmo Tech.
|
|
4
|
+
# Any use, reproduction, translation, broadcasting, transmission, distribution,
|
|
5
|
+
# etc., to any person is prohibited unless it has been previously and
|
|
6
|
+
# specifically authorized by written means by Cosmo Tech.
|
|
7
|
+
|
|
8
|
+
# Copyright (C) - 2023 - 2025 - Cosmo Tech
|
|
9
|
+
# This document and all information contained herein is the exclusive property -
|
|
10
|
+
# including all intellectual property rights pertaining thereto - of Cosmo Tech.
|
|
11
|
+
# Any use, reproduction, translation, broadcasting, transmission, distribution,
|
|
12
|
+
# etc., to any person is prohibited unless it has been previously and
|
|
13
|
+
# specifically authorized by written means by Cosmo Tech.
|
|
14
|
+
import os
|
|
15
|
+
import pathlib
|
|
16
|
+
|
|
17
|
+
import cosmotech_api
|
|
18
|
+
from cosmotech.orchestrator.utils.translate import T
|
|
19
|
+
from cosmotech_api import ApiClient
|
|
20
|
+
|
|
21
|
+
from cosmotech.coal.utils.configuration import ENVIRONMENT_CONFIGURATION, Configuration
|
|
22
|
+
from cosmotech.coal.utils.logger import LOGGER
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class Connection:
|
|
26
|
+
configuration: Configuration
|
|
27
|
+
api_client: ApiClient
|
|
28
|
+
api_type: str
|
|
29
|
+
|
|
30
|
+
# TODO :
|
|
31
|
+
# Replace use of environment variable by configuration usage
|
|
32
|
+
__api_env_keys = {"CSM_API_KEY", "CSM_API_URL"}
|
|
33
|
+
__azure_env_keys = {
|
|
34
|
+
"AZURE_CLIENT_ID",
|
|
35
|
+
"AZURE_CLIENT_SECRET",
|
|
36
|
+
"AZURE_TENANT_ID",
|
|
37
|
+
"CSM_API_URL",
|
|
38
|
+
"CSM_API_SCOPE",
|
|
39
|
+
}
|
|
40
|
+
__keycloak_env_keys = {
|
|
41
|
+
"IDP_TENANT_ID",
|
|
42
|
+
"IDP_CLIENT_ID",
|
|
43
|
+
"IDP_CLIENT_SECRET",
|
|
44
|
+
"IDP_BASE_URL",
|
|
45
|
+
"CSM_API_URL",
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
def __init__(
|
|
49
|
+
self,
|
|
50
|
+
configuration: Configuration = ENVIRONMENT_CONFIGURATION,
|
|
51
|
+
):
|
|
52
|
+
self.configuration = configuration
|
|
53
|
+
self.api_client, self.api_type = self.get_api_client()
|
|
54
|
+
|
|
55
|
+
def get_api_client(self) -> (cosmotech_api.ApiClient, str):
|
|
56
|
+
existing_keys = set(os.environ.keys())
|
|
57
|
+
missing_azure_keys = self.__azure_env_keys - existing_keys
|
|
58
|
+
missing_api_keys = self.__api_env_keys - existing_keys
|
|
59
|
+
missing_keycloak_keys = self.__keycloak_env_keys - existing_keys
|
|
60
|
+
|
|
61
|
+
if all((missing_api_keys, missing_azure_keys, missing_keycloak_keys)):
|
|
62
|
+
LOGGER.error(T("coal.common.errors.no_env_vars"))
|
|
63
|
+
LOGGER.error(T("coal.cosmotech_api.connection.existing_sets"))
|
|
64
|
+
LOGGER.error(
|
|
65
|
+
T("coal.cosmotech_api.connection.azure_connection").format(keys=", ".join(self.__azure_env_keys))
|
|
66
|
+
)
|
|
67
|
+
LOGGER.error(
|
|
68
|
+
T("coal.cosmotech_api.connection.api_key_connection").format(keys=", ".join(self.__api_env_keys))
|
|
69
|
+
)
|
|
70
|
+
LOGGER.error(
|
|
71
|
+
T("coal.cosmotech_api.connection.keycloak_connection").format(keys=", ".join(self.__keycloak_env_keys))
|
|
72
|
+
)
|
|
73
|
+
raise EnvironmentError(T("coal.common.errors.no_env_vars"))
|
|
74
|
+
|
|
75
|
+
if not missing_keycloak_keys:
|
|
76
|
+
LOGGER.debug(T("coal.cosmotech_api.connection.found_keycloak"))
|
|
77
|
+
from keycloak import KeycloakOpenID
|
|
78
|
+
|
|
79
|
+
server_url = os.environ.get("IDP_BASE_URL")
|
|
80
|
+
if server_url[-1] != "/":
|
|
81
|
+
server_url = server_url + "/"
|
|
82
|
+
keycloack_parameters = dict(
|
|
83
|
+
server_url=server_url,
|
|
84
|
+
client_id=os.environ.get("IDP_CLIENT_ID"),
|
|
85
|
+
realm_name=os.environ.get("IDP_TENANT_ID"),
|
|
86
|
+
client_secret_key=os.environ.get("IDP_CLIENT_SECRET"),
|
|
87
|
+
)
|
|
88
|
+
if (ca_cert_path := os.environ.get("IDP_CA_CERT")) and pathlib.Path(ca_cert_path).exists():
|
|
89
|
+
LOGGER.info(T("coal.cosmotech_api.connection.found_cert_authority"))
|
|
90
|
+
keycloack_parameters["verify"] = ca_cert_path
|
|
91
|
+
keycloak_openid = KeycloakOpenID(**keycloack_parameters)
|
|
92
|
+
|
|
93
|
+
access_token = keycloak_openid.token(grant_type="client_credentials")
|
|
94
|
+
|
|
95
|
+
configuration = cosmotech_api.Configuration(
|
|
96
|
+
host=os.environ.get("CSM_API_URL"),
|
|
97
|
+
access_token=access_token["access_token"],
|
|
98
|
+
)
|
|
99
|
+
return cosmotech_api.ApiClient(configuration), "Keycloak Connection"
|
|
100
|
+
|
|
101
|
+
if not missing_api_keys:
|
|
102
|
+
LOGGER.debug(T("coal.cosmotech_api.connection.found_api_key"))
|
|
103
|
+
configuration = cosmotech_api.Configuration(
|
|
104
|
+
host=os.environ.get("CSM_API_URL"),
|
|
105
|
+
)
|
|
106
|
+
return (
|
|
107
|
+
cosmotech_api.ApiClient(
|
|
108
|
+
configuration,
|
|
109
|
+
os.environ.get("CSM_API_KEY_HEADER", "X-CSM-API-KEY"),
|
|
110
|
+
os.environ.get("CSM_API_KEY"),
|
|
111
|
+
),
|
|
112
|
+
"Cosmo Tech API Key",
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
if not missing_azure_keys:
|
|
116
|
+
LOGGER.debug(T("coal.cosmotech_api.connection.found_azure"))
|
|
117
|
+
from azure.identity import EnvironmentCredential
|
|
118
|
+
|
|
119
|
+
credentials = EnvironmentCredential()
|
|
120
|
+
token = credentials.get_token(os.environ.get("CSM_API_SCOPE"))
|
|
121
|
+
|
|
122
|
+
configuration = cosmotech_api.Configuration(host=os.environ.get("CSM_API_URL"), access_token=token.token)
|
|
123
|
+
return cosmotech_api.ApiClient(configuration), "Azure Entra Connection"
|
|
124
|
+
|
|
125
|
+
raise EnvironmentError(T("coal.common.errors.no_valid_connection"))
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Copyright (C) - 2023 - 2025 - Cosmo Tech
|
|
2
|
+
# This document and all information contained herein is the exclusive property -
|
|
3
|
+
# including all intellectual property rights pertaining thereto - of Cosmo Tech.
|
|
4
|
+
# Any use, reproduction, translation, broadcasting, transmission, distribution,
|
|
5
|
+
# etc., to any person is prohibited unless it has been previously and
|
|
6
|
+
# specifically authorized by written means by Cosmo Tech.
|
|
7
|
+
import json
|
|
8
|
+
import os
|
|
9
|
+
import pathlib
|
|
10
|
+
from csv import DictWriter
|
|
11
|
+
from typing import Any, Dict, List
|
|
12
|
+
|
|
13
|
+
from cosmotech.orchestrator.utils.translate import T
|
|
14
|
+
|
|
15
|
+
from cosmotech.coal.utils.logger import LOGGER
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Parameters:
|
|
19
|
+
values: Dict[str, Any] = dict()
|
|
20
|
+
parameters_list: List[Dict[str, Any]] = list()
|
|
21
|
+
|
|
22
|
+
def __init__(self, runner_data: Any):
|
|
23
|
+
"""
|
|
24
|
+
Extract parameters from runner data.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
runner_data: Runner data object
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
Dictionary mapping parameter IDs to values
|
|
31
|
+
"""
|
|
32
|
+
for parameter in runner_data.parameters_values:
|
|
33
|
+
self.values[parameter.parameter_id] = parameter.value
|
|
34
|
+
self.parameters_list = self.format_parameters_list(runner_data)
|
|
35
|
+
|
|
36
|
+
@staticmethod
|
|
37
|
+
def format_parameters_list(runner_data: Any) -> List[Dict[str, Any]]:
|
|
38
|
+
"""
|
|
39
|
+
Format parameters from runner data as a list of dictionaries.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
runner_data: Runner data object
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
List of parameter dictionaries
|
|
46
|
+
"""
|
|
47
|
+
parameters = []
|
|
48
|
+
|
|
49
|
+
if not runner_data.parameters_values:
|
|
50
|
+
return parameters
|
|
51
|
+
|
|
52
|
+
max_name_size = max(map(lambda r: len(r.parameter_id), runner_data.parameters_values))
|
|
53
|
+
max_type_size = max(map(lambda r: len(r.var_type), runner_data.parameters_values))
|
|
54
|
+
|
|
55
|
+
for parameter_data in runner_data.parameters_values:
|
|
56
|
+
parameter_name = parameter_data.parameter_id
|
|
57
|
+
value = parameter_data.value
|
|
58
|
+
var_type = parameter_data.var_type
|
|
59
|
+
is_inherited = parameter_data.is_inherited
|
|
60
|
+
|
|
61
|
+
parameters.append(
|
|
62
|
+
{
|
|
63
|
+
"parameterId": parameter_name,
|
|
64
|
+
"value": value,
|
|
65
|
+
"varType": var_type,
|
|
66
|
+
"isInherited": is_inherited,
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
LOGGER.debug(
|
|
71
|
+
T("coal.cosmotech_api.runner.parameter_debug").format(
|
|
72
|
+
param_id=parameter_name,
|
|
73
|
+
max_name_size=max_name_size,
|
|
74
|
+
var_type=var_type,
|
|
75
|
+
max_type_size=max_type_size,
|
|
76
|
+
value=value,
|
|
77
|
+
inherited=" inherited" if is_inherited else "",
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
return parameters
|
|
82
|
+
|
|
83
|
+
def write_parameters_to_json(
|
|
84
|
+
self,
|
|
85
|
+
parameter_folder: str,
|
|
86
|
+
) -> str:
|
|
87
|
+
pathlib.Path(parameter_folder).mkdir(exist_ok=True, parents=True)
|
|
88
|
+
tmp_parameter_file = os.path.join(parameter_folder, "parameters.json")
|
|
89
|
+
|
|
90
|
+
LOGGER.info(T("coal.cosmotech_api.runner.generating_file").format(file=tmp_parameter_file))
|
|
91
|
+
|
|
92
|
+
with open(tmp_parameter_file, "w") as _file:
|
|
93
|
+
json.dump(self.parameters_list, _file, indent=2)
|
|
94
|
+
|
|
95
|
+
return tmp_parameter_file
|
|
96
|
+
|
|
97
|
+
def write_parameters_to_csv(
|
|
98
|
+
self,
|
|
99
|
+
parameter_folder: str,
|
|
100
|
+
) -> str:
|
|
101
|
+
pathlib.Path(parameter_folder).mkdir(exist_ok=True, parents=True)
|
|
102
|
+
tmp_parameter_file = os.path.join(parameter_folder, "parameters.csv")
|
|
103
|
+
|
|
104
|
+
LOGGER.info(T("coal.cosmotech_api.runner.generating_file").format(file=tmp_parameter_file))
|
|
105
|
+
|
|
106
|
+
with open(tmp_parameter_file, "w") as _file:
|
|
107
|
+
_w = DictWriter(_file, fieldnames=["parameterId", "value", "varType", "isInherited"])
|
|
108
|
+
_w.writeheader()
|
|
109
|
+
_w.writerows(self.parameters_list)
|
|
110
|
+
|
|
111
|
+
return tmp_parameter_file
|
|
112
|
+
|
|
113
|
+
def write_parameters(
|
|
114
|
+
self,
|
|
115
|
+
parameter_folder: str,
|
|
116
|
+
write_csv: bool = True,
|
|
117
|
+
write_json: bool = False,
|
|
118
|
+
) -> Dict[str, str]:
|
|
119
|
+
result = {}
|
|
120
|
+
|
|
121
|
+
if write_csv:
|
|
122
|
+
result["csv"] = self.write_parameters_to_csv(parameter_folder)
|
|
123
|
+
|
|
124
|
+
if write_json:
|
|
125
|
+
result["json"] = self.write_parameters_to_json(parameter_folder)
|
|
126
|
+
|
|
127
|
+
return result
|
|
@@ -13,83 +13,100 @@ for runner metadata operations.
|
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
15
|
from adbc_driver_postgresql import dbapi
|
|
16
|
+
from cosmotech.orchestrator.utils.translate import T
|
|
16
17
|
|
|
17
|
-
from cosmotech.coal.cosmotech_api.
|
|
18
|
-
from cosmotech.coal.
|
|
18
|
+
from cosmotech.coal.cosmotech_api.apis.runner import RunnerApi
|
|
19
|
+
from cosmotech.coal.postgresql.utils import PostgresUtils
|
|
20
|
+
from cosmotech.coal.utils.configuration import Configuration
|
|
19
21
|
from cosmotech.coal.utils.logger import LOGGER
|
|
20
|
-
from cosmotech.coal.utils.postgresql import generate_postgresql_full_uri
|
|
21
|
-
from cosmotech.orchestrator.utils.translate import T
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
def send_runner_metadata_to_postgresql(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
runner_id: str,
|
|
28
|
-
postgres_host: str,
|
|
29
|
-
postgres_port: int,
|
|
30
|
-
postgres_db: str,
|
|
31
|
-
postgres_schema: str,
|
|
32
|
-
postgres_user: str,
|
|
33
|
-
postgres_password: str,
|
|
34
|
-
table_prefix: str = "Cosmotech_",
|
|
35
|
-
force_encode: bool = False,
|
|
36
|
-
) -> None:
|
|
25
|
+
configuration: Configuration,
|
|
26
|
+
) -> str:
|
|
37
27
|
"""
|
|
38
28
|
Send runner metadata to a PostgreSQL database.
|
|
39
29
|
|
|
40
30
|
Args:
|
|
31
|
+
configuration: coal configuration
|
|
41
32
|
organization_id: Organization ID
|
|
42
33
|
workspace_id: Workspace ID
|
|
43
34
|
runner_id: Runner ID
|
|
44
|
-
postgres_host: PostgreSQL host
|
|
45
|
-
postgres_port: PostgreSQL port
|
|
46
|
-
postgres_db: PostgreSQL database name
|
|
47
|
-
postgres_schema: PostgreSQL schema
|
|
48
|
-
postgres_user: PostgreSQL username
|
|
49
|
-
postgres_password: PostgreSQL password
|
|
50
|
-
table_prefix: Table prefix
|
|
51
|
-
force_encode: force password encoding to percent encoding
|
|
52
35
|
"""
|
|
53
|
-
|
|
54
|
-
with get_api_client()[0] as api_client:
|
|
55
|
-
runner = get_runner_metadata(api_client, organization_id, workspace_id, runner_id)
|
|
36
|
+
_psql = PostgresUtils(configuration)
|
|
56
37
|
|
|
57
|
-
#
|
|
58
|
-
|
|
59
|
-
|
|
38
|
+
# Get runner metadata
|
|
39
|
+
_runner_api = RunnerApi(configuration)
|
|
40
|
+
runner = _runner_api.get_runner_metadata(
|
|
41
|
+
configuration.cosmotech.runner_id,
|
|
60
42
|
)
|
|
61
43
|
|
|
62
44
|
# Connect to PostgreSQL and update runner metadata
|
|
63
|
-
with dbapi.connect(
|
|
45
|
+
with dbapi.connect(_psql.full_uri, autocommit=True) as conn:
|
|
64
46
|
with conn.cursor() as curs:
|
|
65
|
-
schema_table = f"{
|
|
47
|
+
schema_table = f"{str(_psql.db_schema)}.{str(_psql.table_prefix)}RunnerMetadata"
|
|
66
48
|
sql_create_table = f"""
|
|
67
49
|
CREATE TABLE IF NOT EXISTS {schema_table} (
|
|
68
50
|
id varchar(32) PRIMARY KEY,
|
|
69
51
|
name varchar(256),
|
|
70
|
-
|
|
52
|
+
last_csm_run_id varchar(32),
|
|
71
53
|
run_template_id varchar(32)
|
|
72
54
|
);
|
|
73
55
|
"""
|
|
74
|
-
sql_upsert = f"""
|
|
75
|
-
INSERT INTO {schema_table} (id, name, last_run_id, run_template_id)
|
|
76
|
-
VALUES(%s, %s, %s, %s)
|
|
77
|
-
ON CONFLICT (id)
|
|
78
|
-
DO
|
|
79
|
-
UPDATE SET name = EXCLUDED.name, last_run_id = EXCLUDED.last_run_id;
|
|
80
|
-
"""
|
|
81
56
|
LOGGER.info(T("coal.services.postgresql.creating_table").format(schema_table=schema_table))
|
|
82
57
|
curs.execute(sql_create_table)
|
|
83
58
|
conn.commit()
|
|
84
59
|
LOGGER.info(T("coal.services.postgresql.metadata"))
|
|
60
|
+
sql_upsert = f"""
|
|
61
|
+
INSERT INTO {schema_table} (id, name, last_csm_run_id, run_template_id)
|
|
62
|
+
VALUES ($1, $2, $3, $4)
|
|
63
|
+
ON CONFLICT (id)
|
|
64
|
+
DO
|
|
65
|
+
UPDATE SET name = EXCLUDED.name, last_csm_run_id = EXCLUDED.last_csm_run_id;
|
|
66
|
+
"""
|
|
67
|
+
LOGGER.debug(runner)
|
|
85
68
|
curs.execute(
|
|
86
69
|
sql_upsert,
|
|
87
70
|
(
|
|
88
71
|
runner.get("id"),
|
|
89
72
|
runner.get("name"),
|
|
90
|
-
runner.get("lastRunId"),
|
|
73
|
+
runner.get("lastRunInfo").get("lastRunId"),
|
|
91
74
|
runner.get("runTemplateId"),
|
|
92
75
|
),
|
|
93
76
|
)
|
|
94
77
|
conn.commit()
|
|
95
78
|
LOGGER.info(T("coal.services.postgresql.metadata_updated"))
|
|
79
|
+
return runner.get("lastRunInfo").get("lastRunId")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def remove_runner_metadata_from_postgresql(
|
|
83
|
+
configuration: Configuration,
|
|
84
|
+
) -> str:
|
|
85
|
+
"""
|
|
86
|
+
Removes run_id from metadata table that trigger cascade delete on other tables
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
configuration: coal configuration
|
|
90
|
+
organization_id: Organization ID
|
|
91
|
+
workspace_id: Workspace ID
|
|
92
|
+
runner_id: Runner ID
|
|
93
|
+
"""
|
|
94
|
+
_psql = PostgresUtils(configuration)
|
|
95
|
+
|
|
96
|
+
# Get runner metadata
|
|
97
|
+
_runner_api = RunnerApi(configuration)
|
|
98
|
+
runner = _runner_api.get_runner_metadata(
|
|
99
|
+
configuration.cosmotech.runner_id,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# Connect to PostgreSQL and remove runner metadata row
|
|
103
|
+
with dbapi.connect(_psql.full_uri, autocommit=True) as conn:
|
|
104
|
+
with conn.cursor() as curs:
|
|
105
|
+
schema_table = f"{_psql.db_schema}.{_psql.table_prefix}RunnerMetadata"
|
|
106
|
+
sql_delete_from_metatable = f"""
|
|
107
|
+
DELETE FROM {schema_table}
|
|
108
|
+
WHERE last_csm_run_id={runner.get("lastRunId")};
|
|
109
|
+
"""
|
|
110
|
+
curs.execute(sql_delete_from_metatable)
|
|
111
|
+
conn.commit()
|
|
112
|
+
return runner.get("lastRunId")
|