Skip to content

Commit 8fdd490

Browse files
author
gdgate
authored
Merge pull request #96 from hkad98/NAS-3677
NAS-3677 add data source id validators for ldm Reviewed-by: https://github.com/pcerny
2 parents 3134906 + 9ccf773 commit 8fdd490

6 files changed

Lines changed: 540 additions & 240 deletions

File tree

gooddata-sdk/gooddata_sdk/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
SnowflakeAttributes,
2121
)
2222
from gooddata_sdk.catalog.data_source.service import CatalogDataSourceService
23+
from gooddata_sdk.catalog.data_source.validation.data_source import DataSourceValidator
2324
from gooddata_sdk.catalog.entity import BasicCredentials, TokenCredentialsFromFile
2425
from gooddata_sdk.catalog.organization.service import CatalogOrganizationService
2526
from gooddata_sdk.catalog.workspace.declarative_model.workspace.workspace import (
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# (C) 2022 GoodData Corporation
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# (C) 2022 GoodData Corporation
2+
from __future__ import annotations
3+
4+
from gooddata_sdk.catalog.data_source.service import CatalogDataSourceService
5+
from gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.ldm import CatalogDeclarativeModel
6+
7+
8+
class DataSourceValidator:
9+
def __init__(self, data_source_service: CatalogDataSourceService):
10+
self._ds_service = data_source_service
11+
12+
def validate_ldm(self, model: CatalogDeclarativeModel) -> None:
13+
if model.ldm is not None:
14+
ldm_ds_in_use = set(
15+
dataset.data_source_table_id.data_source_id
16+
for dataset in model.ldm.datasets
17+
if dataset.data_source_table_id is not None
18+
)
19+
self.validate_data_source_ids(ldm_ds_in_use)
20+
21+
def validate_data_source_ids(self, data_source_ids: set[str]) -> None:
22+
full_ds_set = set(data_source.id for data_source in self._ds_service.list_data_sources())
23+
diff_ds = data_source_ids - full_ds_set
24+
if len(diff_ds) != 0:
25+
raise ValueError(
26+
f"There are not existing data source ids in data source mapping. "
27+
f"These data source ids does not exist {', '.join(diff_ds)}"
28+
)

gooddata-sdk/gooddata_sdk/catalog/workspace/service.py

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
from __future__ import annotations
33

44
import functools
5-
import os
65
from pathlib import Path
7-
from typing import List, Union
6+
from typing import List, Optional, Union
87

98
import gooddata_afm_client.apis as afm_apis
109
import gooddata_afm_client.models as afm_models
1110
from gooddata_metadata_client.exceptions import NotFoundException
1211
from gooddata_sdk.catalog.catalog_service_base import CatalogServiceBase
12+
from gooddata_sdk.catalog.data_source.validation.data_source import DataSourceValidator
1313
from gooddata_sdk.catalog.types import ValidObjects
1414
from gooddata_sdk.catalog.workspace.declarative_model.workspace.analytics_model.analytics_model import (
1515
CatalogDeclarativeAnalytics,
@@ -109,15 +109,13 @@ def get_declarative_workspaces(self) -> CatalogDeclarativeWorkspaces:
109109
def put_declarative_workspaces(self, workspace: CatalogDeclarativeWorkspaces) -> None:
110110
self._layout_api.set_workspaces_layout(workspace.to_api())
111111

112-
def store_declarative_workspaces(self, layout_root_path: Path = Path(os.path.curdir)) -> None:
112+
def store_declarative_workspaces(self, layout_root_path: Path = Path.cwd()) -> None:
113113
self.get_declarative_workspaces().store_to_disk(self.layout_organization_folder(layout_root_path))
114114

115-
def load_declarative_workspaces(
116-
self, layout_root_path: Path = Path(os.path.curdir)
117-
) -> CatalogDeclarativeWorkspaces:
115+
def load_declarative_workspaces(self, layout_root_path: Path = Path.cwd()) -> CatalogDeclarativeWorkspaces:
118116
return CatalogDeclarativeWorkspaces.load_from_disk(self.layout_organization_folder(layout_root_path))
119117

120-
def load_and_put_declarative_workspaces(self, layout_root_path: Path = Path(os.path.curdir)) -> None:
118+
def load_and_put_declarative_workspaces(self, layout_root_path: Path = Path.cwd()) -> None:
121119
declarative_workspaces = self.load_declarative_workspaces(layout_root_path)
122120
self.put_declarative_workspaces(declarative_workspaces)
123121

@@ -264,24 +262,31 @@ def compute_valid_objects(self, workspace_id: str, ctx: ValidObjectsInputType) -
264262
def get_declarative_ldm(self, workspace_id: str) -> CatalogDeclarativeModel:
265263
return CatalogDeclarativeModel.from_api(self._layout_api.get_logical_model(workspace_id))
266264

267-
def store_declarative_ldm(self, workspace_id: str, layout_root_path: Path = Path(os.path.curdir)) -> None:
265+
def store_declarative_ldm(self, workspace_id: str, layout_root_path: Path = Path.cwd()) -> None:
268266
workspace_folder = self.layout_workspace_folder(workspace_id, layout_root_path)
269267
self.get_declarative_ldm(workspace_id).store_to_disk(workspace_folder)
270268

271269
def layout_workspace_folder(self, workspace_id: str, layout_root_path: Path) -> Path:
272270
return self.layout_organization_folder(layout_root_path) / LAYOUT_WORKSPACES_DIR / workspace_id
273271

274-
def load_declarative_ldm(
275-
self, workspace_id: str, layout_root_path: Path = Path(os.path.curdir)
276-
) -> CatalogDeclarativeModel:
272+
def load_declarative_ldm(self, workspace_id: str, layout_root_path: Path = Path.cwd()) -> CatalogDeclarativeModel:
277273
workspace_folder = self.layout_workspace_folder(workspace_id, layout_root_path)
278274
return CatalogDeclarativeModel.load_from_disk(workspace_folder)
279275

280-
def load_and_put_declarative_ldm(self, workspace_id: str, layout_root_path: Path = Path(os.path.curdir)) -> None:
276+
def load_and_put_declarative_ldm(
277+
self,
278+
workspace_id: str,
279+
layout_root_path: Path = Path.cwd(),
280+
validator: Optional[DataSourceValidator] = None,
281+
) -> None:
281282
declarative_ldm = self.load_declarative_ldm(workspace_id, layout_root_path)
282-
self.put_declarative_ldm(workspace_id, declarative_ldm)
283+
self.put_declarative_ldm(workspace_id, declarative_ldm, validator)
283284

284-
def put_declarative_ldm(self, workspace_id: str, ldm: CatalogDeclarativeModel) -> None:
285+
def put_declarative_ldm(
286+
self, workspace_id: str, ldm: CatalogDeclarativeModel, validator: Optional[DataSourceValidator] = None
287+
) -> None:
288+
if validator is not None:
289+
validator.validate_ldm(ldm)
285290
self._layout_api.set_logical_model(workspace_id, ldm.to_api())
286291

287292
def get_declarative_analytics_model(self, workspace_id: str) -> CatalogDeclarativeAnalytics:
@@ -290,21 +295,17 @@ def get_declarative_analytics_model(self, workspace_id: str) -> CatalogDeclarati
290295
def put_declarative_analytics_model(self, workspace_id: str, analytics_model: CatalogDeclarativeAnalytics) -> None:
291296
self._layout_api.set_analytics_model(workspace_id, analytics_model.to_api())
292297

293-
def store_declarative_analytics_model(
294-
self, workspace_id: str, layout_root_path: Path = Path(os.path.curdir)
295-
) -> None:
298+
def store_declarative_analytics_model(self, workspace_id: str, layout_root_path: Path = Path.cwd()) -> None:
296299
workspace_folder = self.layout_workspace_folder(workspace_id, layout_root_path)
297300
declarative_analytics_model = self.get_declarative_analytics_model(workspace_id)
298301
declarative_analytics_model.store_to_disk(workspace_folder)
299302

300303
def load_declarative_analytics_model(
301-
self, workspace_id: str, layout_root_path: Path = Path(os.path.curdir)
304+
self, workspace_id: str, layout_root_path: Path = Path.cwd()
302305
) -> CatalogDeclarativeAnalytics:
303306
workspace_folder = self.layout_workspace_folder(workspace_id, layout_root_path)
304307
return CatalogDeclarativeAnalytics.load_from_disk(workspace_folder)
305308

306-
def load_and_put_declarative_analytics_model(
307-
self, workspace_id: str, layout_root_path: Path = Path(os.path.curdir)
308-
) -> None:
309+
def load_and_put_declarative_analytics_model(self, workspace_id: str, layout_root_path: Path = Path.cwd()) -> None:
309310
declarative_analytics_model = self.load_declarative_analytics_model(workspace_id, layout_root_path)
310311
self.put_declarative_analytics_model(workspace_id, declarative_analytics_model)

0 commit comments

Comments
 (0)