digitalhub 0.12.0__py3-none-any.whl → 0.13.0__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 digitalhub might be problematic. Click here for more details.
- digitalhub/__init__.py +1 -1
- digitalhub/context/api.py +5 -5
- digitalhub/context/builder.py +3 -5
- digitalhub/context/context.py +9 -1
- digitalhub/entities/_base/executable/entity.py +105 -57
- digitalhub/entities/_base/material/entity.py +11 -18
- digitalhub/entities/_base/material/utils.py +1 -1
- digitalhub/entities/_commons/metrics.py +64 -30
- digitalhub/entities/_commons/utils.py +36 -9
- digitalhub/entities/_processors/base.py +150 -79
- digitalhub/entities/_processors/context.py +366 -215
- digitalhub/entities/_processors/utils.py +74 -30
- digitalhub/entities/artifact/crud.py +4 -0
- digitalhub/entities/artifact/utils.py +28 -13
- digitalhub/entities/dataitem/crud.py +14 -2
- digitalhub/entities/dataitem/table/entity.py +3 -3
- digitalhub/entities/dataitem/utils.py +84 -35
- digitalhub/entities/model/crud.py +4 -0
- digitalhub/entities/model/utils.py +28 -13
- digitalhub/entities/project/_base/entity.py +0 -2
- digitalhub/entities/run/_base/entity.py +2 -2
- digitalhub/entities/task/_base/models.py +12 -3
- digitalhub/entities/trigger/_base/entity.py +11 -0
- digitalhub/factory/factory.py +25 -3
- digitalhub/factory/utils.py +11 -3
- digitalhub/runtimes/_base.py +1 -1
- digitalhub/runtimes/builder.py +18 -1
- digitalhub/stores/client/__init__.py +12 -0
- digitalhub/stores/client/_base/api_builder.py +14 -0
- digitalhub/stores/client/_base/client.py +93 -0
- digitalhub/stores/client/_base/key_builder.py +28 -0
- digitalhub/stores/client/_base/params_builder.py +14 -0
- digitalhub/stores/client/api.py +10 -5
- digitalhub/stores/client/builder.py +3 -1
- digitalhub/stores/client/dhcore/api_builder.py +17 -0
- digitalhub/stores/client/dhcore/client.py +325 -70
- digitalhub/stores/client/dhcore/configurator.py +485 -193
- digitalhub/stores/client/dhcore/enums.py +3 -0
- digitalhub/stores/client/dhcore/error_parser.py +35 -1
- digitalhub/stores/client/dhcore/params_builder.py +113 -17
- digitalhub/stores/client/dhcore/utils.py +40 -22
- digitalhub/stores/client/local/api_builder.py +17 -0
- digitalhub/stores/client/local/client.py +6 -8
- digitalhub/stores/credentials/api.py +35 -0
- digitalhub/stores/credentials/configurator.py +210 -0
- digitalhub/stores/credentials/enums.py +68 -0
- digitalhub/stores/credentials/handler.py +176 -0
- digitalhub/stores/{configurator → credentials}/ini_module.py +60 -28
- digitalhub/stores/credentials/store.py +81 -0
- digitalhub/stores/data/_base/store.py +27 -9
- digitalhub/stores/data/api.py +49 -9
- digitalhub/stores/data/builder.py +90 -41
- digitalhub/stores/data/local/store.py +4 -7
- digitalhub/stores/data/remote/store.py +4 -7
- digitalhub/stores/data/s3/configurator.py +65 -80
- digitalhub/stores/data/s3/store.py +69 -81
- digitalhub/stores/data/s3/utils.py +10 -10
- digitalhub/stores/data/sql/configurator.py +76 -73
- digitalhub/stores/data/sql/store.py +191 -102
- digitalhub/utils/exceptions.py +6 -0
- digitalhub/utils/file_utils.py +53 -30
- digitalhub/utils/generic_utils.py +41 -33
- digitalhub/utils/git_utils.py +24 -14
- digitalhub/utils/io_utils.py +19 -18
- digitalhub/utils/uri_utils.py +31 -31
- {digitalhub-0.12.0.dist-info → digitalhub-0.13.0.dist-info}/METADATA +1 -1
- {digitalhub-0.12.0.dist-info → digitalhub-0.13.0.dist-info}/RECORD +71 -74
- digitalhub/entities/_commons/types.py +0 -9
- digitalhub/stores/configurator/api.py +0 -35
- digitalhub/stores/configurator/configurator.py +0 -202
- digitalhub/stores/configurator/credentials_store.py +0 -69
- digitalhub/stores/configurator/enums.py +0 -25
- digitalhub/stores/data/s3/enums.py +0 -20
- digitalhub/stores/data/sql/enums.py +0 -20
- digitalhub/stores/data/utils.py +0 -38
- /digitalhub/stores/{configurator → credentials}/__init__.py +0 -0
- {digitalhub-0.12.0.dist-info → digitalhub-0.13.0.dist-info}/WHEEL +0 -0
- {digitalhub-0.12.0.dist-info → digitalhub-0.13.0.dist-info}/licenses/AUTHORS +0 -0
- {digitalhub-0.12.0.dist-info → digitalhub-0.13.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
+
import typing
|
|
7
8
|
from io import BytesIO
|
|
8
9
|
from pathlib import Path
|
|
9
10
|
from typing import Any, Type
|
|
@@ -11,17 +12,21 @@ from urllib.parse import urlparse
|
|
|
11
12
|
|
|
12
13
|
import boto3
|
|
13
14
|
import botocore.client # pylint: disable=unused-import
|
|
15
|
+
from boto3.s3.transfer import TransferConfig
|
|
14
16
|
from botocore.exceptions import ClientError, NoCredentialsError
|
|
15
17
|
|
|
16
|
-
from digitalhub.stores.configurator.enums import CredsOrigin
|
|
17
18
|
from digitalhub.stores.data._base.store import Store
|
|
18
|
-
from digitalhub.stores.data.s3.configurator import S3StoreConfigurator
|
|
19
19
|
from digitalhub.stores.data.s3.utils import get_bucket_name
|
|
20
20
|
from digitalhub.stores.readers.data.api import get_reader_by_object
|
|
21
|
-
from digitalhub.utils.exceptions import StoreError
|
|
21
|
+
from digitalhub.utils.exceptions import ConfigError, StoreError
|
|
22
22
|
from digitalhub.utils.file_utils import get_file_info_from_s3, get_file_mime_type
|
|
23
23
|
from digitalhub.utils.types import SourcesOrListOfSources
|
|
24
24
|
|
|
25
|
+
if typing.TYPE_CHECKING:
|
|
26
|
+
from digitalhub.stores.credentials.configurator import Configurator
|
|
27
|
+
from digitalhub.stores.data.s3.configurator import S3StoreConfigurator
|
|
28
|
+
|
|
29
|
+
|
|
25
30
|
# Type aliases
|
|
26
31
|
S3Client = Type["botocore.client.S3"]
|
|
27
32
|
|
|
@@ -32,8 +37,9 @@ class S3Store(Store):
|
|
|
32
37
|
artifacts on S3 based storage.
|
|
33
38
|
"""
|
|
34
39
|
|
|
35
|
-
def __init__(self) -> None:
|
|
36
|
-
|
|
40
|
+
def __init__(self, configurator: Configurator | None = None) -> None:
|
|
41
|
+
super().__init__(configurator)
|
|
42
|
+
self._configurator: S3StoreConfigurator
|
|
37
43
|
|
|
38
44
|
##############################
|
|
39
45
|
# I/O methods
|
|
@@ -41,9 +47,8 @@ class S3Store(Store):
|
|
|
41
47
|
|
|
42
48
|
def download(
|
|
43
49
|
self,
|
|
44
|
-
|
|
50
|
+
src: str,
|
|
45
51
|
dst: Path,
|
|
46
|
-
src: list[str],
|
|
47
52
|
overwrite: bool = False,
|
|
48
53
|
) -> str:
|
|
49
54
|
"""
|
|
@@ -51,21 +56,19 @@ class S3Store(Store):
|
|
|
51
56
|
|
|
52
57
|
Parameters
|
|
53
58
|
----------
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
src : str
|
|
60
|
+
Path of the material entity.
|
|
56
61
|
dst : str
|
|
57
|
-
The destination of the
|
|
58
|
-
src : list[str]
|
|
59
|
-
List of sources.
|
|
62
|
+
The destination of the material entity on local filesystem.
|
|
60
63
|
overwrite : bool
|
|
61
64
|
Specify if overwrite existing file(s).
|
|
62
65
|
|
|
63
66
|
Returns
|
|
64
67
|
-------
|
|
65
68
|
str
|
|
66
|
-
Destination path of the downloaded
|
|
69
|
+
Destination path of the downloaded files.
|
|
67
70
|
"""
|
|
68
|
-
client, bucket = self._check_factory(
|
|
71
|
+
client, bucket = self._check_factory(src)
|
|
69
72
|
|
|
70
73
|
# Build destination directory
|
|
71
74
|
if dst.suffix == "":
|
|
@@ -74,20 +77,13 @@ class S3Store(Store):
|
|
|
74
77
|
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
75
78
|
|
|
76
79
|
# Handle src and tree destination
|
|
77
|
-
if self.is_partition(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
trees = [k.removeprefix(strip_root) for k in keys]
|
|
82
|
-
else:
|
|
83
|
-
keys = self._build_key_from_root(root, src)
|
|
84
|
-
trees = [s for s in src]
|
|
80
|
+
if self.is_partition(src):
|
|
81
|
+
keys = self._list_objects(client, bucket, src)
|
|
82
|
+
strip_root = self._get_key(src)
|
|
83
|
+
trees = [k.removeprefix(strip_root) for k in keys]
|
|
85
84
|
else:
|
|
86
|
-
keys = [self._get_key(
|
|
87
|
-
|
|
88
|
-
trees = [Path(self._get_key(root)).name]
|
|
89
|
-
else:
|
|
90
|
-
trees = [s for s in src]
|
|
85
|
+
keys = [self._get_key(src)]
|
|
86
|
+
trees = [Path(self._get_key(src)).name]
|
|
91
87
|
|
|
92
88
|
if len(keys) != len(trees):
|
|
93
89
|
raise StoreError("Keys and trees must have the same length.")
|
|
@@ -128,7 +124,7 @@ class S3Store(Store):
|
|
|
128
124
|
src : SourcesOrListOfSources
|
|
129
125
|
Source(s).
|
|
130
126
|
dst : str
|
|
131
|
-
The destination of the
|
|
127
|
+
The destination of the material entity on storage.
|
|
132
128
|
|
|
133
129
|
Returns
|
|
134
130
|
-------
|
|
@@ -414,7 +410,7 @@ class S3Store(Store):
|
|
|
414
410
|
src : str
|
|
415
411
|
List of sources.
|
|
416
412
|
dst : str
|
|
417
|
-
The destination of the
|
|
413
|
+
The destination of the material entity on storage.
|
|
418
414
|
client : S3Client
|
|
419
415
|
The S3 client object.
|
|
420
416
|
bucket : str
|
|
@@ -457,7 +453,7 @@ class S3Store(Store):
|
|
|
457
453
|
src : list
|
|
458
454
|
List of sources.
|
|
459
455
|
dst : str
|
|
460
|
-
The destination of the
|
|
456
|
+
The destination of the material entity on storage.
|
|
461
457
|
client : S3Client
|
|
462
458
|
The S3 client object.
|
|
463
459
|
bucket : str
|
|
@@ -497,7 +493,7 @@ class S3Store(Store):
|
|
|
497
493
|
src : str
|
|
498
494
|
List of sources.
|
|
499
495
|
dst : str
|
|
500
|
-
The destination of the
|
|
496
|
+
The destination of the material entity on storage.
|
|
501
497
|
client : S3Client
|
|
502
498
|
The S3 client object.
|
|
503
499
|
bucket : str
|
|
@@ -546,7 +542,13 @@ class S3Store(Store):
|
|
|
546
542
|
mime_type = get_file_mime_type(src)
|
|
547
543
|
if mime_type is not None:
|
|
548
544
|
extra_args["ContentType"] = mime_type
|
|
549
|
-
client.upload_file(
|
|
545
|
+
client.upload_file(
|
|
546
|
+
Filename=src,
|
|
547
|
+
Bucket=bucket,
|
|
548
|
+
Key=key,
|
|
549
|
+
ExtraArgs=extra_args,
|
|
550
|
+
Config=TransferConfig(multipart_threshold=100 * 1024 * 1024),
|
|
551
|
+
)
|
|
550
552
|
|
|
551
553
|
@staticmethod
|
|
552
554
|
def _upload_fileobject(
|
|
@@ -573,7 +575,12 @@ class S3Store(Store):
|
|
|
573
575
|
-------
|
|
574
576
|
None
|
|
575
577
|
"""
|
|
576
|
-
client.
|
|
578
|
+
client.upload_fileobj(
|
|
579
|
+
Fileobj=fileobj,
|
|
580
|
+
Bucket=bucket,
|
|
581
|
+
Key=key,
|
|
582
|
+
Config=TransferConfig(multipart_threshold=100 * 1024 * 1024),
|
|
583
|
+
)
|
|
577
584
|
|
|
578
585
|
##############################
|
|
579
586
|
# Helper methods
|
|
@@ -606,55 +613,59 @@ class S3Store(Store):
|
|
|
606
613
|
"""
|
|
607
614
|
return boto3.client("s3", **cfg)
|
|
608
615
|
|
|
609
|
-
def _check_factory(self,
|
|
616
|
+
def _check_factory(self, s3_path: str, retry: bool = True) -> tuple[S3Client, str]:
|
|
610
617
|
"""
|
|
611
|
-
|
|
618
|
+
Checks if the S3 bucket collected from the URI is accessible.
|
|
619
|
+
|
|
620
|
+
Parameters
|
|
621
|
+
----------
|
|
622
|
+
s3_path : str
|
|
623
|
+
Path to the S3 bucket (e.g., 's3://bucket/path').
|
|
624
|
+
retry : bool, optional
|
|
625
|
+
Whether to retry the operation if a ConfigError is raised. Default is True.
|
|
612
626
|
|
|
613
627
|
Returns
|
|
614
628
|
-------
|
|
615
|
-
tuple
|
|
616
|
-
|
|
617
|
-
"""
|
|
618
|
-
bucket = self._get_bucket(root)
|
|
629
|
+
tuple of S3Client and str
|
|
630
|
+
Tuple containing the S3 client object and the name of the S3 bucket.
|
|
619
631
|
|
|
620
|
-
|
|
632
|
+
Raises
|
|
633
|
+
------
|
|
634
|
+
ConfigError
|
|
635
|
+
If access to the specified bucket is not available and retry is False.
|
|
636
|
+
"""
|
|
637
|
+
bucket = self._get_bucket(s3_path)
|
|
621
638
|
try:
|
|
622
|
-
cfg = self._configurator.
|
|
623
|
-
client = self._get_client(cfg)
|
|
624
|
-
self._check_access_to_storage(client, bucket)
|
|
625
|
-
|
|
626
|
-
# Fallback to file
|
|
627
|
-
except StoreError:
|
|
628
|
-
cfg = self._configurator.get_boto3_client_config(CredsOrigin.FILE.value)
|
|
639
|
+
cfg = self._configurator.get_client_config()
|
|
629
640
|
client = self._get_client(cfg)
|
|
630
641
|
self._check_access_to_storage(client, bucket)
|
|
631
|
-
|
|
632
|
-
|
|
642
|
+
return client, bucket
|
|
643
|
+
except ConfigError as e:
|
|
644
|
+
if retry:
|
|
645
|
+
self._configurator.eval_change_origin()
|
|
646
|
+
return self._check_factory(s3_path, False)
|
|
647
|
+
raise e
|
|
633
648
|
|
|
634
649
|
def _check_access_to_storage(self, client: S3Client, bucket: str) -> None:
|
|
635
650
|
"""
|
|
636
|
-
|
|
651
|
+
Checks if the S3 bucket is accessible by sending a head_bucket request.
|
|
637
652
|
|
|
638
653
|
Parameters
|
|
639
654
|
----------
|
|
640
655
|
client : S3Client
|
|
641
|
-
|
|
656
|
+
S3 client object.
|
|
642
657
|
bucket : str
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
Returns
|
|
646
|
-
-------
|
|
647
|
-
None
|
|
658
|
+
Name of the S3 bucket.
|
|
648
659
|
|
|
649
660
|
Raises
|
|
650
661
|
------
|
|
651
|
-
|
|
662
|
+
ConfigError
|
|
652
663
|
If access to the specified bucket is not available.
|
|
653
664
|
"""
|
|
654
665
|
try:
|
|
655
666
|
client.head_bucket(Bucket=bucket)
|
|
656
667
|
except (ClientError, NoCredentialsError) as err:
|
|
657
|
-
raise
|
|
668
|
+
raise ConfigError(f"No access to s3 bucket! Error: {err}")
|
|
658
669
|
|
|
659
670
|
@staticmethod
|
|
660
671
|
def _get_key(path: str) -> str:
|
|
@@ -676,29 +687,6 @@ class S3Store(Store):
|
|
|
676
687
|
key = key[1:]
|
|
677
688
|
return key
|
|
678
689
|
|
|
679
|
-
def _build_key_from_root(self, root: str, paths: list[str]) -> list[str]:
|
|
680
|
-
"""
|
|
681
|
-
Method to build object path.
|
|
682
|
-
|
|
683
|
-
Parameters
|
|
684
|
-
----------
|
|
685
|
-
root : str
|
|
686
|
-
The root of the object path.
|
|
687
|
-
paths : list[str]
|
|
688
|
-
The path to build.
|
|
689
|
-
|
|
690
|
-
Returns
|
|
691
|
-
-------
|
|
692
|
-
list[str]
|
|
693
|
-
List of keys.
|
|
694
|
-
"""
|
|
695
|
-
keys = []
|
|
696
|
-
for path in paths:
|
|
697
|
-
clean_path = self._get_key(path)
|
|
698
|
-
key = self._get_key(f"{root}{clean_path}")
|
|
699
|
-
keys.append(key)
|
|
700
|
-
return keys
|
|
701
|
-
|
|
702
690
|
def _list_objects(self, client: S3Client, bucket: str, partition: str) -> list[str]:
|
|
703
691
|
"""
|
|
704
692
|
List objects in a S3 partition.
|
|
@@ -9,41 +9,41 @@ from urllib.parse import urlparse
|
|
|
9
9
|
|
|
10
10
|
from boto3 import client as boto3_client
|
|
11
11
|
|
|
12
|
-
from digitalhub.stores.
|
|
12
|
+
from digitalhub.stores.credentials.enums import CredsOrigin
|
|
13
13
|
from digitalhub.stores.data.s3.configurator import S3StoreConfigurator
|
|
14
14
|
from digitalhub.utils.exceptions import StoreError
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def get_bucket_name(path: str) -> str:
|
|
18
18
|
"""
|
|
19
|
-
|
|
19
|
+
Extract the bucket name from an S3 path.
|
|
20
20
|
|
|
21
21
|
Parameters
|
|
22
22
|
----------
|
|
23
23
|
path : str
|
|
24
|
-
|
|
24
|
+
S3 URI (e.g., 's3://bucket/key').
|
|
25
25
|
|
|
26
26
|
Returns
|
|
27
27
|
-------
|
|
28
28
|
str
|
|
29
|
-
The bucket name.
|
|
29
|
+
The bucket name extracted from the URI.
|
|
30
30
|
"""
|
|
31
31
|
return urlparse(path).netloc
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
def get_bucket_and_key(path: str) -> tuple[str, str]:
|
|
35
35
|
"""
|
|
36
|
-
|
|
36
|
+
Extract the bucket name and key from an S3 path.
|
|
37
37
|
|
|
38
38
|
Parameters
|
|
39
39
|
----------
|
|
40
40
|
path : str
|
|
41
|
-
|
|
41
|
+
S3 URI (e.g., 's3://bucket/key').
|
|
42
42
|
|
|
43
43
|
Returns
|
|
44
44
|
-------
|
|
45
|
-
tuple
|
|
46
|
-
|
|
45
|
+
tuple of str
|
|
46
|
+
Tuple containing (bucket, key) extracted from the URI.
|
|
47
47
|
"""
|
|
48
48
|
parsed = urlparse(path)
|
|
49
49
|
return parsed.netloc, parsed.path
|
|
@@ -51,7 +51,7 @@ def get_bucket_and_key(path: str) -> tuple[str, str]:
|
|
|
51
51
|
|
|
52
52
|
def get_s3_source(bucket: str, key: str, filename: Path) -> None:
|
|
53
53
|
"""
|
|
54
|
-
|
|
54
|
+
Download an object from S3 and save it to a local file.
|
|
55
55
|
|
|
56
56
|
Parameters
|
|
57
57
|
----------
|
|
@@ -60,7 +60,7 @@ def get_s3_source(bucket: str, key: str, filename: Path) -> None:
|
|
|
60
60
|
key : str
|
|
61
61
|
S3 object key.
|
|
62
62
|
filename : Path
|
|
63
|
-
|
|
63
|
+
Local path where the downloaded object will be saved.
|
|
64
64
|
|
|
65
65
|
Returns
|
|
66
66
|
-------
|
|
@@ -4,114 +4,117 @@
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
-
from digitalhub.stores.
|
|
8
|
-
from digitalhub.stores.
|
|
9
|
-
from digitalhub.stores.data.sql.enums import SqlStoreEnv
|
|
10
|
-
from digitalhub.utils.exceptions import StoreError
|
|
7
|
+
from digitalhub.stores.credentials.configurator import Configurator
|
|
8
|
+
from digitalhub.stores.credentials.enums import CredsEnvVar
|
|
11
9
|
|
|
12
10
|
|
|
13
|
-
class SqlStoreConfigurator:
|
|
11
|
+
class SqlStoreConfigurator(Configurator):
|
|
14
12
|
"""
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
SQL store configuration manager for database connections.
|
|
14
|
+
|
|
15
|
+
Handles credential management and configuration for SQL database
|
|
16
|
+
connections. Loads credentials from environment variables or
|
|
17
|
+
configuration files and provides connection string generation
|
|
18
|
+
for database access.
|
|
19
|
+
|
|
20
|
+
Attributes
|
|
21
|
+
----------
|
|
22
|
+
keys : list[str]
|
|
23
|
+
List of all supported credential keys for SQL connections.
|
|
24
|
+
required_keys : list[str]
|
|
25
|
+
List of mandatory credential keys that must be provided.
|
|
17
26
|
"""
|
|
18
27
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
keys = [
|
|
29
|
+
CredsEnvVar.DB_USERNAME.value,
|
|
30
|
+
CredsEnvVar.DB_PASSWORD.value,
|
|
31
|
+
CredsEnvVar.DB_HOST.value,
|
|
32
|
+
CredsEnvVar.DB_PORT.value,
|
|
33
|
+
CredsEnvVar.DB_DATABASE.value,
|
|
34
|
+
CredsEnvVar.DB_PLATFORM.value,
|
|
25
35
|
]
|
|
36
|
+
required_keys = [
|
|
37
|
+
CredsEnvVar.DB_USERNAME.value,
|
|
38
|
+
CredsEnvVar.DB_PASSWORD.value,
|
|
39
|
+
CredsEnvVar.DB_HOST.value,
|
|
40
|
+
CredsEnvVar.DB_PORT.value,
|
|
41
|
+
CredsEnvVar.DB_DATABASE.value,
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
def __init__(self):
|
|
45
|
+
super().__init__()
|
|
46
|
+
self.load_configs()
|
|
26
47
|
|
|
27
48
|
##############################
|
|
28
49
|
# Configuration methods
|
|
29
50
|
##############################
|
|
30
51
|
|
|
31
|
-
def
|
|
52
|
+
def load_env_vars(self) -> None:
|
|
32
53
|
"""
|
|
33
|
-
|
|
54
|
+
Load database credentials from environment variables.
|
|
34
55
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
The origin of the credentials.
|
|
56
|
+
Retrieves SQL database connection credentials from the system
|
|
57
|
+
environment variables and stores them in the configurator's
|
|
58
|
+
credential handler for use in database connections.
|
|
39
59
|
|
|
40
60
|
Returns
|
|
41
61
|
-------
|
|
42
|
-
|
|
43
|
-
The connection string.
|
|
44
|
-
"""
|
|
45
|
-
if origin == CredsOrigin.ENV.value:
|
|
46
|
-
creds = self._get_env_config()
|
|
47
|
-
elif origin == CredsOrigin.FILE.value:
|
|
48
|
-
creds = self._get_file_config()
|
|
49
|
-
else:
|
|
50
|
-
raise StoreError(f"Unknown origin: {origin}")
|
|
51
|
-
|
|
52
|
-
user = creds[SqlStoreEnv.USERNAME.value]
|
|
53
|
-
password = creds[SqlStoreEnv.PASSWORD.value]
|
|
54
|
-
host = creds[SqlStoreEnv.HOST.value]
|
|
55
|
-
port = creds[SqlStoreEnv.PORT.value]
|
|
56
|
-
database = creds[SqlStoreEnv.DATABASE.value]
|
|
57
|
-
return f"postgresql://{user}:{password}@{host}:{port}/{database}"
|
|
58
|
-
|
|
59
|
-
def _get_env_config(self) -> dict:
|
|
62
|
+
None
|
|
60
63
|
"""
|
|
61
|
-
|
|
64
|
+
env_creds = self._creds_handler.load_from_env(self.keys)
|
|
65
|
+
self._creds_handler.set_credentials(self._env, env_creds)
|
|
62
66
|
|
|
63
|
-
|
|
64
|
-
-------
|
|
65
|
-
dict
|
|
66
|
-
The credentials.
|
|
67
|
+
def load_file_vars(self) -> None:
|
|
67
68
|
"""
|
|
68
|
-
|
|
69
|
-
self._set_credentials(credentials)
|
|
70
|
-
return credentials
|
|
69
|
+
Load database credentials from configuration file.
|
|
71
70
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
Retrieves SQL database connection credentials from a
|
|
72
|
+
configuration file and stores them in the configurator's
|
|
73
|
+
credential handler for use in database connections.
|
|
75
74
|
|
|
76
75
|
Returns
|
|
77
76
|
-------
|
|
78
|
-
|
|
79
|
-
The credentials.
|
|
77
|
+
None
|
|
80
78
|
"""
|
|
81
|
-
|
|
82
|
-
self.
|
|
83
|
-
return credentials
|
|
79
|
+
file_creds = self._creds_handler.load_from_file(self.keys)
|
|
80
|
+
self._creds_handler.set_credentials(self._file, file_creds)
|
|
84
81
|
|
|
85
|
-
def
|
|
82
|
+
def get_sql_conn_string(self) -> str:
|
|
86
83
|
"""
|
|
87
|
-
|
|
84
|
+
Generate PostgreSQL connection string from stored credentials.
|
|
88
85
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
The credentials.
|
|
86
|
+
Constructs a PostgreSQL connection string using the configured
|
|
87
|
+
database credentials including username, password, host, port,
|
|
88
|
+
and database name.
|
|
93
89
|
|
|
94
90
|
Returns
|
|
95
91
|
-------
|
|
96
|
-
|
|
92
|
+
str
|
|
93
|
+
A PostgreSQL connection string in the format:
|
|
94
|
+
'postgresql://username:password@host:port/database'
|
|
97
95
|
"""
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
96
|
+
creds = self.get_sql_credentials()
|
|
97
|
+
user = creds[CredsEnvVar.DB_USERNAME.value]
|
|
98
|
+
password = creds[CredsEnvVar.DB_PASSWORD.value]
|
|
99
|
+
host = creds[CredsEnvVar.DB_HOST.value]
|
|
100
|
+
port = creds[CredsEnvVar.DB_PORT.value]
|
|
101
|
+
database = creds[CredsEnvVar.DB_DATABASE.value]
|
|
102
|
+
return f"postgresql://{user}:{password}@{host}:{port}/{database}"
|
|
101
103
|
|
|
102
|
-
def
|
|
104
|
+
def get_sql_credentials(self) -> dict:
|
|
103
105
|
"""
|
|
104
|
-
|
|
106
|
+
Get all configured database credentials as a dictionary.
|
|
105
107
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
The credentials.
|
|
108
|
+
Retrieves all available database credentials from the configured
|
|
109
|
+
source and returns them as a dictionary with all credential keys
|
|
110
|
+
from self.keys mapped to their values.
|
|
110
111
|
|
|
111
112
|
Returns
|
|
112
113
|
-------
|
|
113
|
-
|
|
114
|
+
dict
|
|
115
|
+
Dictionary containing all credential key-value pairs from self.keys.
|
|
116
|
+
Keys correspond to database connection parameters such as
|
|
117
|
+
username, password, host, port, database, and platform.
|
|
114
118
|
"""
|
|
115
|
-
|
|
116
|
-
for key
|
|
117
|
-
configurator.set_credential(key, value)
|
|
119
|
+
creds = self.get_credentials(self._origin)
|
|
120
|
+
return {key: creds.get(key) for key in self.keys}
|