digitalhub 0.13.0b2__py3-none-any.whl → 0.13.0b4__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/material/entity.py +3 -3
- 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 +363 -212
- digitalhub/entities/_processors/utils.py +74 -30
- digitalhub/entities/artifact/utils.py +28 -13
- digitalhub/entities/dataitem/crud.py +10 -2
- digitalhub/entities/dataitem/table/entity.py +3 -3
- digitalhub/entities/dataitem/utils.py +84 -35
- digitalhub/entities/model/utils.py +28 -13
- digitalhub/entities/task/_base/models.py +12 -3
- 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 +276 -58
- digitalhub/stores/client/dhcore/configurator.py +336 -141
- digitalhub/stores/client/dhcore/error_parser.py +35 -1
- digitalhub/stores/client/dhcore/params_builder.py +113 -17
- digitalhub/stores/client/dhcore/utils.py +32 -14
- digitalhub/stores/client/local/api_builder.py +17 -0
- digitalhub/stores/client/local/client.py +6 -8
- digitalhub/stores/credentials/api.py +8 -8
- digitalhub/stores/credentials/configurator.py +176 -3
- digitalhub/stores/credentials/enums.py +17 -3
- digitalhub/stores/credentials/handler.py +73 -45
- digitalhub/stores/credentials/ini_module.py +59 -27
- digitalhub/stores/credentials/store.py +33 -1
- digitalhub/stores/data/_base/store.py +8 -3
- digitalhub/stores/data/api.py +20 -16
- digitalhub/stores/data/builder.py +69 -13
- digitalhub/stores/data/s3/configurator.py +64 -23
- digitalhub/stores/data/s3/store.py +30 -27
- digitalhub/stores/data/s3/utils.py +9 -9
- digitalhub/stores/data/sql/configurator.py +76 -25
- digitalhub/stores/data/sql/store.py +180 -91
- 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.13.0b2.dist-info → digitalhub-0.13.0b4.dist-info}/METADATA +1 -1
- {digitalhub-0.13.0b2.dist-info → digitalhub-0.13.0b4.dist-info}/RECORD +60 -61
- digitalhub/entities/_commons/types.py +0 -9
- {digitalhub-0.13.0b2.dist-info → digitalhub-0.13.0b4.dist-info}/WHEEL +0 -0
- {digitalhub-0.13.0b2.dist-info → digitalhub-0.13.0b4.dist-info}/licenses/AUTHORS +0 -0
- {digitalhub-0.13.0b2.dist-info → digitalhub-0.13.0b4.dist-info}/licenses/LICENSE +0 -0
|
@@ -4,8 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
+
from datetime import datetime, timezone
|
|
8
|
+
|
|
7
9
|
from botocore.config import Config
|
|
8
10
|
|
|
11
|
+
from digitalhub.stores.client.dhcore.utils import refresh_token
|
|
9
12
|
from digitalhub.stores.credentials.configurator import Configurator
|
|
10
13
|
from digitalhub.stores.credentials.enums import CredsEnvVar
|
|
11
14
|
|
|
@@ -17,17 +20,19 @@ class S3StoreConfigurator(Configurator):
|
|
|
17
20
|
"""
|
|
18
21
|
|
|
19
22
|
keys = [
|
|
20
|
-
CredsEnvVar.S3_ENDPOINT_URL,
|
|
21
|
-
CredsEnvVar.S3_ACCESS_KEY_ID,
|
|
22
|
-
CredsEnvVar.S3_SECRET_ACCESS_KEY,
|
|
23
|
-
CredsEnvVar.S3_REGION,
|
|
24
|
-
CredsEnvVar.S3_SIGNATURE_VERSION,
|
|
25
|
-
CredsEnvVar.S3_SESSION_TOKEN,
|
|
23
|
+
CredsEnvVar.S3_ENDPOINT_URL.value,
|
|
24
|
+
CredsEnvVar.S3_ACCESS_KEY_ID.value,
|
|
25
|
+
CredsEnvVar.S3_SECRET_ACCESS_KEY.value,
|
|
26
|
+
CredsEnvVar.S3_REGION.value,
|
|
27
|
+
CredsEnvVar.S3_SIGNATURE_VERSION.value,
|
|
28
|
+
CredsEnvVar.S3_SESSION_TOKEN.value,
|
|
29
|
+
CredsEnvVar.S3_PATH_STYLE.value,
|
|
30
|
+
CredsEnvVar.S3_CREDENTIALS_EXPIRATION.value,
|
|
26
31
|
]
|
|
27
32
|
required_keys = [
|
|
28
|
-
CredsEnvVar.S3_ENDPOINT_URL,
|
|
29
|
-
CredsEnvVar.S3_ACCESS_KEY_ID,
|
|
30
|
-
CredsEnvVar.S3_SECRET_ACCESS_KEY,
|
|
33
|
+
CredsEnvVar.S3_ENDPOINT_URL.value,
|
|
34
|
+
CredsEnvVar.S3_ACCESS_KEY_ID.value,
|
|
35
|
+
CredsEnvVar.S3_SECRET_ACCESS_KEY.value,
|
|
31
36
|
]
|
|
32
37
|
|
|
33
38
|
def __init__(self):
|
|
@@ -38,30 +43,43 @@ class S3StoreConfigurator(Configurator):
|
|
|
38
43
|
# Configuration methods
|
|
39
44
|
##############################
|
|
40
45
|
|
|
41
|
-
def
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
def load_env_vars(self) -> None:
|
|
47
|
+
"""
|
|
48
|
+
Loads the credentials from the environment variables.
|
|
49
|
+
|
|
50
|
+
Returns
|
|
51
|
+
-------
|
|
52
|
+
None
|
|
53
|
+
"""
|
|
54
|
+
env_creds = self._creds_handler.load_from_env(self.keys)
|
|
44
55
|
self._creds_handler.set_credentials(self._env, env_creds)
|
|
45
56
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
57
|
+
def load_file_vars(self) -> None:
|
|
58
|
+
"""
|
|
59
|
+
Loads the credentials from a file.
|
|
49
60
|
|
|
50
|
-
|
|
61
|
+
Returns
|
|
62
|
+
-------
|
|
63
|
+
None
|
|
51
64
|
"""
|
|
52
|
-
|
|
65
|
+
file_creds = self._creds_handler.load_from_file(self.keys)
|
|
66
|
+
self._creds_handler.set_credentials(self._file, file_creds)
|
|
53
67
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
The origin of the credentials.
|
|
68
|
+
def get_client_config(self) -> dict:
|
|
69
|
+
"""
|
|
70
|
+
Gets S3 credentials (access key, secret key, session token, and other config).
|
|
58
71
|
|
|
59
72
|
Returns
|
|
60
73
|
-------
|
|
61
74
|
dict
|
|
62
|
-
|
|
75
|
+
Dictionary containing S3 credentials and configuration.
|
|
63
76
|
"""
|
|
64
|
-
creds = self.get_credentials(
|
|
77
|
+
creds = self.get_credentials(self._origin)
|
|
78
|
+
expired = creds[CredsEnvVar.S3_CREDENTIALS_EXPIRATION.value]
|
|
79
|
+
if self._origin == self._file and self._is_expired(expired):
|
|
80
|
+
refresh_token()
|
|
81
|
+
self.load_file_vars()
|
|
82
|
+
creds = self.get_credentials(self._origin)
|
|
65
83
|
return {
|
|
66
84
|
"endpoint_url": creds[CredsEnvVar.S3_ENDPOINT_URL.value],
|
|
67
85
|
"aws_access_key_id": creds[CredsEnvVar.S3_ACCESS_KEY_ID.value],
|
|
@@ -72,3 +90,26 @@ class S3StoreConfigurator(Configurator):
|
|
|
72
90
|
signature_version=creds[CredsEnvVar.S3_SIGNATURE_VERSION.value],
|
|
73
91
|
),
|
|
74
92
|
}
|
|
93
|
+
|
|
94
|
+
@staticmethod
|
|
95
|
+
def _is_expired(timestamp: str | None) -> bool:
|
|
96
|
+
"""
|
|
97
|
+
Determines whether a given timestamp is after the current UTC time.
|
|
98
|
+
|
|
99
|
+
Parameters
|
|
100
|
+
----------
|
|
101
|
+
timestamp : str or None
|
|
102
|
+
Timestamp string in the format 'YYYY-MM-DDTHH:MM:SSZ'.
|
|
103
|
+
|
|
104
|
+
Returns
|
|
105
|
+
-------
|
|
106
|
+
bool
|
|
107
|
+
True if the given timestamp is later than the current UTC time,
|
|
108
|
+
otherwise False.
|
|
109
|
+
"""
|
|
110
|
+
if timestamp is None:
|
|
111
|
+
return False
|
|
112
|
+
dt = datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%SZ")
|
|
113
|
+
dt = dt.replace(tzinfo=timezone.utc)
|
|
114
|
+
now = datetime.now(timezone.utc) + datetime.timedelta(seconds=120)
|
|
115
|
+
return dt < now
|
|
@@ -15,11 +15,10 @@ import botocore.client # pylint: disable=unused-import
|
|
|
15
15
|
from boto3.s3.transfer import TransferConfig
|
|
16
16
|
from botocore.exceptions import ClientError, NoCredentialsError
|
|
17
17
|
|
|
18
|
-
from digitalhub.stores.credentials.enums import CredsOrigin
|
|
19
18
|
from digitalhub.stores.data._base.store import Store
|
|
20
19
|
from digitalhub.stores.data.s3.utils import get_bucket_name
|
|
21
20
|
from digitalhub.stores.readers.data.api import get_reader_by_object
|
|
22
|
-
from digitalhub.utils.exceptions import StoreError
|
|
21
|
+
from digitalhub.utils.exceptions import ConfigError, StoreError
|
|
23
22
|
from digitalhub.utils.file_utils import get_file_info_from_s3, get_file_mime_type
|
|
24
23
|
from digitalhub.utils.types import SourcesOrListOfSources
|
|
25
24
|
|
|
@@ -614,55 +613,59 @@ class S3Store(Store):
|
|
|
614
613
|
"""
|
|
615
614
|
return boto3.client("s3", **cfg)
|
|
616
615
|
|
|
617
|
-
def _check_factory(self,
|
|
616
|
+
def _check_factory(self, s3_path: str, retry: bool = True) -> tuple[S3Client, str]:
|
|
618
617
|
"""
|
|
619
|
-
|
|
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.
|
|
620
626
|
|
|
621
627
|
Returns
|
|
622
628
|
-------
|
|
623
|
-
tuple
|
|
624
|
-
|
|
625
|
-
"""
|
|
626
|
-
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.
|
|
627
631
|
|
|
628
|
-
|
|
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)
|
|
629
638
|
try:
|
|
630
|
-
cfg = self._configurator.get_client_config(
|
|
639
|
+
cfg = self._configurator.get_client_config()
|
|
631
640
|
client = self._get_client(cfg)
|
|
632
641
|
self._check_access_to_storage(client, bucket)
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
return client, bucket
|
|
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
|
|
641
648
|
|
|
642
649
|
def _check_access_to_storage(self, client: S3Client, bucket: str) -> None:
|
|
643
650
|
"""
|
|
644
|
-
|
|
651
|
+
Checks if the S3 bucket is accessible by sending a head_bucket request.
|
|
645
652
|
|
|
646
653
|
Parameters
|
|
647
654
|
----------
|
|
648
655
|
client : S3Client
|
|
649
|
-
|
|
656
|
+
S3 client object.
|
|
650
657
|
bucket : str
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
Returns
|
|
654
|
-
-------
|
|
655
|
-
None
|
|
658
|
+
Name of the S3 bucket.
|
|
656
659
|
|
|
657
660
|
Raises
|
|
658
661
|
------
|
|
659
|
-
|
|
662
|
+
ConfigError
|
|
660
663
|
If access to the specified bucket is not available.
|
|
661
664
|
"""
|
|
662
665
|
try:
|
|
663
666
|
client.head_bucket(Bucket=bucket)
|
|
664
667
|
except (ClientError, NoCredentialsError) as err:
|
|
665
|
-
raise
|
|
668
|
+
raise ConfigError(f"No access to s3 bucket! Error: {err}")
|
|
666
669
|
|
|
667
670
|
@staticmethod
|
|
668
671
|
def _get_key(path: str) -> str:
|
|
@@ -16,34 +16,34 @@ from digitalhub.utils.exceptions import StoreError
|
|
|
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
|
-------
|
|
@@ -10,23 +10,35 @@ from digitalhub.stores.credentials.enums import CredsEnvVar
|
|
|
10
10
|
|
|
11
11
|
class SqlStoreConfigurator(Configurator):
|
|
12
12
|
"""
|
|
13
|
-
|
|
14
|
-
|
|
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.
|
|
15
26
|
"""
|
|
16
27
|
|
|
17
28
|
keys = [
|
|
18
|
-
CredsEnvVar.DB_USERNAME,
|
|
19
|
-
CredsEnvVar.DB_PASSWORD,
|
|
20
|
-
CredsEnvVar.DB_HOST,
|
|
21
|
-
CredsEnvVar.DB_PORT,
|
|
22
|
-
CredsEnvVar.DB_DATABASE,
|
|
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,
|
|
23
35
|
]
|
|
24
36
|
required_keys = [
|
|
25
|
-
CredsEnvVar.DB_USERNAME,
|
|
26
|
-
CredsEnvVar.DB_PASSWORD,
|
|
27
|
-
CredsEnvVar.DB_HOST,
|
|
28
|
-
CredsEnvVar.DB_PORT,
|
|
29
|
-
CredsEnvVar.DB_DATABASE,
|
|
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,
|
|
30
42
|
]
|
|
31
43
|
|
|
32
44
|
def __init__(self):
|
|
@@ -37,33 +49,72 @@ class SqlStoreConfigurator(Configurator):
|
|
|
37
49
|
# Configuration methods
|
|
38
50
|
##############################
|
|
39
51
|
|
|
40
|
-
def
|
|
41
|
-
|
|
42
|
-
|
|
52
|
+
def load_env_vars(self) -> None:
|
|
53
|
+
"""
|
|
54
|
+
Load database credentials from environment variables.
|
|
55
|
+
|
|
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.
|
|
59
|
+
|
|
60
|
+
Returns
|
|
61
|
+
-------
|
|
62
|
+
None
|
|
63
|
+
"""
|
|
64
|
+
env_creds = self._creds_handler.load_from_env(self.keys)
|
|
43
65
|
self._creds_handler.set_credentials(self._env, env_creds)
|
|
44
66
|
|
|
45
|
-
|
|
46
|
-
|
|
67
|
+
def load_file_vars(self) -> None:
|
|
68
|
+
"""
|
|
69
|
+
Load database credentials from configuration file.
|
|
70
|
+
|
|
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.
|
|
74
|
+
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
None
|
|
78
|
+
"""
|
|
79
|
+
file_creds = self._creds_handler.load_from_file(self.keys)
|
|
47
80
|
self._creds_handler.set_credentials(self._file, file_creds)
|
|
48
81
|
|
|
49
|
-
def get_sql_conn_string(self
|
|
82
|
+
def get_sql_conn_string(self) -> str:
|
|
50
83
|
"""
|
|
51
|
-
|
|
84
|
+
Generate PostgreSQL connection string from stored credentials.
|
|
52
85
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
The origin of the credentials.
|
|
86
|
+
Constructs a PostgreSQL connection string using the configured
|
|
87
|
+
database credentials including username, password, host, port,
|
|
88
|
+
and database name.
|
|
57
89
|
|
|
58
90
|
Returns
|
|
59
91
|
-------
|
|
60
92
|
str
|
|
61
|
-
|
|
93
|
+
A PostgreSQL connection string in the format:
|
|
94
|
+
'postgresql://username:password@host:port/database'
|
|
62
95
|
"""
|
|
63
|
-
creds = self.
|
|
96
|
+
creds = self.get_sql_credentials()
|
|
64
97
|
user = creds[CredsEnvVar.DB_USERNAME.value]
|
|
65
98
|
password = creds[CredsEnvVar.DB_PASSWORD.value]
|
|
66
99
|
host = creds[CredsEnvVar.DB_HOST.value]
|
|
67
100
|
port = creds[CredsEnvVar.DB_PORT.value]
|
|
68
101
|
database = creds[CredsEnvVar.DB_DATABASE.value]
|
|
69
102
|
return f"postgresql://{user}:{password}@{host}:{port}/{database}"
|
|
103
|
+
|
|
104
|
+
def get_sql_credentials(self) -> dict:
|
|
105
|
+
"""
|
|
106
|
+
Get all configured database credentials as a dictionary.
|
|
107
|
+
|
|
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.
|
|
111
|
+
|
|
112
|
+
Returns
|
|
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.
|
|
118
|
+
"""
|
|
119
|
+
creds = self.get_credentials(self._origin)
|
|
120
|
+
return {key: creds.get(key) for key in self.keys}
|