gooddata-pipelines 1.52.0__py3-none-any.whl → 1.52.1.dev1__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.
Potentially problematic release.
This version of gooddata-pipelines might be problematic. Click here for more details.
- gooddata_pipelines/__init__.py +6 -0
- gooddata_pipelines/provisioning/generic/__init__.py +1 -0
- gooddata_pipelines/provisioning/generic/config.py +118 -0
- gooddata_pipelines/provisioning/generic/provision.py +49 -0
- {gooddata_pipelines-1.52.0.dist-info → gooddata_pipelines-1.52.1.dev1.dist-info}/METADATA +14 -10
- {gooddata_pipelines-1.52.0.dist-info → gooddata_pipelines-1.52.1.dev1.dist-info}/RECORD +8 -5
- {gooddata_pipelines-1.52.0.dist-info → gooddata_pipelines-1.52.1.dev1.dist-info}/WHEEL +0 -0
- {gooddata_pipelines-1.52.0.dist-info → gooddata_pipelines-1.52.1.dev1.dist-info}/licenses/LICENSE.txt +0 -0
gooddata_pipelines/__init__.py
CHANGED
|
@@ -51,6 +51,10 @@ from .provisioning.entities.workspaces.models import (
|
|
|
51
51
|
)
|
|
52
52
|
from .provisioning.entities.workspaces.workspace import WorkspaceProvisioner
|
|
53
53
|
|
|
54
|
+
# -------- Generic Provisioning --------
|
|
55
|
+
from .provisioning.generic.config import WorkflowType
|
|
56
|
+
from .provisioning.generic.provision import provision
|
|
57
|
+
|
|
54
58
|
__all__ = [
|
|
55
59
|
"BackupManager",
|
|
56
60
|
"BackupRestoreConfig",
|
|
@@ -79,5 +83,7 @@ __all__ = [
|
|
|
79
83
|
"CustomFieldDefinition",
|
|
80
84
|
"ColumnDataType",
|
|
81
85
|
"CustomFieldType",
|
|
86
|
+
"provision",
|
|
87
|
+
"WorkflowType",
|
|
82
88
|
"__version__",
|
|
83
89
|
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# (C) 2025 GoodData Corporation
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# (C) 2025 GoodData Corporation
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from typing import Type, TypeAlias
|
|
5
|
+
|
|
6
|
+
import attrs
|
|
7
|
+
|
|
8
|
+
from gooddata_pipelines.provisioning.entities.users.models.permissions import (
|
|
9
|
+
PermissionFullLoad,
|
|
10
|
+
PermissionIncrementalLoad,
|
|
11
|
+
)
|
|
12
|
+
from gooddata_pipelines.provisioning.entities.users.models.user_groups import (
|
|
13
|
+
UserGroupFullLoad,
|
|
14
|
+
UserGroupIncrementalLoad,
|
|
15
|
+
)
|
|
16
|
+
from gooddata_pipelines.provisioning.entities.users.models.users import (
|
|
17
|
+
UserFullLoad,
|
|
18
|
+
UserIncrementalLoad,
|
|
19
|
+
)
|
|
20
|
+
from gooddata_pipelines.provisioning.entities.users.permissions import (
|
|
21
|
+
PermissionProvisioner,
|
|
22
|
+
)
|
|
23
|
+
from gooddata_pipelines.provisioning.entities.users.user_groups import (
|
|
24
|
+
UserGroupProvisioner,
|
|
25
|
+
)
|
|
26
|
+
from gooddata_pipelines.provisioning.entities.users.users import UserProvisioner
|
|
27
|
+
from gooddata_pipelines.provisioning.entities.workspaces.models import (
|
|
28
|
+
WorkspaceFullLoad,
|
|
29
|
+
WorkspaceIncrementalLoad,
|
|
30
|
+
)
|
|
31
|
+
from gooddata_pipelines.provisioning.entities.workspaces.workspace import (
|
|
32
|
+
WorkspaceProvisioner,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
ValidationModel: TypeAlias = (
|
|
36
|
+
PermissionFullLoad
|
|
37
|
+
| PermissionIncrementalLoad
|
|
38
|
+
| UserFullLoad
|
|
39
|
+
| UserIncrementalLoad
|
|
40
|
+
| UserGroupFullLoad
|
|
41
|
+
| UserGroupIncrementalLoad
|
|
42
|
+
| WorkspaceFullLoad
|
|
43
|
+
| WorkspaceIncrementalLoad
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
Provisioner: TypeAlias = (
|
|
47
|
+
PermissionProvisioner
|
|
48
|
+
| UserProvisioner
|
|
49
|
+
| UserGroupProvisioner
|
|
50
|
+
| WorkspaceProvisioner
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class LoadType(str, Enum):
|
|
55
|
+
FULL = "full"
|
|
56
|
+
INCREMENTAL = "incremental"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class WorkflowType(str, Enum):
|
|
60
|
+
WORKSPACE_FULL_LOAD = "workspace_full_load"
|
|
61
|
+
WORKSPACE_INCREMENTAL_LOAD = "workspace_incremental_load"
|
|
62
|
+
USER_FULL_LOAD = "user_full_load"
|
|
63
|
+
USER_INCREMENTAL_LOAD = "user_incremental_load"
|
|
64
|
+
USER_GROUP_FULL_LOAD = "user_group_full_load"
|
|
65
|
+
USER_GROUP_INCREMENTAL_LOAD = "user_group_incremental_load"
|
|
66
|
+
PERMISSION_FULL_LOAD = "permission_full_load"
|
|
67
|
+
PERMISSION_INCREMENTAL_LOAD = "permission_incremental_load"
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@attrs.define
|
|
71
|
+
class ProvisioningConfig:
|
|
72
|
+
validation_model: Type[ValidationModel]
|
|
73
|
+
provisioner_class: Type[Provisioner]
|
|
74
|
+
load_type: LoadType
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
PROVISIONING_CONFIG = {
|
|
78
|
+
WorkflowType.WORKSPACE_FULL_LOAD: ProvisioningConfig(
|
|
79
|
+
validation_model=WorkspaceFullLoad,
|
|
80
|
+
provisioner_class=WorkspaceProvisioner,
|
|
81
|
+
load_type=LoadType.FULL,
|
|
82
|
+
),
|
|
83
|
+
WorkflowType.WORKSPACE_INCREMENTAL_LOAD: ProvisioningConfig(
|
|
84
|
+
validation_model=WorkspaceIncrementalLoad,
|
|
85
|
+
provisioner_class=WorkspaceProvisioner,
|
|
86
|
+
load_type=LoadType.INCREMENTAL,
|
|
87
|
+
),
|
|
88
|
+
WorkflowType.USER_FULL_LOAD: ProvisioningConfig(
|
|
89
|
+
validation_model=UserFullLoad,
|
|
90
|
+
provisioner_class=UserProvisioner,
|
|
91
|
+
load_type=LoadType.FULL,
|
|
92
|
+
),
|
|
93
|
+
WorkflowType.USER_INCREMENTAL_LOAD: ProvisioningConfig(
|
|
94
|
+
validation_model=UserIncrementalLoad,
|
|
95
|
+
provisioner_class=UserProvisioner,
|
|
96
|
+
load_type=LoadType.INCREMENTAL,
|
|
97
|
+
),
|
|
98
|
+
WorkflowType.USER_GROUP_FULL_LOAD: ProvisioningConfig(
|
|
99
|
+
validation_model=UserGroupFullLoad,
|
|
100
|
+
provisioner_class=UserGroupProvisioner,
|
|
101
|
+
load_type=LoadType.FULL,
|
|
102
|
+
),
|
|
103
|
+
WorkflowType.USER_GROUP_INCREMENTAL_LOAD: ProvisioningConfig(
|
|
104
|
+
validation_model=UserGroupIncrementalLoad,
|
|
105
|
+
provisioner_class=UserGroupProvisioner,
|
|
106
|
+
load_type=LoadType.INCREMENTAL,
|
|
107
|
+
),
|
|
108
|
+
WorkflowType.PERMISSION_FULL_LOAD: ProvisioningConfig(
|
|
109
|
+
validation_model=PermissionFullLoad,
|
|
110
|
+
provisioner_class=PermissionProvisioner,
|
|
111
|
+
load_type=LoadType.FULL,
|
|
112
|
+
),
|
|
113
|
+
WorkflowType.PERMISSION_INCREMENTAL_LOAD: ProvisioningConfig(
|
|
114
|
+
validation_model=PermissionIncrementalLoad,
|
|
115
|
+
provisioner_class=PermissionProvisioner,
|
|
116
|
+
load_type=LoadType.INCREMENTAL,
|
|
117
|
+
),
|
|
118
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# (C) 2025 GoodData Corporation
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from gooddata_pipelines.logger import LoggerLike
|
|
6
|
+
from gooddata_pipelines.provisioning.generic.config import (
|
|
7
|
+
PROVISIONING_CONFIG,
|
|
8
|
+
LoadType,
|
|
9
|
+
WorkflowType,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def provision(
|
|
14
|
+
data: list[dict[str, Any]],
|
|
15
|
+
workflow_type: WorkflowType,
|
|
16
|
+
host: str,
|
|
17
|
+
token: str,
|
|
18
|
+
logger: LoggerLike | None = None,
|
|
19
|
+
) -> None:
|
|
20
|
+
"""Generic provisioning function accepting raw data and workflow type.
|
|
21
|
+
|
|
22
|
+
The function will validate data based on the selected workflow type and run
|
|
23
|
+
the corresponding provisioning in full or incremental mode.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
data: List of dictionaries containing the data to be provisioned.
|
|
27
|
+
workflow_type: The type of workflow to run.
|
|
28
|
+
host: The host of the GoodData platform.
|
|
29
|
+
token: The token for the GoodData platform.
|
|
30
|
+
logger: The logger to use for logging.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
if workflow_type not in PROVISIONING_CONFIG:
|
|
34
|
+
raise ValueError(f"Invalid workflow type: {workflow_type}")
|
|
35
|
+
|
|
36
|
+
config = PROVISIONING_CONFIG[workflow_type]
|
|
37
|
+
|
|
38
|
+
provisioner = config.provisioner_class.create(host, token)
|
|
39
|
+
validated_data: list = [config.validation_model(**item) for item in data]
|
|
40
|
+
|
|
41
|
+
if logger:
|
|
42
|
+
provisioner.logger.subscribe(logger)
|
|
43
|
+
|
|
44
|
+
if config.load_type == LoadType.FULL:
|
|
45
|
+
provisioner.full_load(validated_data)
|
|
46
|
+
elif config.load_type == LoadType.INCREMENTAL:
|
|
47
|
+
provisioner.incremental_load(validated_data)
|
|
48
|
+
else:
|
|
49
|
+
raise ValueError(f"Invalid load type: {config.load_type}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gooddata-pipelines
|
|
3
|
-
Version: 1.52.
|
|
3
|
+
Version: 1.52.1.dev1
|
|
4
4
|
Summary: GoodData Cloud lifecycle automation pipelines
|
|
5
5
|
Author-email: GoodData <support@gooddata.com>
|
|
6
6
|
License: MIT
|
|
@@ -8,7 +8,7 @@ License-File: LICENSE.txt
|
|
|
8
8
|
Requires-Python: >=3.10
|
|
9
9
|
Requires-Dist: boto3-stubs<2.0.0,>=1.39.3
|
|
10
10
|
Requires-Dist: boto3<2.0.0,>=1.39.3
|
|
11
|
-
Requires-Dist: gooddata-sdk~=1.52.
|
|
11
|
+
Requires-Dist: gooddata-sdk~=1.52.1.dev1
|
|
12
12
|
Requires-Dist: pydantic<3.0.0,>=2.11.3
|
|
13
13
|
Requires-Dist: requests<3.0.0,>=2.32.3
|
|
14
14
|
Requires-Dist: types-pyyaml<7.0.0,>=6.0.12.20250326
|
|
@@ -45,33 +45,37 @@ The provisioning module exposes _Provisioner_ classes reflecting the different e
|
|
|
45
45
|
|
|
46
46
|
```python
|
|
47
47
|
import os
|
|
48
|
+
import logging
|
|
49
|
+
|
|
48
50
|
from csv import DictReader
|
|
49
51
|
from pathlib import Path
|
|
50
52
|
|
|
51
53
|
# Import the Entity Provisioner class and corresponding model from gooddata_pipelines library
|
|
52
54
|
from gooddata_pipelines import UserFullLoad, UserProvisioner
|
|
53
|
-
from gooddata_pipelines.logger.logger import LogObserver
|
|
54
|
-
|
|
55
|
-
# Optionally, subscribe a standard Python logger to the LogObserver
|
|
56
|
-
import logging
|
|
57
|
-
logger = logging.getLogger(__name__)
|
|
58
|
-
LogObserver().subscribe(logger)
|
|
59
55
|
|
|
60
56
|
# Create the Provisioner instance - you can also create the instance from a GDC yaml profile
|
|
61
57
|
provisioner = UserProvisioner(
|
|
62
58
|
host=os.environ["GDC_HOSTNAME"], token=os.environ["GDC_AUTH_TOKEN"]
|
|
63
59
|
)
|
|
64
60
|
|
|
61
|
+
# Optional: set up logging and subscribe to logs emitted by the provisioner
|
|
62
|
+
logging.basicConfig(level=logging.INFO)
|
|
63
|
+
logger = logging.getLogger(__name__)
|
|
64
|
+
provisioner.logger.subscribe(logger)
|
|
65
|
+
|
|
65
66
|
# Load your data from your data source
|
|
66
67
|
source_data_path: Path = Path("path/to/some.csv")
|
|
67
68
|
source_data_reader = DictReader(source_data_path.read_text().splitlines())
|
|
68
69
|
source_data = [row for row in source_data_reader]
|
|
69
70
|
|
|
70
|
-
# Validate your input data
|
|
71
|
+
# Validate your input data
|
|
71
72
|
full_load_data: list[UserFullLoad] = UserFullLoad.from_list_of_dicts(
|
|
72
73
|
source_data
|
|
73
74
|
)
|
|
75
|
+
|
|
76
|
+
# Run the provisioning
|
|
74
77
|
provisioner.full_load(full_load_data)
|
|
78
|
+
|
|
75
79
|
```
|
|
76
80
|
|
|
77
81
|
## Bugs & Requests
|
|
@@ -81,5 +85,5 @@ or request features.
|
|
|
81
85
|
|
|
82
86
|
## Changelog
|
|
83
87
|
|
|
84
|
-
See
|
|
88
|
+
See [Github releases](https://github.com/gooddata/gooddata-python-sdk/releases) for released versions
|
|
85
89
|
and a list of changes.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
gooddata_pipelines/__init__.py,sha256=
|
|
1
|
+
gooddata_pipelines/__init__.py,sha256=dGbyckzT8MrxL5SljSOj2jo5DFXZ2HYn0kBbAe0vO7s,2602
|
|
2
2
|
gooddata_pipelines/_version.py,sha256=Zi8Ht5ofjFeSYGG5USixQtJNB1po6okh0Rez8VyAsFM,200
|
|
3
3
|
gooddata_pipelines/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
gooddata_pipelines/api/__init__.py,sha256=0WaBI2XMdkkZgnUsQ9kqipNzh2l2zamZvUt_qjp8xCk,106
|
|
@@ -52,13 +52,16 @@ gooddata_pipelines/provisioning/entities/workspaces/workspace.py,sha256=jngaEKNl
|
|
|
52
52
|
gooddata_pipelines/provisioning/entities/workspaces/workspace_data_filters.py,sha256=0dNcK7tkp40XulCj7EPoB4zVeyQbRx2Tt4yAfgLrm50,10736
|
|
53
53
|
gooddata_pipelines/provisioning/entities/workspaces/workspace_data_parser.py,sha256=akiN8F9x-6xo7KXLJ40iOlmBImEKqWlGYlN3lpF4jQs,4562
|
|
54
54
|
gooddata_pipelines/provisioning/entities/workspaces/workspace_data_validator.py,sha256=t6RWNsrDpebyOgB4c_ctqrkio72jBHqsXqk-ntBTkA4,7225
|
|
55
|
+
gooddata_pipelines/provisioning/generic/__init__.py,sha256=-BG28PGDbalLyZGQjpFG0pjdIvtf25ut0r8ZwZVbi4s,32
|
|
56
|
+
gooddata_pipelines/provisioning/generic/config.py,sha256=RMIa7UXiXRsodsHwmg_9w74m0WLDnEF6cce0OiDZWpQ,3689
|
|
57
|
+
gooddata_pipelines/provisioning/generic/provision.py,sha256=TgBFbOroG9nHVhHQkqAmpYt2gDiaVkbMNyAVbazCwRg,1541
|
|
55
58
|
gooddata_pipelines/provisioning/utils/__init__.py,sha256=-BG28PGDbalLyZGQjpFG0pjdIvtf25ut0r8ZwZVbi4s,32
|
|
56
59
|
gooddata_pipelines/provisioning/utils/context_objects.py,sha256=HJoeumH_gXwM6X-GO3HkC4w-6RYozz6-aqQOhDnu7no,879
|
|
57
60
|
gooddata_pipelines/provisioning/utils/exceptions.py,sha256=1WnAOlPhqOf0xRcvn70lxAlLb8Oo6m6WCYS4hj9uzDU,3630
|
|
58
61
|
gooddata_pipelines/provisioning/utils/utils.py,sha256=u-nVVp6ykY4MZqRXBoPCKLrFlUunLF-cugF9SpSzL1E,2766
|
|
59
62
|
gooddata_pipelines/utils/__init__.py,sha256=s9TtSjKqo1gSGWOVoGrXaGi1TsbRowjRDYKtjmKy7BY,155
|
|
60
63
|
gooddata_pipelines/utils/rate_limiter.py,sha256=owbcEZhUxlTnE7rRHiWQ8XBC-vML2fVPbt41EeGEM7o,2002
|
|
61
|
-
gooddata_pipelines-1.52.
|
|
62
|
-
gooddata_pipelines-1.52.
|
|
63
|
-
gooddata_pipelines-1.52.
|
|
64
|
-
gooddata_pipelines-1.52.
|
|
64
|
+
gooddata_pipelines-1.52.1.dev1.dist-info/METADATA,sha256=Bq0BXaTIq36gNxCeBc63ijIms2O87QuZsDGDKg8T82o,3658
|
|
65
|
+
gooddata_pipelines-1.52.1.dev1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
66
|
+
gooddata_pipelines-1.52.1.dev1.dist-info/licenses/LICENSE.txt,sha256=PNC7WXGIo6OKkNoPLRxlVrw6jaLcjSTUsSxy9Xcu9Jo,560365
|
|
67
|
+
gooddata_pipelines-1.52.1.dev1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|