naas-abi-core 1.2.1__py3-none-any.whl → 1.3.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.
- naas_abi_core/engine/engine_configuration/EngineConfiguration.py +32 -11
- naas_abi_core/engine/engine_configuration/EngineConfiguration_ObjectStorageService.py +29 -1
- naas_abi_core/engine/engine_configuration/EngineConfiguration_SecretService.py +31 -9
- naas_abi_core/engine/engine_configuration/EngineConfiguration_SecretService_test.py +74 -0
- naas_abi_core/engine/engine_configuration/EngineConfiguration_TripleStoreService.py +13 -8
- naas_abi_core/engine/engine_configuration/EngineConfiguration_TripleStoreService_test.py +109 -0
- naas_abi_core/engine/engine_configuration/EngineConfiguration_VectorStoreService.py +11 -0
- naas_abi_core/engine/engine_configuration/EngineConfiguration_VectorStoreService_test.py +33 -0
- naas_abi_core/services/secret/SecretPorts.py +5 -0
- naas_abi_core/services/secret/adaptors/secondary/NaasSecret.py +8 -1
- naas_abi_core/services/triple_store/adaptors/secondary/AWSNeptune.py +12 -2
- {naas_abi_core-1.2.1.dist-info → naas_abi_core-1.3.0.dist-info}/METADATA +3 -1
- {naas_abi_core-1.2.1.dist-info → naas_abi_core-1.3.0.dist-info}/RECORD +15 -12
- {naas_abi_core-1.2.1.dist-info → naas_abi_core-1.3.0.dist-info}/WHEEL +0 -0
- {naas_abi_core-1.2.1.dist-info → naas_abi_core-1.3.0.dist-info}/entry_points.txt +0 -0
|
@@ -129,7 +129,22 @@ class EngineConfiguration(BaseModel):
|
|
|
129
129
|
|
|
130
130
|
def __getattr__(self, name):
|
|
131
131
|
if self.secret_service is None:
|
|
132
|
-
|
|
132
|
+
# This rule is used only when doing the first pass configuration to load the secret service.
|
|
133
|
+
|
|
134
|
+
# First priority is to check the environment variables.
|
|
135
|
+
if name in os.environ:
|
|
136
|
+
return os.environ.get(name)
|
|
137
|
+
else:
|
|
138
|
+
# If the environment variable is not found, we check the .env file. ONLY FOR THE FIRST PASS CONFIGURATION.
|
|
139
|
+
from dotenv import dotenv_values
|
|
140
|
+
|
|
141
|
+
secrets = dotenv_values()
|
|
142
|
+
if name in secrets:
|
|
143
|
+
return secrets.get(name)
|
|
144
|
+
else:
|
|
145
|
+
return f"Secret '{name}' not found while loading the secret service. Please provide it via the environment variables or .env file."
|
|
146
|
+
elif name in os.environ:
|
|
147
|
+
return os.environ.get(name)
|
|
133
148
|
secret = self.secret_service.get(name)
|
|
134
149
|
if secret is None:
|
|
135
150
|
if not sys.stdin.isatty():
|
|
@@ -144,9 +159,6 @@ class EngineConfiguration(BaseModel):
|
|
|
144
159
|
return value
|
|
145
160
|
return secret
|
|
146
161
|
|
|
147
|
-
def get(self, key, default=None):
|
|
148
|
-
return 0
|
|
149
|
-
|
|
150
162
|
first_pass_data = yaml.safe_load(
|
|
151
163
|
StringIO(Template(yaml_content).render(secret=SecretServiceWrapper()))
|
|
152
164
|
)
|
|
@@ -157,13 +169,11 @@ class EngineConfiguration(BaseModel):
|
|
|
157
169
|
# Here we can now template the yaml by using `yaml_content` and the secret service.
|
|
158
170
|
# Using Jinja2 template engine.
|
|
159
171
|
|
|
160
|
-
logger.debug("Yaml content: {yaml_content}")
|
|
172
|
+
logger.debug(f"Yaml content: {yaml_content}")
|
|
161
173
|
|
|
162
174
|
template = Template(yaml_content)
|
|
163
175
|
templated_yaml = template.render(secret=SecretServiceWrapper(secret_service))
|
|
164
176
|
|
|
165
|
-
logger.debug(f"Templated yaml: {templated_yaml}")
|
|
166
|
-
|
|
167
177
|
data = yaml.safe_load(StringIO(templated_yaml))
|
|
168
178
|
|
|
169
179
|
logger.debug(f"Data: {data}")
|
|
@@ -178,17 +188,28 @@ class EngineConfiguration(BaseModel):
|
|
|
178
188
|
if configuration_yaml is not None:
|
|
179
189
|
return cls.from_yaml_content(configuration_yaml)
|
|
180
190
|
|
|
181
|
-
|
|
191
|
+
# Get ENV value
|
|
192
|
+
from dotenv import dotenv_values
|
|
193
|
+
|
|
194
|
+
env = os.getenv("ENV")
|
|
195
|
+
if not env:
|
|
196
|
+
env = dotenv_values().get("ENV")
|
|
182
197
|
|
|
183
|
-
|
|
184
|
-
|
|
198
|
+
# First we check the environment variable.
|
|
199
|
+
if os.path.exists(f"config.{env}.yaml"):
|
|
200
|
+
config_file = f"config.{env}.yaml"
|
|
201
|
+
# If the config.{env}.yaml file is not found, we check the config.yaml file.
|
|
185
202
|
elif os.path.exists("config.yaml"):
|
|
186
|
-
|
|
203
|
+
config_file = "config.yaml"
|
|
187
204
|
else:
|
|
188
205
|
raise FileNotFoundError(
|
|
189
206
|
"Configuration file not found. Please create a config.yaml file or config.{env}.yaml file."
|
|
190
207
|
)
|
|
191
208
|
|
|
209
|
+
logger.debug(f"Loading configuration from {config_file}")
|
|
210
|
+
|
|
211
|
+
return cls.from_yaml(config_file)
|
|
212
|
+
|
|
192
213
|
|
|
193
214
|
if __name__ == "__main__":
|
|
194
215
|
config = EngineConfiguration.load_configuration()
|
|
@@ -17,18 +17,46 @@ from typing_extensions import Self
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class ObjectStorageAdapterFSConfiguration(BaseModel):
|
|
20
|
+
"""Object storage adapter filesystem configuration.
|
|
21
|
+
|
|
22
|
+
object_storage_adapter:
|
|
23
|
+
adapter: "fs"
|
|
24
|
+
config:
|
|
25
|
+
base_path: "storage/datastore"
|
|
26
|
+
"""
|
|
20
27
|
base_path: str
|
|
21
28
|
|
|
22
29
|
|
|
23
30
|
class ObjectStorageAdapterS3Configuration(BaseModel):
|
|
31
|
+
"""Object storage adapter S3 configuration.
|
|
32
|
+
|
|
33
|
+
object_storage_adapter:
|
|
34
|
+
adapter: "s3"
|
|
35
|
+
config:
|
|
36
|
+
bucket_name: "my-bucket"
|
|
37
|
+
base_prefix: "my-prefix"
|
|
38
|
+
access_key_id: "{{ secret.AWS_ACCESS_KEY_ID }}"
|
|
39
|
+
secret_access_key: "{{ secret.AWS_SECRET_ACCESS_KEY }}"
|
|
40
|
+
session_token: "{{ secret.AWS_SESSION_TOKEN }}"
|
|
41
|
+
"""
|
|
24
42
|
bucket_name: str
|
|
43
|
+
base_prefix: str
|
|
25
44
|
access_key_id: str
|
|
26
45
|
secret_access_key: str
|
|
27
|
-
base_prefix: str
|
|
28
46
|
session_token: str | None = None
|
|
29
47
|
|
|
30
48
|
|
|
31
49
|
class ObjectStorageAdapterNaasConfiguration(BaseModel):
|
|
50
|
+
"""Object storage adapter Naas configuration.
|
|
51
|
+
|
|
52
|
+
object_storage_adapter:
|
|
53
|
+
adapter: "naas"
|
|
54
|
+
config:
|
|
55
|
+
naas_api_key: "{{ secret.NAAS_API_KEY }}"
|
|
56
|
+
workspace_id: "{{ secret.WORKSPACE_ID }}"
|
|
57
|
+
storage_name: "{{ secret.STORAGE_NAME }}"
|
|
58
|
+
base_prefix: "my-prefix"
|
|
59
|
+
"""
|
|
32
60
|
naas_api_key: str
|
|
33
61
|
workspace_id: str
|
|
34
62
|
storage_name: str
|
|
@@ -18,7 +18,38 @@ if TYPE_CHECKING:
|
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
class DotenvSecretConfiguration(BaseModel):
|
|
22
|
+
"""Dotenv secret configuration.
|
|
23
|
+
|
|
24
|
+
secret_adapters:
|
|
25
|
+
- adapter: "dotenv"
|
|
26
|
+
config: {}
|
|
27
|
+
"""
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class NaasSecretConfiguration(BaseModel):
|
|
32
|
+
"""Naas secret configuration.
|
|
33
|
+
|
|
34
|
+
secret_adapters:
|
|
35
|
+
- adapter: "naas"
|
|
36
|
+
config:
|
|
37
|
+
naas_api_key: "{{ secret.NAAS_API_KEY }}"
|
|
38
|
+
naas_api_url: "https://api.naas.ai"
|
|
39
|
+
"""
|
|
40
|
+
naas_api_key: str
|
|
41
|
+
naas_api_url: str
|
|
42
|
+
|
|
43
|
+
|
|
21
44
|
class Base64SecretConfiguration(BaseModel):
|
|
45
|
+
"""Base64 secret configuration.
|
|
46
|
+
|
|
47
|
+
secret_adapters:
|
|
48
|
+
- adapter: "base64"
|
|
49
|
+
config:
|
|
50
|
+
secret_adapter: *secret_adapter
|
|
51
|
+
base64_secret_key: "{{ secret.BASE64_SECRET_KEY }}"
|
|
52
|
+
"""
|
|
22
53
|
secret_adapter: "SecretAdapterConfiguration"
|
|
23
54
|
base64_secret_key: str
|
|
24
55
|
|
|
@@ -30,15 +61,6 @@ class Base64SecretConfiguration(BaseModel):
|
|
|
30
61
|
return Base64Secret(self.secret_adapter.load(), self.base64_secret_key)
|
|
31
62
|
|
|
32
63
|
|
|
33
|
-
class NaasSecretConfiguration(BaseModel):
|
|
34
|
-
naas_api_key: str
|
|
35
|
-
naas_api_url: str
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
class DotenvSecretConfiguration(BaseModel):
|
|
39
|
-
pass
|
|
40
|
-
|
|
41
|
-
|
|
42
64
|
class SecretAdapterConfiguration(GenericLoader):
|
|
43
65
|
adapter: Literal["dotenv", "naas", "base64", "custom"]
|
|
44
66
|
config: (
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from naas_abi_core.engine.engine_configuration.EngineConfiguration_SecretService import (
|
|
2
|
+
DotenvSecretConfiguration,
|
|
3
|
+
NaasSecretConfiguration,
|
|
4
|
+
SecretAdapterConfiguration,
|
|
5
|
+
SecretServiceConfiguration,
|
|
6
|
+
)
|
|
7
|
+
from naas_abi_core.services.secret.Secret import Secret
|
|
8
|
+
from naas_abi_core.services.secret.SecretPorts import ISecretAdapter
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_secret_service_configuration():
|
|
12
|
+
from naas_abi_core.services.secret.adaptors.secondary.dotenv_secret_secondaryadaptor import (
|
|
13
|
+
DotenvSecretSecondaryAdaptor,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
configuration = SecretServiceConfiguration(
|
|
17
|
+
secret_adapters=[
|
|
18
|
+
SecretAdapterConfiguration(
|
|
19
|
+
adapter="dotenv", config=DotenvSecretConfiguration()
|
|
20
|
+
)
|
|
21
|
+
]
|
|
22
|
+
)
|
|
23
|
+
assert configuration.secret_adapters is not None
|
|
24
|
+
assert len(configuration.secret_adapters) == 1
|
|
25
|
+
|
|
26
|
+
secret_adapter = configuration.secret_adapters[0].load()
|
|
27
|
+
|
|
28
|
+
assert secret_adapter is not None
|
|
29
|
+
assert isinstance(secret_adapter, ISecretAdapter)
|
|
30
|
+
assert isinstance(secret_adapter, DotenvSecretSecondaryAdaptor)
|
|
31
|
+
|
|
32
|
+
secret_service = configuration.load()
|
|
33
|
+
|
|
34
|
+
assert secret_service is not None
|
|
35
|
+
assert isinstance(secret_service, Secret)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_secret_service_configuration_naas():
|
|
39
|
+
import os
|
|
40
|
+
|
|
41
|
+
from dotenv import load_dotenv
|
|
42
|
+
from naas_abi_core.services.secret.adaptors.secondary.NaasSecret import (
|
|
43
|
+
NaasSecret,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
load_dotenv()
|
|
47
|
+
|
|
48
|
+
naas_api_key = os.getenv("NAAS_API_KEY")
|
|
49
|
+
if naas_api_key is None:
|
|
50
|
+
raise ValueError("NAAS_API_KEY is not set")
|
|
51
|
+
|
|
52
|
+
naas_api_url = os.getenv("NAAS_API_URL")
|
|
53
|
+
if naas_api_url is None:
|
|
54
|
+
raise ValueError("NAAS_API_URL is not set")
|
|
55
|
+
|
|
56
|
+
configuration = SecretServiceConfiguration(
|
|
57
|
+
secret_adapters=[
|
|
58
|
+
SecretAdapterConfiguration(
|
|
59
|
+
adapter="naas",
|
|
60
|
+
config=NaasSecretConfiguration(
|
|
61
|
+
naas_api_key=naas_api_key,
|
|
62
|
+
naas_api_url=naas_api_url,
|
|
63
|
+
),
|
|
64
|
+
)
|
|
65
|
+
]
|
|
66
|
+
)
|
|
67
|
+
assert configuration.secret_adapters is not None
|
|
68
|
+
assert len(configuration.secret_adapters) == 1
|
|
69
|
+
|
|
70
|
+
secret_adapter = configuration.secret_adapters[0].load()
|
|
71
|
+
|
|
72
|
+
assert secret_adapter is not None
|
|
73
|
+
assert isinstance(secret_adapter, ISecretAdapter)
|
|
74
|
+
assert isinstance(secret_adapter, NaasSecret)
|
|
@@ -28,6 +28,7 @@ class OxigraphAdapterConfiguration(BaseModel):
|
|
|
28
28
|
oxigraph_url: "http://localhost:7878"
|
|
29
29
|
timeout: 60
|
|
30
30
|
"""
|
|
31
|
+
|
|
31
32
|
oxigraph_url: str = "http://localhost:7878"
|
|
32
33
|
timeout: int = 60
|
|
33
34
|
|
|
@@ -38,11 +39,12 @@ class AWSNeptuneAdapterConfiguration(BaseModel):
|
|
|
38
39
|
triple_store_adapter:
|
|
39
40
|
adapter: "aws_neptune"
|
|
40
41
|
config:
|
|
41
|
-
aws_region_name: "
|
|
42
|
+
aws_region_name: "{{ secret.AWS_REGION }}"
|
|
42
43
|
aws_access_key_id: "{{ secret.AWS_ACCESS_KEY_ID }}"
|
|
43
44
|
aws_secret_access_key: "{{ secret.AWS_SECRET_ACCESS_KEY }}"
|
|
44
|
-
db_instance_identifier: "{{ secret.
|
|
45
|
+
db_instance_identifier: "{{ secret.AWS_NEPTUNE_DB_INSTANCE_IDENTIFIER }}"
|
|
45
46
|
"""
|
|
47
|
+
|
|
46
48
|
aws_region_name: str
|
|
47
49
|
aws_access_key_id: str
|
|
48
50
|
aws_secret_access_key: str
|
|
@@ -55,15 +57,16 @@ class AWSNeptuneSSHTunnelAdapterConfiguration(AWSNeptuneAdapterConfiguration):
|
|
|
55
57
|
triple_store_adapter:
|
|
56
58
|
adapter: "aws_neptune_sshtunnel"
|
|
57
59
|
config:
|
|
58
|
-
aws_region_name: "
|
|
60
|
+
aws_region_name: "{{ secret.AWS_REGION }}"
|
|
59
61
|
aws_access_key_id: "{{ secret.AWS_ACCESS_KEY_ID }}"
|
|
60
62
|
aws_secret_access_key: "{{ secret.AWS_SECRET_ACCESS_KEY }}"
|
|
61
|
-
db_instance_identifier: "{{ secret.
|
|
62
|
-
bastion_host: "
|
|
63
|
-
bastion_port:
|
|
64
|
-
bastion_user: "
|
|
65
|
-
bastion_private_key: "{{ secret.
|
|
63
|
+
db_instance_identifier: "{{ secret.AWS_NEPTUNE_DB_INSTANCE_IDENTIFIER }}"
|
|
64
|
+
bastion_host: "{{ secret.AWS_BASTION_HOST }}"
|
|
65
|
+
bastion_port: "{{ secret.AWS_BASTION_PORT }}"
|
|
66
|
+
bastion_user: "{{ secret.AWS_BASTION_USER }}"
|
|
67
|
+
bastion_private_key: "{{ secret.AWS_BASTION_PRIVATE_KEY }}"
|
|
66
68
|
"""
|
|
69
|
+
|
|
67
70
|
bastion_host: str
|
|
68
71
|
bastion_port: int
|
|
69
72
|
bastion_user: str
|
|
@@ -79,6 +82,7 @@ class TripleStoreAdapterFilesystemConfiguration(BaseModel):
|
|
|
79
82
|
store_path: "storage/triplestore"
|
|
80
83
|
triples_path: "triples"
|
|
81
84
|
"""
|
|
85
|
+
|
|
82
86
|
store_path: str
|
|
83
87
|
triples_path: str = "triples"
|
|
84
88
|
|
|
@@ -92,6 +96,7 @@ class TripleStoreAdapterObjectStorageConfiguration(BaseModel):
|
|
|
92
96
|
object_storage_service: *object_storage_service
|
|
93
97
|
triples_prefix: "triples"
|
|
94
98
|
"""
|
|
99
|
+
|
|
95
100
|
object_storage_service: ObjectStorageServiceConfiguration
|
|
96
101
|
triples_prefix: str = "triples"
|
|
97
102
|
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from naas_abi_core.engine.engine_configuration.EngineConfiguration_TripleStoreService import (
|
|
2
|
+
AWSNeptuneSSHTunnelAdapterConfiguration,
|
|
3
|
+
OxigraphAdapterConfiguration,
|
|
4
|
+
TripleStoreAdapterConfiguration,
|
|
5
|
+
TripleStoreAdapterFilesystemConfiguration,
|
|
6
|
+
TripleStoreServiceConfiguration,
|
|
7
|
+
)
|
|
8
|
+
from naas_abi_core.services.triple_store.TripleStorePorts import ITripleStorePort
|
|
9
|
+
from naas_abi_core.services.triple_store.TripleStoreService import TripleStoreService
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_triple_store_service_configuration():
|
|
13
|
+
from naas_abi_core.services.triple_store.adaptors.secondary.TripleStoreService__SecondaryAdaptor__Filesystem import (
|
|
14
|
+
TripleStoreService__SecondaryAdaptor__Filesystem,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
configuration = TripleStoreServiceConfiguration(
|
|
18
|
+
triple_store_adapter=TripleStoreAdapterConfiguration(
|
|
19
|
+
adapter="fs",
|
|
20
|
+
config=TripleStoreAdapterFilesystemConfiguration(
|
|
21
|
+
store_path="storage/triplestore/test", triples_path="triples"
|
|
22
|
+
),
|
|
23
|
+
)
|
|
24
|
+
)
|
|
25
|
+
assert configuration.triple_store_adapter is not None
|
|
26
|
+
|
|
27
|
+
triple_store_adapter = configuration.triple_store_adapter.load()
|
|
28
|
+
|
|
29
|
+
assert triple_store_adapter is not None
|
|
30
|
+
assert isinstance(triple_store_adapter, ITripleStorePort)
|
|
31
|
+
assert isinstance(
|
|
32
|
+
triple_store_adapter, TripleStoreService__SecondaryAdaptor__Filesystem
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
triple_store_service = configuration.load()
|
|
36
|
+
|
|
37
|
+
assert triple_store_service is not None
|
|
38
|
+
assert isinstance(triple_store_service, TripleStoreService)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_triple_store_service_configuration_naas():
|
|
42
|
+
from naas_abi_core.services.triple_store.adaptors.secondary.Oxigraph import (
|
|
43
|
+
Oxigraph,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
configuration = TripleStoreServiceConfiguration(
|
|
47
|
+
triple_store_adapter=TripleStoreAdapterConfiguration(
|
|
48
|
+
adapter="oxigraph",
|
|
49
|
+
config=OxigraphAdapterConfiguration(
|
|
50
|
+
oxigraph_url="http://localhost:7878",
|
|
51
|
+
timeout=120,
|
|
52
|
+
),
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
assert configuration.triple_store_adapter is not None
|
|
56
|
+
|
|
57
|
+
triple_store_adapter = configuration.triple_store_adapter.load()
|
|
58
|
+
|
|
59
|
+
assert triple_store_adapter is not None
|
|
60
|
+
assert isinstance(triple_store_adapter, ITripleStorePort)
|
|
61
|
+
assert isinstance(triple_store_adapter, Oxigraph)
|
|
62
|
+
|
|
63
|
+
triple_store_service = configuration.load()
|
|
64
|
+
|
|
65
|
+
assert triple_store_service is not None
|
|
66
|
+
assert isinstance(triple_store_service, TripleStoreService)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def test_triple_store_service_configuration_aws_neptune_sshtunnel():
|
|
70
|
+
import os
|
|
71
|
+
|
|
72
|
+
from dotenv import load_dotenv
|
|
73
|
+
|
|
74
|
+
load_dotenv()
|
|
75
|
+
|
|
76
|
+
from naas_abi_core.services.triple_store.adaptors.secondary.AWSNeptune import (
|
|
77
|
+
AWSNeptuneSSHTunnel,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
configuration = TripleStoreServiceConfiguration(
|
|
81
|
+
triple_store_adapter=TripleStoreAdapterConfiguration(
|
|
82
|
+
adapter="aws_neptune_sshtunnel",
|
|
83
|
+
config=AWSNeptuneSSHTunnelAdapterConfiguration(
|
|
84
|
+
aws_region_name=os.environ.get("AWS_REGION"),
|
|
85
|
+
aws_access_key_id=os.environ.get("AWS_ACCESS_KEY_ID"),
|
|
86
|
+
aws_secret_access_key=os.environ.get("AWS_SECRET_ACCESS_KEY"),
|
|
87
|
+
db_instance_identifier=os.environ.get(
|
|
88
|
+
"AWS_NEPTUNE_DB_INSTANCE_IDENTIFIER"
|
|
89
|
+
),
|
|
90
|
+
bastion_host=os.environ.get("AWS_BASTION_HOST"),
|
|
91
|
+
bastion_port=int(os.environ.get("AWS_BASTION_PORT")),
|
|
92
|
+
bastion_user=os.environ.get("AWS_BASTION_USER"),
|
|
93
|
+
bastion_private_key=os.environ.get("AWS_BASTION_PRIVATE_KEY"),
|
|
94
|
+
),
|
|
95
|
+
),
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
assert configuration.triple_store_adapter is not None
|
|
99
|
+
|
|
100
|
+
triple_store_adapter = configuration.triple_store_adapter.load()
|
|
101
|
+
|
|
102
|
+
assert triple_store_adapter is not None
|
|
103
|
+
assert isinstance(triple_store_adapter, ITripleStorePort)
|
|
104
|
+
assert isinstance(triple_store_adapter, AWSNeptuneSSHTunnel)
|
|
105
|
+
|
|
106
|
+
triple_store_service = configuration.load()
|
|
107
|
+
|
|
108
|
+
assert triple_store_service is not None
|
|
109
|
+
assert isinstance(triple_store_service, TripleStoreService)
|
|
@@ -12,6 +12,17 @@ from pydantic import BaseModel, model_validator
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class VectorStoreAdapterQdrantConfiguration(BaseModel):
|
|
15
|
+
"""Qdrant vector store adapter configuration.
|
|
16
|
+
|
|
17
|
+
vector_store_adapter:
|
|
18
|
+
adapter: "qdrant"
|
|
19
|
+
config:
|
|
20
|
+
host: "{{ secret.QDRANT_HOST }}"
|
|
21
|
+
port: "{{ secret.QDRANT_PORT }}"
|
|
22
|
+
api_key: "{{ secret.QDRANT_API_KEY }}"
|
|
23
|
+
https: "{{ secret.QDRANT_HTTPS }}"
|
|
24
|
+
timeout: "{{ secret.QDRANT_TIMEOUT }}"
|
|
25
|
+
"""
|
|
15
26
|
host: str = "localhost"
|
|
16
27
|
port: int = 6333
|
|
17
28
|
api_key: str | None = None
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from naas_abi_core.engine.engine_configuration.EngineConfiguration_VectorStoreService import (
|
|
2
|
+
VectorStoreAdapterConfiguration,
|
|
3
|
+
VectorStoreAdapterQdrantConfiguration,
|
|
4
|
+
VectorStoreServiceConfiguration,
|
|
5
|
+
)
|
|
6
|
+
from naas_abi_core.services.vector_store.IVectorStorePort import IVectorStorePort
|
|
7
|
+
from naas_abi_core.services.vector_store.VectorStoreService import VectorStoreService
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_vector_store_service_configuration():
|
|
11
|
+
from naas_abi_core.services.vector_store.adapters.QdrantAdapter import (
|
|
12
|
+
QdrantAdapter,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
qdrant_config = VectorStoreAdapterQdrantConfiguration()
|
|
16
|
+
configuration = VectorStoreServiceConfiguration(
|
|
17
|
+
vector_store_adapter=VectorStoreAdapterConfiguration(
|
|
18
|
+
adapter="qdrant",
|
|
19
|
+
config=qdrant_config.model_dump(),
|
|
20
|
+
)
|
|
21
|
+
)
|
|
22
|
+
assert configuration.vector_store_adapter is not None
|
|
23
|
+
|
|
24
|
+
vector_store_adapter = configuration.vector_store_adapter.load()
|
|
25
|
+
|
|
26
|
+
assert vector_store_adapter is not None
|
|
27
|
+
assert isinstance(vector_store_adapter, IVectorStorePort)
|
|
28
|
+
assert isinstance(vector_store_adapter, QdrantAdapter)
|
|
29
|
+
|
|
30
|
+
vector_store_service = configuration.load()
|
|
31
|
+
|
|
32
|
+
assert vector_store_service is not None
|
|
33
|
+
assert isinstance(vector_store_service, VectorStoreService)
|
|
@@ -2,6 +2,10 @@ from abc import ABC, abstractmethod
|
|
|
2
2
|
from typing import Any, Dict, List
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
class SecretAuthenticationError(Exception):
|
|
6
|
+
pass
|
|
7
|
+
|
|
8
|
+
|
|
5
9
|
class ISecretAdapter(ABC):
|
|
6
10
|
@abstractmethod
|
|
7
11
|
def get(self, key: str, default: Any = None) -> str | Any | None:
|
|
@@ -38,3 +42,4 @@ class ISecretService(ABC):
|
|
|
38
42
|
@abstractmethod
|
|
39
43
|
def list(self) -> Dict[str, str | None]:
|
|
40
44
|
raise NotImplementedError()
|
|
45
|
+
raise NotImplementedError()
|
|
@@ -2,7 +2,10 @@ from typing import Any, Dict
|
|
|
2
2
|
|
|
3
3
|
import requests
|
|
4
4
|
from naas_abi_core import logger
|
|
5
|
-
from naas_abi_core.services.secret.SecretPorts import
|
|
5
|
+
from naas_abi_core.services.secret.SecretPorts import (
|
|
6
|
+
ISecretAdapter,
|
|
7
|
+
SecretAuthenticationError,
|
|
8
|
+
)
|
|
6
9
|
|
|
7
10
|
NAAS_API_URL = "https://api.naas.ai"
|
|
8
11
|
|
|
@@ -27,6 +30,10 @@ class NaasSecret(ISecretAdapter):
|
|
|
27
30
|
except requests.exceptions.HTTPError as _:
|
|
28
31
|
if response.status_code == 404:
|
|
29
32
|
logger.debug(f"Secret {key} not found")
|
|
33
|
+
elif response.status_code == 401:
|
|
34
|
+
error_message = f"Authentication error on '{NAAS_API_URL}' with NAAS_API_KEY '{self.naas_api_key}'"
|
|
35
|
+
logger.error(error_message)
|
|
36
|
+
raise SecretAuthenticationError(error_message)
|
|
30
37
|
else:
|
|
31
38
|
logger.error(f"Error getting secret {key}: {response.status_code}")
|
|
32
39
|
return default
|
|
@@ -947,7 +947,7 @@ class AWSNeptuneSSHTunnel(AWSNeptune):
|
|
|
947
947
|
aws_secret_access_key: str,
|
|
948
948
|
db_instance_identifier: str,
|
|
949
949
|
bastion_host: str,
|
|
950
|
-
bastion_port: int,
|
|
950
|
+
bastion_port: int | str,
|
|
951
951
|
bastion_user: str,
|
|
952
952
|
bastion_private_key: str,
|
|
953
953
|
default_graph_name: URIRef = NEPTUNE_DEFAULT_GRAPH_NAME,
|
|
@@ -965,7 +965,7 @@ class AWSNeptuneSSHTunnel(AWSNeptune):
|
|
|
965
965
|
aws_secret_access_key (str): AWS secret key for Neptune authentication
|
|
966
966
|
db_instance_identifier (str): Neptune database instance identifier
|
|
967
967
|
bastion_host (str): Hostname or IP address of the bastion host
|
|
968
|
-
bastion_port (int): SSH port on the bastion host (typically 22)
|
|
968
|
+
bastion_port (int | str): SSH port on the bastion host (typically 22)
|
|
969
969
|
bastion_user (str): SSH username for bastion host authentication
|
|
970
970
|
bastion_private_key (str): Complete SSH private key content as a string
|
|
971
971
|
default_graph_name (URIRef, optional): Default named graph URI
|
|
@@ -1002,6 +1002,16 @@ class AWSNeptuneSSHTunnel(AWSNeptune):
|
|
|
1002
1002
|
)
|
|
1003
1003
|
|
|
1004
1004
|
assert isinstance(bastion_host, str)
|
|
1005
|
+
if not isinstance(bastion_port, int):
|
|
1006
|
+
# This block is added because the "naas" secret adapter does not always manage int values:
|
|
1007
|
+
# it may provide 'bastion_port' as a string; convert it to int if needed.
|
|
1008
|
+
if isinstance(bastion_port, str):
|
|
1009
|
+
try:
|
|
1010
|
+
bastion_port = int(bastion_port)
|
|
1011
|
+
except ValueError:
|
|
1012
|
+
raise ValueError(
|
|
1013
|
+
f"bastion_port must be an int or a string convertible to int, got string: {bastion_port!r}"
|
|
1014
|
+
)
|
|
1005
1015
|
assert isinstance(bastion_port, int)
|
|
1006
1016
|
assert isinstance(bastion_user, str)
|
|
1007
1017
|
assert isinstance(bastion_private_key, str)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: naas-abi-core
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Abi framework allowing you to build your AI system.
|
|
5
5
|
Author-email: Maxime Jublou <maxime@naas.ai>, Florent Ravenel <florent@naas.ai>, Jeremy Ravenel <jeremy@naas.ai>
|
|
6
6
|
Requires-Python: <4,>=3.10
|
|
@@ -28,6 +28,8 @@ Requires-Dist: spacy>=3.8.7
|
|
|
28
28
|
Requires-Dist: sparqlwrapper>=2.0.0
|
|
29
29
|
Requires-Dist: sse-starlette<3,>=2.1.3
|
|
30
30
|
Requires-Dist: starlette>=0.46.2
|
|
31
|
+
Requires-Dist: types-paramiko>=4.0.0.20250822
|
|
32
|
+
Requires-Dist: types-pyyaml>=6.0.12.20250915
|
|
31
33
|
Requires-Dist: types-tqdm>=4.67.0.20250809
|
|
32
34
|
Provides-Extra: all
|
|
33
35
|
Requires-Dist: boto3<2,>=1.38.19; extra == 'all'
|
|
@@ -12,14 +12,17 @@ naas_abi_core/engine/EngineProxy.py,sha256=o-D8LlP-PjQ_Yct4JWrDZw7mA7yporxb2XrJF
|
|
|
12
12
|
naas_abi_core/engine/Engine_test.py,sha256=8eLZEnkL0IR4VAr6LF8fJ_fxZzi9s1mXCLgTVOIsR3E,161
|
|
13
13
|
naas_abi_core/engine/IEngine.py,sha256=u-m-Qrvt3SP3gYKWPFPVjV8rs05D6NGnzO3XA0FInnw,2865
|
|
14
14
|
naas_abi_core/engine/conftest.py,sha256=Al-SRVLrEdbTrX8sxQ3bBK4w1bbzE4GoBkzoBK-aXlg,932
|
|
15
|
-
naas_abi_core/engine/engine_configuration/EngineConfiguration.py,sha256=
|
|
15
|
+
naas_abi_core/engine/engine_configuration/EngineConfiguration.py,sha256=7_ACJLTwwUYsm2RyabvPenyr78kXxy3x3t1BpW4H4r0,7797
|
|
16
16
|
naas_abi_core/engine/engine_configuration/EngineConfiguration_Deploy.py,sha256=7nqOnXWcNbQAp9G3afc3y58BrxCaIrrTpUz7yBngy14,163
|
|
17
17
|
naas_abi_core/engine/engine_configuration/EngineConfiguration_GenericLoader.py,sha256=KK2TQx6cNmoqFcwr9En00NKrX4ckkZl4ecv9QCUwPyc,1995
|
|
18
|
-
naas_abi_core/engine/engine_configuration/EngineConfiguration_ObjectStorageService.py,sha256=
|
|
18
|
+
naas_abi_core/engine/engine_configuration/EngineConfiguration_ObjectStorageService.py,sha256=erngfACkUwwHHOilmjbN9rRN5IPmMjOz9-zPaAeS5dM,5569
|
|
19
19
|
naas_abi_core/engine/engine_configuration/EngineConfiguration_ObjectStorageService_test.py,sha256=h1PdIbMTJWi_lG83YgpI6zg8gRo0WEWvGSE6R4uKQp4,1063
|
|
20
|
-
naas_abi_core/engine/engine_configuration/EngineConfiguration_SecretService.py,sha256=
|
|
21
|
-
naas_abi_core/engine/engine_configuration/
|
|
22
|
-
naas_abi_core/engine/engine_configuration/
|
|
20
|
+
naas_abi_core/engine/engine_configuration/EngineConfiguration_SecretService.py,sha256=yNAwPpDwElSto6QjgKxoQsysnzk5NzjGE0OkIcNilwQ,4589
|
|
21
|
+
naas_abi_core/engine/engine_configuration/EngineConfiguration_SecretService_test.py,sha256=5SyeB5LxPN1tYrgIzTXj7d-xcJttC5qm1XtJrixUyoE,2317
|
|
22
|
+
naas_abi_core/engine/engine_configuration/EngineConfiguration_TripleStoreService.py,sha256=vIWO-RQ5BetHUcG0hfSnPCVzqopx2qO51e4axw7lEbc,7876
|
|
23
|
+
naas_abi_core/engine/engine_configuration/EngineConfiguration_TripleStoreService_test.py,sha256=Q8V_2urBgYhHbgcmlruxd9zV-YbQxdHT_V2SwM_oj2U,4026
|
|
24
|
+
naas_abi_core/engine/engine_configuration/EngineConfiguration_VectorStoreService.py,sha256=1Ulqtbjw9zAjdiXFyqVETtoY-xiqiauPH6GeuPGKiZg,2552
|
|
25
|
+
naas_abi_core/engine/engine_configuration/EngineConfiguration_VectorStoreService_test.py,sha256=hy6OLrn0L-dpcAprbRZLXdKPPgpK0F-gVOdahAvjbf0,1258
|
|
23
26
|
naas_abi_core/engine/engine_configuration/EngineConfiguration_test.py,sha256=PL4A4Dawq6tfyHsiIkqbHhovc7wkIHcVZra6llRI-CY,286
|
|
24
27
|
naas_abi_core/engine/engine_configuration/utils/PydanticModelValidator.py,sha256=jZzLqLvR8HawpyGYiUJEng3NlebLHiN3mVFOzNDSWs8,504
|
|
25
28
|
naas_abi_core/engine/engine_loaders/EngineModuleLoader.py,sha256=4VsGtPsaeslej2JuyksHUbHJEY6J096cnr3iuTrhnpY,12043
|
|
@@ -67,17 +70,17 @@ naas_abi_core/services/ontology/OntologyPorts.py,sha256=CANMwmXps5k2IB1pq1I5723H
|
|
|
67
70
|
naas_abi_core/services/ontology/OntologyService.py,sha256=-shSDmL5zvEvNjTbDQ1pq2ziwnJvfR-ka6XJh1AcDuA,542
|
|
68
71
|
naas_abi_core/services/ontology/adaptors/secondary/OntologyService_SecondaryAdaptor_NERPort.py,sha256=CNGnlvtoADUki8fEWnanD4Xe7_osQrpWDusZOLu1mgo,1303
|
|
69
72
|
naas_abi_core/services/secret/Secret.py,sha256=7odnAtpkC12laA8CFzE_W2NOFpDyaW2TmoebUCFMSQE,5159
|
|
70
|
-
naas_abi_core/services/secret/SecretPorts.py,sha256=
|
|
73
|
+
naas_abi_core/services/secret/SecretPorts.py,sha256=4JnkU1dPC4_p_GweOxmfiEE5RxwZztjNo3Ygnwo2sLw,1087
|
|
71
74
|
naas_abi_core/services/secret/Secret_test.py,sha256=rRLAsBCNDMduUwCeCSdlWtIFwguqFeVdRp-3lF6R9mc,1581
|
|
72
75
|
naas_abi_core/services/secret/adaptors/secondary/Base64Secret.py,sha256=Py7bBEBnkaBnuD9wtXO_tMI5HiM7olspOvfBRRq57Tw,1967
|
|
73
76
|
naas_abi_core/services/secret/adaptors/secondary/Base64Secret_test.py,sha256=wwdfMJrkh6vFZabZie9xyQHYlTjPAfouV-sPI4pk8MM,1287
|
|
74
|
-
naas_abi_core/services/secret/adaptors/secondary/NaasSecret.py,sha256=
|
|
77
|
+
naas_abi_core/services/secret/adaptors/secondary/NaasSecret.py,sha256=YyJCcMWadsnBg-1jvGbsGqBelKbMwsPtLDXKm92Pbwo,3064
|
|
75
78
|
naas_abi_core/services/secret/adaptors/secondary/NaasSecret_test.py,sha256=gR2hjU8e3hbkWn_suhwj4kfWLjTZjZavj-5R-z93zjU,625
|
|
76
79
|
naas_abi_core/services/secret/adaptors/secondary/dotenv_secret_secondaryadaptor.py,sha256=jNs1bTz25lD0B5HZUKjenxZ7x6qUm9kIESFmh2-QDs8,909
|
|
77
80
|
naas_abi_core/services/triple_store/TripleStoreFactory.py,sha256=4cCWJUhmXo5-yB61fyDwc-pigIYZo_PzmPW_5pY5I-E,4560
|
|
78
81
|
naas_abi_core/services/triple_store/TripleStorePorts.py,sha256=dRhDc5-uiXDZQWzscqUd972EPi_pafPLkj4sXwxF8Xs,6681
|
|
79
82
|
naas_abi_core/services/triple_store/TripleStoreService.py,sha256=X1ty-fH0A1XyLhZpU6oc3h-BgOoarAHSMPzITBBVhlY,16274
|
|
80
|
-
naas_abi_core/services/triple_store/adaptors/secondary/AWSNeptune.py,sha256=
|
|
83
|
+
naas_abi_core/services/triple_store/adaptors/secondary/AWSNeptune.py,sha256=KXxmB_phSuC1zLU7IA1pF5poFPjpVvUJnuZkDoYIplg,49968
|
|
81
84
|
naas_abi_core/services/triple_store/adaptors/secondary/AWSNeptune_test.py,sha256=b9LiXwQ3EWem5T_OplJWgXQ-cPwkrfomKO5MQx6zwF4,7662
|
|
82
85
|
naas_abi_core/services/triple_store/adaptors/secondary/Oxigraph.py,sha256=1VXtc-Ew7unmqULTA95nN8gnaYWP0Leb3rKbuWe1vRo,20729
|
|
83
86
|
naas_abi_core/services/triple_store/adaptors/secondary/Oxigraph_test.py,sha256=oVyBHGYsrZn9HpzC4aRBi3w515yU0vXG8Yo1mIZN1hk,57224
|
|
@@ -114,7 +117,7 @@ naas_abi_core/utils/onto2py/tests/ttl2py_test.py,sha256=5OZqSxPffjJYiX9T4rT1mV0P
|
|
|
114
117
|
naas_abi_core/workflow/__init__.py,sha256=hZD58mCB1PApxITqftP_xgjxL7NeLvOfI-rJENg1ENs,250
|
|
115
118
|
naas_abi_core/workflow/workflow.py,sha256=ZufSS073JztVl0OQRTqNyK7FepFvv7gXlc4j5FAEZCI,1216
|
|
116
119
|
assets/favicon.ico,sha256=nWk8wrHZiJV3DeuWrP2MqilXxCuoNWKGtMZfYmEVQLw,666
|
|
117
|
-
naas_abi_core-1.
|
|
118
|
-
naas_abi_core-1.
|
|
119
|
-
naas_abi_core-1.
|
|
120
|
-
naas_abi_core-1.
|
|
120
|
+
naas_abi_core-1.3.0.dist-info/METADATA,sha256=0gj0DNiJOnY9bcoT3wt-zKSy70tE0g68mJW9reZk5oQ,3988
|
|
121
|
+
naas_abi_core-1.3.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
122
|
+
naas_abi_core-1.3.0.dist-info/entry_points.txt,sha256=IX0WUFxZuo1JU6H66fcRR6y7gYChMVw_XA9suPk9_1Q,70
|
|
123
|
+
naas_abi_core-1.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|