digitalkin 0.1.1__py3-none-any.whl → 0.2.1__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.
- base_server/__init__.py +1 -0
- base_server/mock/__init__.py +5 -0
- base_server/mock/mock_pb2.py +39 -0
- base_server/mock/mock_pb2_grpc.py +102 -0
- base_server/server_async_insecure.py +124 -0
- base_server/server_async_secure.py +142 -0
- base_server/server_sync_insecure.py +102 -0
- base_server/server_sync_secure.py +121 -0
- digitalkin/__init__.py +1 -11
- digitalkin/__version__.py +1 -4
- digitalkin/{grpc → grpc_servers}/__init__.py +1 -13
- digitalkin/{grpc → grpc_servers}/_base_server.py +3 -3
- digitalkin/{grpc → grpc_servers}/module_server.py +31 -13
- digitalkin/{grpc → grpc_servers}/module_servicer.py +30 -14
- digitalkin/{grpc → grpc_servers}/registry_server.py +13 -8
- digitalkin/{grpc → grpc_servers}/registry_servicer.py +8 -2
- digitalkin/{grpc → grpc_servers}/utils/factory.py +6 -4
- digitalkin/grpc_servers/utils/grpc_client_wrapper.py +68 -0
- digitalkin/{grpc → grpc_servers}/utils/models.py +1 -1
- digitalkin/models/__init__.py +1 -4
- digitalkin/models/module/__init__.py +8 -2
- digitalkin/models/module/module_types.py +10 -0
- digitalkin/models/services/__init__.py +0 -5
- digitalkin/modules/__init__.py +3 -3
- digitalkin/modules/_base_module.py +64 -27
- digitalkin/modules/archetype_module.py +2 -6
- digitalkin/modules/job_manager.py +46 -28
- digitalkin/modules/tool_module.py +3 -7
- digitalkin/modules/trigger_module.py +2 -7
- digitalkin/services/__init__.py +7 -9
- digitalkin/services/agent/__init__.py +2 -2
- digitalkin/services/agent/agent_strategy.py +3 -6
- digitalkin/services/agent/default_agent.py +1 -4
- digitalkin/services/base_strategy.py +18 -0
- digitalkin/services/cost/__init__.py +4 -3
- digitalkin/services/cost/cost_strategy.py +35 -5
- digitalkin/services/cost/default_cost.py +22 -5
- digitalkin/services/cost/grpc_cost.py +81 -0
- digitalkin/services/filesystem/__init__.py +4 -3
- digitalkin/services/filesystem/default_filesystem.py +197 -17
- digitalkin/services/filesystem/filesystem_strategy.py +54 -15
- digitalkin/services/filesystem/grpc_filesystem.py +209 -0
- digitalkin/services/identity/__init__.py +2 -2
- digitalkin/services/identity/default_identity.py +1 -1
- digitalkin/services/identity/identity_strategy.py +3 -1
- digitalkin/services/registry/__init__.py +2 -2
- digitalkin/services/registry/default_registry.py +1 -4
- digitalkin/services/registry/registry_strategy.py +3 -6
- digitalkin/services/services_config.py +176 -0
- digitalkin/services/services_models.py +61 -0
- digitalkin/services/setup/default_setup.py +222 -0
- digitalkin/services/setup/grpc_setup.py +307 -0
- digitalkin/services/setup/setup_strategy.py +145 -0
- digitalkin/services/snapshot/__init__.py +2 -2
- digitalkin/services/snapshot/default_snapshot.py +1 -1
- digitalkin/services/snapshot/snapshot_strategy.py +3 -4
- digitalkin/services/storage/__init__.py +4 -3
- digitalkin/services/storage/default_storage.py +184 -57
- digitalkin/services/storage/grpc_storage.py +76 -170
- digitalkin/services/storage/storage_strategy.py +195 -24
- digitalkin/utils/arg_parser.py +16 -17
- {digitalkin-0.1.1.dist-info → digitalkin-0.2.1.dist-info}/METADATA +8 -7
- digitalkin-0.2.1.dist-info/RECORD +78 -0
- {digitalkin-0.1.1.dist-info → digitalkin-0.2.1.dist-info}/WHEEL +1 -1
- digitalkin-0.2.1.dist-info/top_level.txt +3 -0
- modules/__init__.py +0 -0
- modules/minimal_llm_module.py +162 -0
- modules/storage_module.py +187 -0
- modules/text_transform_module.py +201 -0
- digitalkin/services/default_service.py +0 -13
- digitalkin/services/development_service.py +0 -10
- digitalkin/services/service_provider.py +0 -27
- digitalkin-0.1.1.dist-info/RECORD +0 -59
- digitalkin-0.1.1.dist-info/top_level.txt +0 -1
- /digitalkin/{grpc → grpc_servers}/utils/exceptions.py +0 -0
- /digitalkin/{grpc → grpc_servers}/utils/types.py +0 -0
- {digitalkin-0.1.1.dist-info → digitalkin-0.2.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"""This module contains the abstract base class for setup strategies."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import secrets
|
|
5
|
+
import string
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from pydantic import ValidationError
|
|
9
|
+
|
|
10
|
+
from digitalkin.services.setup.grpc_setup import SetupData, SetupVersionData
|
|
11
|
+
from digitalkin.services.setup.setup_strategy import SetupServiceError, SetupStrategy
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class DefaultSetup(SetupStrategy):
|
|
17
|
+
"""Abstract base class for setup strategies."""
|
|
18
|
+
|
|
19
|
+
setups: dict[str, SetupData]
|
|
20
|
+
setup_versions: dict[str, dict[str, SetupVersionData]]
|
|
21
|
+
|
|
22
|
+
def __init__(self) -> None:
|
|
23
|
+
"""Initialize the default setup strategy."""
|
|
24
|
+
super().__init__()
|
|
25
|
+
self.setups = {}
|
|
26
|
+
self.setup_versions = {}
|
|
27
|
+
|
|
28
|
+
def create_setup(self, setup_dict: dict[str, Any]) -> str:
|
|
29
|
+
"""Create a new setup with comprehensive validation.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
setup_dict: Dictionary containing setup details.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
bool: Success status of setup creation.
|
|
36
|
+
|
|
37
|
+
Raises:
|
|
38
|
+
ValidationError: If setup data is invalid.
|
|
39
|
+
GrpcOperationError: If gRPC operation fails.
|
|
40
|
+
"""
|
|
41
|
+
try:
|
|
42
|
+
valid_data = SetupData.model_validate(setup_dict["data"]) # Revalidates instance
|
|
43
|
+
except ValidationError:
|
|
44
|
+
logger.exception("Validation failed for model SetupData")
|
|
45
|
+
return ""
|
|
46
|
+
|
|
47
|
+
setup_id = setup_dict.get(
|
|
48
|
+
"setup_id", "".join(secrets.choice(string.ascii_letters + string.digits) for _ in range(16))
|
|
49
|
+
)
|
|
50
|
+
valid_data.id = setup_id
|
|
51
|
+
self.setups[setup_id] = valid_data
|
|
52
|
+
logger.info("CREATE SETUP DATA %s:%s succesfull", setup_id, valid_data)
|
|
53
|
+
return setup_id
|
|
54
|
+
|
|
55
|
+
def get_setup(self, setup_dict: dict[str, Any]) -> SetupData:
|
|
56
|
+
"""Retrieve a setup by its unique identifier.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
setup_dict: Dictionary with 'name' and optional 'version'.
|
|
60
|
+
|
|
61
|
+
Raises:
|
|
62
|
+
SetupServiceError: setup_id does not exist.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
Dict[str, Any]: Setup details including optional setup version.
|
|
66
|
+
"""
|
|
67
|
+
logger.info("GET setup_id = %s", setup_dict["setup_id"])
|
|
68
|
+
if setup_dict["setup_id"] not in self.setups:
|
|
69
|
+
msg = f"GET setup_id = {setup_dict['setup_id']}: setup_id DOESN'T EXIST"
|
|
70
|
+
logger.error(msg)
|
|
71
|
+
raise SetupServiceError(msg)
|
|
72
|
+
return self.setups[setup_dict["setup_id"]]
|
|
73
|
+
|
|
74
|
+
def update_setup(self, setup_dict: dict[str, Any]) -> bool:
|
|
75
|
+
"""Update an existing setup.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
setup_dict: Dictionary with setup update details.
|
|
79
|
+
|
|
80
|
+
Raises:
|
|
81
|
+
ValidationError: setup object failed validation.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
bool: Success status of the update operation.
|
|
85
|
+
"""
|
|
86
|
+
if setup_dict["setup_id"] not in self.setups:
|
|
87
|
+
logger.info("UPDATE setup_id = %s: setup_id DOESN'T EXIST", setup_dict["setup_id"])
|
|
88
|
+
return False
|
|
89
|
+
|
|
90
|
+
try:
|
|
91
|
+
valid_data = SetupData.model_validate(setup_dict["data"]) # Revalidates instance
|
|
92
|
+
except ValidationError:
|
|
93
|
+
logger.exception("Validation failed for model SetupData")
|
|
94
|
+
return False
|
|
95
|
+
|
|
96
|
+
self.setups[setup_dict["update_id"]] = valid_data
|
|
97
|
+
return True
|
|
98
|
+
|
|
99
|
+
def delete_setup(self, setup_dict: dict[str, Any]) -> bool:
|
|
100
|
+
"""Delete a setup by its unique identifier.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
setup_dict: Dictionary with the setup 'name'.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
bool: Success status of deletion.
|
|
107
|
+
"""
|
|
108
|
+
if setup_dict["setup_id"] not in self.setups:
|
|
109
|
+
logger.info("UPDATE setup_id = %s: setup_id DOESN'T EXIST", setup_dict["setup_id"])
|
|
110
|
+
return False
|
|
111
|
+
del self.setups[setup_dict["setup_id"]]
|
|
112
|
+
return True
|
|
113
|
+
|
|
114
|
+
def create_setup_version(self, setup_version_dict: dict[str, Any]) -> str:
|
|
115
|
+
"""Create a new setup version.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
setup_version_dict: Dictionary with setup version details.
|
|
119
|
+
|
|
120
|
+
Raises:
|
|
121
|
+
SetupServiceError: setup object failed validation.
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
str: version of setup version creation.
|
|
125
|
+
"""
|
|
126
|
+
try:
|
|
127
|
+
valid_data = SetupVersionData.model_validate(setup_version_dict["data"]) # Revalidates instance
|
|
128
|
+
except ValidationError:
|
|
129
|
+
msg = "Validation failed for model SetupVersionData"
|
|
130
|
+
logger.exception(msg)
|
|
131
|
+
raise SetupServiceError(msg)
|
|
132
|
+
|
|
133
|
+
if setup_version_dict["setup_id"] not in self.setup_versions:
|
|
134
|
+
self.setup_versions[setup_version_dict["setup_id"]] = {}
|
|
135
|
+
self.setup_versions[setup_version_dict["setup_id"]][valid_data.version] = valid_data
|
|
136
|
+
logger.info("CREATE SETUP VERSION DATA %s:%s succesfull", setup_version_dict["setup_id"], valid_data)
|
|
137
|
+
return valid_data.version
|
|
138
|
+
|
|
139
|
+
def get_setup_version(self, setup_version_dict: dict[str, Any]) -> SetupVersionData:
|
|
140
|
+
"""Retrieve a setup version by its unique identifier.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
setup_version_dict: Dictionary with the setup version 'name'.
|
|
144
|
+
|
|
145
|
+
Raises:
|
|
146
|
+
SetupServiceError: setup_id does not exist.
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
Dict[str, Any]: Setup version details.
|
|
150
|
+
"""
|
|
151
|
+
logger.info("GET setup_id = %s: version = %s", setup_version_dict["setup_id"], setup_version_dict["version"])
|
|
152
|
+
if setup_version_dict["setup_id"] not in self.setup_versions:
|
|
153
|
+
msg = f"GET setup_id = {setup_version_dict['setup_id']}: setup_id DOESN'T EXIST"
|
|
154
|
+
logger.error(msg)
|
|
155
|
+
raise SetupServiceError(msg)
|
|
156
|
+
|
|
157
|
+
return self.setup_versions[setup_version_dict["setup_id"]][setup_version_dict["version"]]
|
|
158
|
+
|
|
159
|
+
def search_setup_versions(self, setup_version_dict: dict[str, Any]) -> list[SetupVersionData]:
|
|
160
|
+
"""Search for setup versions based on filters.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
setup_version_dict: Dictionary with optional 'name' or 'query_versions' filters.
|
|
164
|
+
|
|
165
|
+
Raises:
|
|
166
|
+
SetupServiceError: setup_id does not exist.
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
List[SetupVersionData]: A list of matching setup version details.
|
|
170
|
+
"""
|
|
171
|
+
if setup_version_dict["setup_id"] not in self.setup_versions:
|
|
172
|
+
msg = f"GET setup_id = {setup_version_dict['setup_id']}: setup_id DOESN'T EXIST"
|
|
173
|
+
logger.error(msg)
|
|
174
|
+
raise SetupServiceError(msg)
|
|
175
|
+
|
|
176
|
+
return [
|
|
177
|
+
value
|
|
178
|
+
for value in setup_version_dict["setup_id"].values()
|
|
179
|
+
if setup_version_dict["query_versions"] in value.version or setup_version_dict["name"] in value.name
|
|
180
|
+
]
|
|
181
|
+
|
|
182
|
+
def update_setup_version(self, setup_version_dict: dict[str, Any]) -> bool:
|
|
183
|
+
"""Update an existing setup version.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
setup_version_dict: Dictionary with setup version update details.
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
bool: Success status of the update operation.
|
|
190
|
+
"""
|
|
191
|
+
if setup_version_dict["setup_id"] not in self.setup_versions:
|
|
192
|
+
logger.info("UPDATE setup_id = %s: setup_id DOESN'T EXIST", setup_version_dict["setup_id"])
|
|
193
|
+
return False
|
|
194
|
+
|
|
195
|
+
if setup_version_dict["version"] not in self.setup_versions["setup_id"]:
|
|
196
|
+
logger.info("UPDATE setup_id = %s: setup_id DOESN'T EXIST", setup_version_dict["setup_id"])
|
|
197
|
+
return False
|
|
198
|
+
|
|
199
|
+
try:
|
|
200
|
+
valid_data = SetupVersionData.model_validate(setup_version_dict["data"])
|
|
201
|
+
except ValidationError:
|
|
202
|
+
logger.exception("Validation failed for model SetupVersionData")
|
|
203
|
+
return False
|
|
204
|
+
|
|
205
|
+
self.setup_versions[setup_version_dict["setup_id"]][setup_version_dict["version"]] = valid_data
|
|
206
|
+
return True
|
|
207
|
+
|
|
208
|
+
def delete_setup_version(self, setup_version_dict: dict[str, Any]) -> bool:
|
|
209
|
+
"""Delete a setup version by its unique identifier.
|
|
210
|
+
|
|
211
|
+
Args:
|
|
212
|
+
setup_version_dict: Dictionary with the setup version 'name'.
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
bool: Success status of version deletion.
|
|
216
|
+
"""
|
|
217
|
+
if setup_version_dict["setup_id"] not in self.setup_versions:
|
|
218
|
+
logger.info("UPDATE setup_id = %s: setup_id DOESN'T EXIST", setup_version_dict["setup_id"])
|
|
219
|
+
return False
|
|
220
|
+
|
|
221
|
+
del self.setup_versions[setup_version_dict["setup_id"]][setup_version_dict["version"]]
|
|
222
|
+
return True
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
"""Digital Kin Setup Service gRPC Client."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from collections.abc import Generator
|
|
5
|
+
from contextlib import contextmanager
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
import grpc
|
|
9
|
+
from digitalkin_proto.digitalkin.setup.v2 import (
|
|
10
|
+
setup_pb2,
|
|
11
|
+
setup_service_pb2_grpc,
|
|
12
|
+
)
|
|
13
|
+
from google.protobuf import json_format
|
|
14
|
+
from google.protobuf.struct_pb2 import Struct
|
|
15
|
+
from pydantic import ValidationError
|
|
16
|
+
|
|
17
|
+
from digitalkin.grpc_servers.utils.exceptions import ServerError
|
|
18
|
+
from digitalkin.grpc_servers.utils.grpc_client_wrapper import GrpcClientWrapper
|
|
19
|
+
from digitalkin.grpc_servers.utils.models import ServerConfig
|
|
20
|
+
from digitalkin.services.setup.setup_strategy import SetupData, SetupServiceError, SetupStrategy, SetupVersionData
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class GrpcSetup(SetupStrategy, GrpcClientWrapper):
|
|
26
|
+
"""This class implements the gRPC setup service."""
|
|
27
|
+
|
|
28
|
+
def __post_init__(self, config: ServerConfig) -> None:
|
|
29
|
+
"""Init the channel from a config file.
|
|
30
|
+
|
|
31
|
+
Need to be call if the user register a gRPC channel.
|
|
32
|
+
"""
|
|
33
|
+
channel = self._init_channel(config)
|
|
34
|
+
self.stub = setup_service_pb2_grpc.SetupServiceStub(channel)
|
|
35
|
+
logger.info("Channel client 'setup' initialized succesfully")
|
|
36
|
+
|
|
37
|
+
@contextmanager
|
|
38
|
+
def _handle_grpc_errors(self, operation: str) -> Generator[Any, Any, Any]: # noqa: PLR6301
|
|
39
|
+
"""Context manager for consistent gRPC error handling.
|
|
40
|
+
|
|
41
|
+
Yields:
|
|
42
|
+
Allow error handling in context.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
operation: Description of the operation being performed.
|
|
46
|
+
|
|
47
|
+
Raises:
|
|
48
|
+
ValueError: Error wiht the model validation.
|
|
49
|
+
ServerError: from gRPC Client.
|
|
50
|
+
SetupServiceError: setup service internal.
|
|
51
|
+
"""
|
|
52
|
+
try:
|
|
53
|
+
yield
|
|
54
|
+
except ValidationError as e:
|
|
55
|
+
msg = f"Invalid data for {operation}"
|
|
56
|
+
logger.exception(msg)
|
|
57
|
+
raise ValueError(msg) from e
|
|
58
|
+
except grpc.RpcError as e:
|
|
59
|
+
msg = f"gRPC {operation} failed: {e}"
|
|
60
|
+
logger.exception(msg)
|
|
61
|
+
raise ServerError(msg) from e
|
|
62
|
+
except Exception as e:
|
|
63
|
+
msg = f"Unexpected error in {operation}"
|
|
64
|
+
logger.exception(msg)
|
|
65
|
+
raise SetupServiceError(msg) from e
|
|
66
|
+
|
|
67
|
+
def create_setup(self, setup_dict: dict[str, Any]) -> str:
|
|
68
|
+
"""Create a new setup with comprehensive validation.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
setup_dict: Dictionary containing setup details.
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
bool: Success status of setup creation.
|
|
75
|
+
|
|
76
|
+
Raises:
|
|
77
|
+
ValidationError: If setup data is invalid.
|
|
78
|
+
ServerError: If gRPC operation fails.
|
|
79
|
+
SetupServiceError: For any unexpected internal error.
|
|
80
|
+
"""
|
|
81
|
+
with self._handle_grpc_errors("Setup Creation"):
|
|
82
|
+
valid_data = SetupData.model_validate(setup_dict)
|
|
83
|
+
|
|
84
|
+
request = setup_pb2.CreateSetupRequest(
|
|
85
|
+
name=valid_data.name,
|
|
86
|
+
organisation_id=valid_data.organisation_id,
|
|
87
|
+
owner_id=valid_data.owner_id,
|
|
88
|
+
module_id=valid_data.module_id,
|
|
89
|
+
current_setup_version=setup_pb2.SetupVersion(**valid_data.current_setup_version.model_dump()),
|
|
90
|
+
)
|
|
91
|
+
response = self.exec_grpc_query("CreateSetup", request)
|
|
92
|
+
logger.info("Setup '%s' query sent successfully", valid_data.name)
|
|
93
|
+
return response
|
|
94
|
+
|
|
95
|
+
def get_setup(self, setup_dict: dict[str, Any]) -> SetupData:
|
|
96
|
+
"""Retrieve a setup by its unique identifier.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
setup_dict: Dictionary with 'name' and optional 'version'.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
dict[str, Any]: Setup details including optional setup version.
|
|
103
|
+
|
|
104
|
+
Raises:
|
|
105
|
+
ValidationError: If the setup name is missing.
|
|
106
|
+
ServerError: If gRPC operation fails.
|
|
107
|
+
SetupServiceError: For any unexpected internal error.
|
|
108
|
+
"""
|
|
109
|
+
with self._handle_grpc_errors("Get Setup"):
|
|
110
|
+
if "setup_id" not in setup_dict:
|
|
111
|
+
msg = "Setup name is required"
|
|
112
|
+
raise ValidationError(msg)
|
|
113
|
+
request = setup_pb2.GetSetupRequest(
|
|
114
|
+
setup_id=setup_dict["setup_id"],
|
|
115
|
+
version=setup_dict.get("version", ""),
|
|
116
|
+
)
|
|
117
|
+
response = self.exec_grpc_query("GetSetup", request)
|
|
118
|
+
response_data = json_format.MessageToDict(response, preserving_proto_field_name=True)
|
|
119
|
+
return SetupData(**response_data["setup"])
|
|
120
|
+
|
|
121
|
+
def update_setup(self, setup_dict: dict[str, Any]) -> bool:
|
|
122
|
+
"""Update an existing setup.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
setup_dict: Dictionary with setup update details.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
bool: Success status of the update operation.
|
|
129
|
+
|
|
130
|
+
Raises:
|
|
131
|
+
ValidationError: If setup data is invalid.
|
|
132
|
+
ServerError: If gRPC operation fails.
|
|
133
|
+
SetupServiceError: For any unexpected internal error.
|
|
134
|
+
"""
|
|
135
|
+
current_setup_version = None
|
|
136
|
+
|
|
137
|
+
with self._handle_grpc_errors("Setup Update"):
|
|
138
|
+
valid_data = SetupData.model_validate(setup_dict)
|
|
139
|
+
|
|
140
|
+
if valid_data.current_setup_version is not None:
|
|
141
|
+
current_setup_version = setup_pb2.SetupVersion(**valid_data.current_setup_version.model_dump())
|
|
142
|
+
|
|
143
|
+
request = setup_pb2.UpdateSetupRequest(
|
|
144
|
+
name=valid_data.name,
|
|
145
|
+
owner_id=valid_data.owner_id or "",
|
|
146
|
+
current_setup_version=current_setup_version,
|
|
147
|
+
)
|
|
148
|
+
response = self.exec_grpc_query("UpdateSetup", request)
|
|
149
|
+
logger.info("Setup '%s' query sent successfully", valid_data.name)
|
|
150
|
+
return getattr(response, "success", False)
|
|
151
|
+
|
|
152
|
+
def delete_setup(self, setup_dict: dict[str, Any]) -> bool:
|
|
153
|
+
"""Delete a setup by its unique identifier.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
setup_dict: Dictionary with the setup 'setup_id'.
|
|
157
|
+
|
|
158
|
+
Returns:
|
|
159
|
+
bool: Success status of deletion.
|
|
160
|
+
|
|
161
|
+
Raises:
|
|
162
|
+
ValidationError: If the setup setup_id is missing.
|
|
163
|
+
ServerError: If gRPC operation fails.
|
|
164
|
+
SetupServiceError: For any unexpected internal error.
|
|
165
|
+
"""
|
|
166
|
+
with self._handle_grpc_errors("Setup Deletion"):
|
|
167
|
+
setup_id = setup_dict.get("setup_id")
|
|
168
|
+
if not setup_id:
|
|
169
|
+
msg = "Setup name is required for deletion"
|
|
170
|
+
raise ValidationError(msg)
|
|
171
|
+
request = setup_pb2.DeleteSetupRequest(setup_id=setup_id)
|
|
172
|
+
response = self.exec_grpc_query("DeleteSetup", request)
|
|
173
|
+
logger.info("Setup '%s' query sent successfully", setup_id)
|
|
174
|
+
return getattr(response, "success", False)
|
|
175
|
+
|
|
176
|
+
def create_setup_version(self, setup_version_dict: dict[str, Any]) -> str:
|
|
177
|
+
"""Create a new setup version.
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
setup_version_dict: Dictionary with setup version details.
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
str: version of setup version creation.
|
|
184
|
+
|
|
185
|
+
Raises:
|
|
186
|
+
ValidationError: If setup version data is invalid.
|
|
187
|
+
ServerError: If gRPC operation fails.
|
|
188
|
+
SetupServiceError: For any unexpected internal error.
|
|
189
|
+
"""
|
|
190
|
+
with self._handle_grpc_errors("Setup Version Creation"):
|
|
191
|
+
valid_data = SetupVersionData.model_validate(setup_version_dict)
|
|
192
|
+
content_struct = Struct()
|
|
193
|
+
content_struct.update(valid_data.content)
|
|
194
|
+
request = setup_pb2.CreateSetupVersionRequest(
|
|
195
|
+
setup_id=valid_data.setup_id,
|
|
196
|
+
version=valid_data.version,
|
|
197
|
+
content=content_struct,
|
|
198
|
+
)
|
|
199
|
+
logger.info(
|
|
200
|
+
"Setup Version '%s' for setup '%s' query sent successfully",
|
|
201
|
+
valid_data.version,
|
|
202
|
+
valid_data.setup_id,
|
|
203
|
+
)
|
|
204
|
+
return self.exec_grpc_query("CreateSetupVersion", request)
|
|
205
|
+
|
|
206
|
+
def get_setup_version(self, setup_version_dict: dict[str, Any]) -> SetupVersionData:
|
|
207
|
+
"""Retrieve a setup version by its unique identifier.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
setup_version_dict: Dictionary with the setup version 'setup_version_id'.
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
dict[str, Any]: Setup version details.
|
|
214
|
+
|
|
215
|
+
Raises:
|
|
216
|
+
ValidationError: If the setup version id is missing.
|
|
217
|
+
ServerError: If gRPC operation fails.
|
|
218
|
+
SetupServiceError: For any unexpected internal error.
|
|
219
|
+
"""
|
|
220
|
+
with self._handle_grpc_errors("Get Setup Version"):
|
|
221
|
+
setup_version_id = setup_version_dict.get("setup_version_id")
|
|
222
|
+
if not setup_version_id:
|
|
223
|
+
msg = "Setup version id is required"
|
|
224
|
+
raise ValidationError(msg)
|
|
225
|
+
request = setup_pb2.GetSetupVersionRequest(setup_version_id=setup_version_id)
|
|
226
|
+
response = self.exec_grpc_query("GetSetupVersion", request)
|
|
227
|
+
return SetupVersionData(**json_format.MessageToDict(response.setup_version))
|
|
228
|
+
|
|
229
|
+
def search_setup_versions(self, setup_version_dict: dict[str, Any]) -> list[SetupVersionData]:
|
|
230
|
+
"""Search for setup versions based on filters.
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
setup_version_dict: Dictionary with optional 'name' and 'version' filters.
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
list[dict[str, Any]]: A list of matching setup version details.
|
|
237
|
+
|
|
238
|
+
Raises:
|
|
239
|
+
ServerError: If gRPC operation fails.
|
|
240
|
+
SetupServiceError: For any unexpected internal error.
|
|
241
|
+
ValidationError: If both name and version are not provided.
|
|
242
|
+
"""
|
|
243
|
+
with self._handle_grpc_errors("Search Setup Versions"):
|
|
244
|
+
if "name" not in setup_version_dict and "version" not in setup_version_dict:
|
|
245
|
+
msg = "Either name or version must be provided"
|
|
246
|
+
raise ValidationError(msg)
|
|
247
|
+
request = setup_pb2.SearchSetupVersionsRequest(
|
|
248
|
+
setup_id=setup_version_dict.get("setup_id", ""),
|
|
249
|
+
version=setup_version_dict.get("version", ""),
|
|
250
|
+
)
|
|
251
|
+
response = self.exec_grpc_query("SearchSetupVersions", request)
|
|
252
|
+
return [SetupVersionData(**json_format.MessageToDict(sv)) for sv in response.setup_versions]
|
|
253
|
+
|
|
254
|
+
def update_setup_version(self, setup_version_dict: dict[str, Any]) -> bool:
|
|
255
|
+
"""Update an existing setup version.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
setup_version_dict: Dictionary with setup version update details.
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
bool: Success status of the update operation.
|
|
262
|
+
|
|
263
|
+
Raises:
|
|
264
|
+
ValidationError: If setup version data is invalid.
|
|
265
|
+
ServerError: If gRPC operation fails.
|
|
266
|
+
SetupServiceError: For any unexpected internal error.
|
|
267
|
+
"""
|
|
268
|
+
with self._handle_grpc_errors("Setup Version Update"):
|
|
269
|
+
valid_data = SetupVersionData.model_validate(setup_version_dict)
|
|
270
|
+
content_struct = Struct()
|
|
271
|
+
content_struct.update(valid_data.content)
|
|
272
|
+
request = setup_pb2.UpdateSetupVersionRequest(
|
|
273
|
+
setup_version_id=valid_data.id,
|
|
274
|
+
version=valid_data.version,
|
|
275
|
+
content=content_struct,
|
|
276
|
+
)
|
|
277
|
+
response = self.exec_grpc_query("UpdateSetupVersion", request)
|
|
278
|
+
logger.info(
|
|
279
|
+
"Setup Version '%s' for setup '%s' query sent successfully",
|
|
280
|
+
valid_data.id,
|
|
281
|
+
valid_data.setup_id,
|
|
282
|
+
)
|
|
283
|
+
return getattr(response, "success", False)
|
|
284
|
+
|
|
285
|
+
def delete_setup_version(self, setup_version_dict: dict[str, Any]) -> bool:
|
|
286
|
+
"""Delete a setup version by its unique identifier.
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
setup_version_dict: Dictionary with the setup version 'name'.
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
bool: Success status of version deletion.
|
|
293
|
+
|
|
294
|
+
Raises:
|
|
295
|
+
ValidationError: If the setup version name is missing.
|
|
296
|
+
ServerError: If gRPC operation fails.
|
|
297
|
+
SetupServiceError: For any unexpected internal error.
|
|
298
|
+
"""
|
|
299
|
+
with self._handle_grpc_errors("Setup Version Deletion"):
|
|
300
|
+
setup_version_id = setup_version_dict.get("setup_version_id")
|
|
301
|
+
if not setup_version_id:
|
|
302
|
+
msg = "Setup version id is required for deletion"
|
|
303
|
+
raise ValidationError(msg)
|
|
304
|
+
request = setup_pb2.DeleteSetupVersionRequest(setup_version_id=setup_version_id)
|
|
305
|
+
response = self.exec_grpc_query("DeleteSetupVersion", request)
|
|
306
|
+
logger.info("Setup Version '%s' query sent successfully", setup_version_id)
|
|
307
|
+
return getattr(response, "success", False)
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""This module contains the abstract base class for setup strategies."""
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
from abc import ABC, abstractmethod
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class SetupServiceError(Exception):
|
|
11
|
+
"""Base exception for Setup service errors."""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SetupVersionData(BaseModel):
|
|
15
|
+
"""Pydantic model for SetupVersion data validation."""
|
|
16
|
+
|
|
17
|
+
id: str
|
|
18
|
+
setup_id: str
|
|
19
|
+
version: str
|
|
20
|
+
content: dict[str, Any]
|
|
21
|
+
creation_date: datetime.datetime
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class SetupData(BaseModel):
|
|
25
|
+
"""Pydantic model for Setup data validation."""
|
|
26
|
+
|
|
27
|
+
id: str
|
|
28
|
+
name: str
|
|
29
|
+
organisation_id: str
|
|
30
|
+
owner_id: str
|
|
31
|
+
module_id: str
|
|
32
|
+
current_setup_version: SetupVersionData
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class SetupStrategy(ABC):
|
|
36
|
+
"""Abstract base class for setup strategies."""
|
|
37
|
+
|
|
38
|
+
def __init__(self) -> None:
|
|
39
|
+
"""Initialize the setup strategy."""
|
|
40
|
+
|
|
41
|
+
def __post_init__(self, *args, **kwargs) -> None: # noqa: ANN002, ANN003
|
|
42
|
+
"""Initialize the setup strategy."""
|
|
43
|
+
|
|
44
|
+
@abstractmethod
|
|
45
|
+
def create_setup(self, setup_dict: dict[str, Any]) -> str:
|
|
46
|
+
"""Create a new setup with comprehensive validation.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
setup_dict: Dictionary containing setup details.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
bool: Success status of setup creation.
|
|
53
|
+
|
|
54
|
+
Raises:
|
|
55
|
+
ValidationError: If setup data is invalid.
|
|
56
|
+
GrpcOperationError: If gRPC operation fails.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
@abstractmethod
|
|
60
|
+
def get_setup(self, setup_dict: dict[str, Any]) -> SetupData:
|
|
61
|
+
"""Retrieve a setup by its unique identifier.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
setup_dict: Dictionary with 'name' and optional 'version'.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
Dict[str, Any]: Setup details including optional setup version.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
@abstractmethod
|
|
71
|
+
def update_setup(self, setup_dict: dict[str, Any]) -> bool:
|
|
72
|
+
"""Update an existing setup.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
setup_dict: Dictionary with setup update details.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
bool: Success status of the update operation.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
@abstractmethod
|
|
82
|
+
def delete_setup(self, setup_dict: dict[str, Any]) -> bool:
|
|
83
|
+
"""Delete a setup by its unique identifier.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
setup_dict: Dictionary with the setup 'name'.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
bool: Success status of deletion.
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
@abstractmethod
|
|
93
|
+
def create_setup_version(self, setup_version_dict: dict[str, Any]) -> str:
|
|
94
|
+
"""Create a new setup version.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
setup_version_dict: Dictionary with setup version details.
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
str: name of setup version creation.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
@abstractmethod
|
|
104
|
+
def get_setup_version(self, setup_version_dict: dict[str, Any]) -> SetupVersionData:
|
|
105
|
+
"""Retrieve a setup version by its unique identifier.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
setup_version_dict: Dictionary with the setup version 'name'.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
Dict[str, Any]: Setup version details.
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
@abstractmethod
|
|
115
|
+
def search_setup_versions(self, setup_version_dict: dict[str, Any]) -> list[SetupVersionData]:
|
|
116
|
+
"""Search for setup versions based on filters.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
setup_version_dict: Dictionary with optional 'name' and 'version' filters.
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
List[Dict[str, Any]]: A list of matching setup version details.
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
@abstractmethod
|
|
126
|
+
def update_setup_version(self, setup_version_dict: dict[str, Any]) -> bool:
|
|
127
|
+
"""Update an existing setup version.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
setup_version_dict: Dictionary with setup version update details.
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
bool: Success status of the update operation.
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
@abstractmethod
|
|
137
|
+
def delete_setup_version(self, setup_version_dict: dict[str, Any]) -> bool:
|
|
138
|
+
"""Delete a setup version by its unique identifier.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
setup_version_dict: Dictionary with the setup version 'name'.
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
bool: Success status of version deletion.
|
|
145
|
+
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""This module is responsible for handling the snapshot service."""
|
|
2
2
|
|
|
3
|
-
from .default_snapshot import DefaultSnapshot
|
|
4
|
-
from .snapshot_strategy import SnapshotStrategy
|
|
3
|
+
from digitalkin.services.snapshot.default_snapshot import DefaultSnapshot
|
|
4
|
+
from digitalkin.services.snapshot.snapshot_strategy import SnapshotStrategy
|
|
5
5
|
|
|
6
6
|
__all__ = ["DefaultSnapshot", "SnapshotStrategy"]
|