embed-client-dev 4.0.78__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.
- embed_client/__init__.py +36 -0
- embed_client/__main__.py +15 -0
- embed_client/_version.py +3 -0
- embed_client/adapter_config_factory.py +213 -0
- embed_client/adapter_config_normalizer.py +135 -0
- embed_client/adapter_generator_bridge.py +166 -0
- embed_client/auth.py +189 -0
- embed_client/cli.py +483 -0
- embed_client/cli_core.py +427 -0
- embed_client/client_factory.py +515 -0
- embed_client/client_factory_examples.py +375 -0
- embed_client/client_factory_helpers.py +59 -0
- embed_client/config.py +408 -0
- embed_client/config_defaults.py +77 -0
- embed_client/config_examples.py +228 -0
- embed_client/config_generator.py +652 -0
- embed_client/config_generator_cli.py +151 -0
- embed_client/config_presets.py +245 -0
- embed_client/config_validator.py +246 -0
- embed_client/config_validator_cli.py +141 -0
- embed_client/constants.py +52 -0
- embed_client/demo_cli.py +78 -0
- embed_client/demo_security_cli.py +206 -0
- embed_client/embed_file_output_validate.py +348 -0
- embed_client/embed_file_status_store.py +80 -0
- embed_client/embedding_client.py +1929 -0
- embed_client/embedding_client_helpers.py +105 -0
- embed_client/example_async_usage.py +357 -0
- embed_client/example_async_usage_demo.py +282 -0
- embed_client/example_async_usage_ru.py +340 -0
- embed_client/example_async_usage_ru_demo.py +313 -0
- embed_client/exceptions.py +122 -0
- embed_client/identifier_types.py +56 -0
- embed_client/json_embed_file_preflight.py +128 -0
- embed_client/local_json_embed_file.py +73 -0
- embed_client/md_embed_file_prep.py +197 -0
- embed_client/response_normalizer.py +160 -0
- embed_client/response_parsers.py +219 -0
- embed_client/security_cli.py +200 -0
- embed_client/security_cli_core.py +227 -0
- embed_client/ssl_examples.py +278 -0
- embed_client/ssl_manager.py +141 -0
- embed_client_dev-4.0.78.dist-info/METADATA +155 -0
- embed_client_dev-4.0.78.dist-info/RECORD +48 -0
- embed_client_dev-4.0.78.dist-info/WHEEL +5 -0
- embed_client_dev-4.0.78.dist-info/entry_points.txt +4 -0
- embed_client_dev-4.0.78.dist-info/licenses/LICENSE +21 -0
- embed_client_dev-4.0.78.dist-info/top_level.txt +1 -0
embed_client/config.py
ADDED
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Client configuration management module.
|
|
3
|
+
|
|
4
|
+
This module provides configuration management for the embed-client,
|
|
5
|
+
supporting all security modes and authentication methods.
|
|
6
|
+
|
|
7
|
+
Author: Vasiliy Zdanovskiy
|
|
8
|
+
email: vasilyvz@gmail.com
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
from copy import deepcopy
|
|
14
|
+
from typing import Any, Dict, List, Optional
|
|
15
|
+
|
|
16
|
+
from embed_client.config_defaults import DEFAULT_CONFIG, update_nested_dict
|
|
17
|
+
from embed_client.config_presets import (
|
|
18
|
+
create_http_config_for_class,
|
|
19
|
+
create_http_token_config_for_class,
|
|
20
|
+
create_https_config_for_class,
|
|
21
|
+
create_https_token_config_for_class,
|
|
22
|
+
create_mtls_config_for_class,
|
|
23
|
+
create_minimal_config_dict,
|
|
24
|
+
create_secure_config_dict,
|
|
25
|
+
load_env_variables,
|
|
26
|
+
validate_client_config,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ClientConfig:
|
|
31
|
+
"""
|
|
32
|
+
Configuration management class for the embed-client.
|
|
33
|
+
Allows loading settings from configuration file and environment variables.
|
|
34
|
+
Supports all security modes and authentication methods.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(self, config_path: Optional[str] = None):
|
|
38
|
+
"""
|
|
39
|
+
Initialize client configuration.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
config_path: Path to configuration file. If not specified,
|
|
43
|
+
"./config.json" is used.
|
|
44
|
+
"""
|
|
45
|
+
self.config_path = config_path or "./config.json"
|
|
46
|
+
self.config_data: Dict[str, Any] = {}
|
|
47
|
+
self.load_config()
|
|
48
|
+
|
|
49
|
+
def load_config(self) -> None:
|
|
50
|
+
"""
|
|
51
|
+
Load configuration from file and environment variables.
|
|
52
|
+
"""
|
|
53
|
+
# Set default config values (deep copy to avoid global mutation)
|
|
54
|
+
self.config_data = deepcopy(DEFAULT_CONFIG)
|
|
55
|
+
|
|
56
|
+
# Try to load configuration from file
|
|
57
|
+
if os.path.exists(self.config_path):
|
|
58
|
+
try:
|
|
59
|
+
with open(self.config_path, "r", encoding="utf-8") as f:
|
|
60
|
+
file_config = json.load(f)
|
|
61
|
+
# The default ``server.base_url`` must not override an
|
|
62
|
+
# explicitly configured host/port (adapter prefers base_url).
|
|
63
|
+
file_server = file_config.get("server")
|
|
64
|
+
if (
|
|
65
|
+
isinstance(file_server, dict)
|
|
66
|
+
and ("host" in file_server or "port" in file_server)
|
|
67
|
+
and "base_url" not in file_server
|
|
68
|
+
):
|
|
69
|
+
self.config_data["server"].pop("base_url", None)
|
|
70
|
+
update_nested_dict(self.config_data, file_config)
|
|
71
|
+
except Exception as e:
|
|
72
|
+
print(f"Error loading config from {self.config_path}: {e}")
|
|
73
|
+
|
|
74
|
+
# Load configuration from environment variables
|
|
75
|
+
load_env_variables(self.config_data)
|
|
76
|
+
|
|
77
|
+
def load_from_file(self, config_path: str) -> None:
|
|
78
|
+
"""
|
|
79
|
+
Load configuration from the specified file.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
config_path: Path to configuration file.
|
|
83
|
+
"""
|
|
84
|
+
self.config_path = config_path
|
|
85
|
+
self.load_config()
|
|
86
|
+
|
|
87
|
+
def load_config_file(self, config_path: str) -> None:
|
|
88
|
+
"""Backward-compatible alias for :meth:`load_from_file`."""
|
|
89
|
+
self.load_from_file(config_path)
|
|
90
|
+
|
|
91
|
+
def get(self, key: str, default: Any = None) -> Any:
|
|
92
|
+
"""
|
|
93
|
+
Get configuration value for key.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
key: Configuration key in format "section.param"
|
|
97
|
+
default: Default value if key not found
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
Configuration value
|
|
101
|
+
"""
|
|
102
|
+
parts = key.split(".")
|
|
103
|
+
|
|
104
|
+
# Get value from config
|
|
105
|
+
value = self.config_data
|
|
106
|
+
for part in parts:
|
|
107
|
+
if not isinstance(value, dict) or part not in value:
|
|
108
|
+
return default
|
|
109
|
+
value = value[part]
|
|
110
|
+
|
|
111
|
+
return value
|
|
112
|
+
|
|
113
|
+
def get_all(self) -> Dict[str, Any]:
|
|
114
|
+
"""
|
|
115
|
+
Get all configuration values.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
Dictionary with all configuration values
|
|
119
|
+
"""
|
|
120
|
+
return self.config_data.copy()
|
|
121
|
+
|
|
122
|
+
def set(self, key: str, value: Any) -> None:
|
|
123
|
+
"""
|
|
124
|
+
Set configuration value for key.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
key: Configuration key in format "section.param"
|
|
128
|
+
value: Configuration value
|
|
129
|
+
"""
|
|
130
|
+
parts = key.split(".")
|
|
131
|
+
if len(parts) == 1:
|
|
132
|
+
self.config_data[key] = value
|
|
133
|
+
else:
|
|
134
|
+
section = parts[0]
|
|
135
|
+
|
|
136
|
+
if section not in self.config_data:
|
|
137
|
+
self.config_data[section] = {}
|
|
138
|
+
|
|
139
|
+
current = self.config_data[section]
|
|
140
|
+
for part in parts[1:-1]:
|
|
141
|
+
if part not in current:
|
|
142
|
+
current[part] = {}
|
|
143
|
+
current = current[part]
|
|
144
|
+
|
|
145
|
+
current[parts[-1]] = value
|
|
146
|
+
|
|
147
|
+
def save(self, path: Optional[str] = None) -> None:
|
|
148
|
+
"""
|
|
149
|
+
Save configuration to file.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
path: Path to configuration file. If not specified,
|
|
153
|
+
self.config_path is used.
|
|
154
|
+
"""
|
|
155
|
+
save_path = path or self.config_path
|
|
156
|
+
with open(save_path, "w", encoding="utf-8") as f:
|
|
157
|
+
json.dump(self.config_data, f, indent=2)
|
|
158
|
+
|
|
159
|
+
def configure_auth_mode(self, mode: str, **kwargs) -> None:
|
|
160
|
+
"""
|
|
161
|
+
Configure authentication mode.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
mode: Authentication mode (none, api_key, jwt, certificate, basic)
|
|
165
|
+
**kwargs: Additional configuration parameters
|
|
166
|
+
"""
|
|
167
|
+
self.set("auth.method", mode)
|
|
168
|
+
|
|
169
|
+
if mode == "api_key":
|
|
170
|
+
if "key" in kwargs:
|
|
171
|
+
self.set("auth.api_key.key", kwargs["key"])
|
|
172
|
+
if "header" in kwargs:
|
|
173
|
+
self.set("auth.api_key.header", kwargs["header"])
|
|
174
|
+
elif mode == "jwt":
|
|
175
|
+
if "username" in kwargs:
|
|
176
|
+
self.set("auth.jwt.username", kwargs["username"])
|
|
177
|
+
if "password" in kwargs:
|
|
178
|
+
self.set("auth.jwt.password", kwargs["password"])
|
|
179
|
+
if "secret" in kwargs:
|
|
180
|
+
self.set("auth.jwt.secret", kwargs["secret"])
|
|
181
|
+
if "expiry_hours" in kwargs:
|
|
182
|
+
self.set("auth.jwt.expiry_hours", kwargs["expiry_hours"])
|
|
183
|
+
elif mode == "certificate":
|
|
184
|
+
self.set("auth.certificate.enabled", True)
|
|
185
|
+
if "cert_file" in kwargs:
|
|
186
|
+
self.set("auth.certificate.cert_file", kwargs["cert_file"])
|
|
187
|
+
if "key_file" in kwargs:
|
|
188
|
+
self.set("auth.certificate.key_file", kwargs["key_file"])
|
|
189
|
+
if "ca_cert_file" in kwargs:
|
|
190
|
+
self.set("auth.certificate.ca_cert_file", kwargs["ca_cert_file"])
|
|
191
|
+
elif mode == "basic":
|
|
192
|
+
if "username" in kwargs:
|
|
193
|
+
self.set("auth.basic.username", kwargs["username"])
|
|
194
|
+
if "password" in kwargs:
|
|
195
|
+
self.set("auth.basic.password", kwargs["password"])
|
|
196
|
+
|
|
197
|
+
def configure_ssl(self, enabled: bool = True, **kwargs) -> None:
|
|
198
|
+
"""
|
|
199
|
+
Configure SSL/TLS settings.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
enabled: Enable SSL/TLS
|
|
203
|
+
**kwargs: Additional SSL configuration parameters
|
|
204
|
+
"""
|
|
205
|
+
self.set("ssl.enabled", enabled)
|
|
206
|
+
|
|
207
|
+
if "verify" in kwargs:
|
|
208
|
+
self.set("ssl.verify", kwargs["verify"])
|
|
209
|
+
if "check_hostname" in kwargs:
|
|
210
|
+
self.set("ssl.check_hostname", kwargs["check_hostname"])
|
|
211
|
+
if "cert_file" in kwargs:
|
|
212
|
+
self.set("ssl.cert_file", kwargs["cert_file"])
|
|
213
|
+
if "key_file" in kwargs:
|
|
214
|
+
self.set("ssl.key_file", kwargs["key_file"])
|
|
215
|
+
if "ca_cert_file" in kwargs:
|
|
216
|
+
self.set("ssl.ca_cert_file", kwargs["ca_cert_file"])
|
|
217
|
+
if "client_cert_required" in kwargs:
|
|
218
|
+
self.set("ssl.client_cert_required", kwargs["client_cert_required"])
|
|
219
|
+
|
|
220
|
+
def configure_server(
|
|
221
|
+
self, host: str, port: int, base_url: Optional[str] = None
|
|
222
|
+
) -> None:
|
|
223
|
+
"""
|
|
224
|
+
Configure server connection settings.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
host: Server host
|
|
228
|
+
port: Server port
|
|
229
|
+
base_url: Full server URL (optional, will be constructed if not provided)
|
|
230
|
+
"""
|
|
231
|
+
self.set("server.host", host)
|
|
232
|
+
self.set("server.port", port)
|
|
233
|
+
|
|
234
|
+
if base_url:
|
|
235
|
+
self.set("server.base_url", base_url)
|
|
236
|
+
else:
|
|
237
|
+
protocol = "https" if self.get("ssl.enabled", False) else "http"
|
|
238
|
+
self.set("server.base_url", f"{protocol}://{host}:{port}")
|
|
239
|
+
|
|
240
|
+
def get_server_url(self) -> str:
|
|
241
|
+
"""
|
|
242
|
+
Get the complete server URL.
|
|
243
|
+
|
|
244
|
+
Returns:
|
|
245
|
+
Server URL string
|
|
246
|
+
"""
|
|
247
|
+
return self.get("server.base_url", "http://localhost:8001")
|
|
248
|
+
|
|
249
|
+
def get_auth_method(self) -> str:
|
|
250
|
+
"""
|
|
251
|
+
Get the authentication method.
|
|
252
|
+
|
|
253
|
+
Returns:
|
|
254
|
+
Authentication method string
|
|
255
|
+
"""
|
|
256
|
+
return self.get("auth.method", "none")
|
|
257
|
+
|
|
258
|
+
def is_ssl_enabled(self) -> bool:
|
|
259
|
+
"""
|
|
260
|
+
Check if SSL/TLS is enabled.
|
|
261
|
+
|
|
262
|
+
Returns:
|
|
263
|
+
True if SSL is enabled, False otherwise
|
|
264
|
+
"""
|
|
265
|
+
return self.get("ssl.enabled", False)
|
|
266
|
+
|
|
267
|
+
def is_auth_enabled(self) -> bool:
|
|
268
|
+
"""
|
|
269
|
+
Check if authentication is enabled.
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
True if authentication is enabled, False otherwise
|
|
273
|
+
"""
|
|
274
|
+
return self.get("auth.method", "none") != "none"
|
|
275
|
+
|
|
276
|
+
def is_security_enabled(self) -> bool:
|
|
277
|
+
"""
|
|
278
|
+
Check if security features are enabled.
|
|
279
|
+
|
|
280
|
+
Returns:
|
|
281
|
+
True if security is enabled, False otherwise
|
|
282
|
+
"""
|
|
283
|
+
return self.get("security.enabled", False)
|
|
284
|
+
|
|
285
|
+
def validate_config(self) -> List[str]:
|
|
286
|
+
"""Validate configuration and return list of validation error messages."""
|
|
287
|
+
return validate_client_config(self)
|
|
288
|
+
|
|
289
|
+
def create_minimal_config(self) -> Dict[str, Any]:
|
|
290
|
+
"""Create minimal configuration with only essential features."""
|
|
291
|
+
return create_minimal_config_dict(self)
|
|
292
|
+
|
|
293
|
+
def create_secure_config(self) -> Dict[str, Any]:
|
|
294
|
+
"""Create secure configuration with all security features enabled."""
|
|
295
|
+
return create_secure_config_dict(self)
|
|
296
|
+
|
|
297
|
+
@classmethod
|
|
298
|
+
def from_dict(cls, config_dict: Dict[str, Any]) -> "ClientConfig":
|
|
299
|
+
"""
|
|
300
|
+
Create ClientConfig instance from dictionary.
|
|
301
|
+
|
|
302
|
+
Args:
|
|
303
|
+
config_dict: Configuration dictionary
|
|
304
|
+
|
|
305
|
+
Returns:
|
|
306
|
+
ClientConfig instance
|
|
307
|
+
"""
|
|
308
|
+
config = cls()
|
|
309
|
+
config.config_data = update_nested_dict(config.config_data, config_dict)
|
|
310
|
+
return config
|
|
311
|
+
|
|
312
|
+
@classmethod
|
|
313
|
+
def from_file(cls, config_path: str) -> "ClientConfig":
|
|
314
|
+
"""
|
|
315
|
+
Create ClientConfig instance from file.
|
|
316
|
+
|
|
317
|
+
Args:
|
|
318
|
+
config_path: Path to configuration file
|
|
319
|
+
|
|
320
|
+
Returns:
|
|
321
|
+
ClientConfig instance
|
|
322
|
+
"""
|
|
323
|
+
config = cls(config_path)
|
|
324
|
+
return config
|
|
325
|
+
|
|
326
|
+
@classmethod
|
|
327
|
+
def create_http_config(
|
|
328
|
+
cls, host: str = "localhost", port: int = 8001
|
|
329
|
+
) -> "ClientConfig":
|
|
330
|
+
"""Create configuration for HTTP connection without authentication."""
|
|
331
|
+
return create_http_config_for_class(cls, host=host, port=port)
|
|
332
|
+
|
|
333
|
+
@classmethod
|
|
334
|
+
def create_http_token_config(
|
|
335
|
+
cls,
|
|
336
|
+
host: str = "localhost",
|
|
337
|
+
port: int = 8001,
|
|
338
|
+
api_key: Optional[str] = None,
|
|
339
|
+
) -> "ClientConfig":
|
|
340
|
+
"""Create configuration for HTTP connection with API key authentication."""
|
|
341
|
+
return create_http_token_config_for_class(
|
|
342
|
+
cls,
|
|
343
|
+
host=host,
|
|
344
|
+
port=port,
|
|
345
|
+
api_key=api_key,
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
@classmethod
|
|
349
|
+
def create_https_config(
|
|
350
|
+
cls,
|
|
351
|
+
host: str = "localhost",
|
|
352
|
+
port: int = 8443,
|
|
353
|
+
cert_file: Optional[str] = None,
|
|
354
|
+
key_file: Optional[str] = None,
|
|
355
|
+
ca_cert_file: Optional[str] = None,
|
|
356
|
+
) -> "ClientConfig":
|
|
357
|
+
"""Create configuration for HTTPS connection without authentication."""
|
|
358
|
+
return create_https_config_for_class(
|
|
359
|
+
cls,
|
|
360
|
+
host=host,
|
|
361
|
+
port=port,
|
|
362
|
+
cert_file=cert_file,
|
|
363
|
+
key_file=key_file,
|
|
364
|
+
ca_cert_file=ca_cert_file,
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
@classmethod
|
|
368
|
+
def create_https_token_config(
|
|
369
|
+
cls,
|
|
370
|
+
host: str = "localhost",
|
|
371
|
+
port: int = 8443,
|
|
372
|
+
api_key: Optional[str] = None,
|
|
373
|
+
cert_file: Optional[str] = None,
|
|
374
|
+
key_file: Optional[str] = None,
|
|
375
|
+
ca_cert_file: Optional[str] = None,
|
|
376
|
+
) -> "ClientConfig":
|
|
377
|
+
"""Create configuration for HTTPS connection with API key authentication."""
|
|
378
|
+
return create_https_token_config_for_class(
|
|
379
|
+
cls,
|
|
380
|
+
host=host,
|
|
381
|
+
port=port,
|
|
382
|
+
api_key=api_key,
|
|
383
|
+
cert_file=cert_file,
|
|
384
|
+
key_file=key_file,
|
|
385
|
+
ca_cert_file=ca_cert_file,
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
@classmethod
|
|
389
|
+
def create_mtls_config(
|
|
390
|
+
cls,
|
|
391
|
+
host: str = "localhost",
|
|
392
|
+
port: int = 8443,
|
|
393
|
+
cert_file: Optional[str] = None,
|
|
394
|
+
key_file: Optional[str] = None,
|
|
395
|
+
ca_cert_file: Optional[str] = None,
|
|
396
|
+
) -> "ClientConfig":
|
|
397
|
+
"""Create configuration for mTLS connection with client certificates."""
|
|
398
|
+
return create_mtls_config_for_class(
|
|
399
|
+
cls,
|
|
400
|
+
host=host,
|
|
401
|
+
port=port,
|
|
402
|
+
cert_file=cert_file,
|
|
403
|
+
key_file=key_file,
|
|
404
|
+
ca_cert_file=ca_cert_file,
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
# Singleton instance
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Default configuration and helpers for embed-client ClientConfig.
|
|
3
|
+
|
|
4
|
+
Author: Vasiliy Zdanovskiy
|
|
5
|
+
email: vasilyvz@gmail.com
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any, Dict
|
|
11
|
+
|
|
12
|
+
DEFAULT_CONFIG: Dict[str, Any] = {
|
|
13
|
+
"server": {
|
|
14
|
+
"host": "localhost",
|
|
15
|
+
"port": 8001,
|
|
16
|
+
"base_url": "http://localhost:8001",
|
|
17
|
+
},
|
|
18
|
+
"timeout": 30,
|
|
19
|
+
"retry_attempts": 3,
|
|
20
|
+
"retry_delay": 1,
|
|
21
|
+
"auth": {
|
|
22
|
+
"method": "none", # none, api_key, jwt, certificate, basic
|
|
23
|
+
"api_key": {"key": None, "header": "X-API-Key"},
|
|
24
|
+
"jwt": {
|
|
25
|
+
"username": None,
|
|
26
|
+
"password": None,
|
|
27
|
+
"secret": None,
|
|
28
|
+
"expiry_hours": 24,
|
|
29
|
+
},
|
|
30
|
+
"certificate": {
|
|
31
|
+
"enabled": False,
|
|
32
|
+
"cert_file": None,
|
|
33
|
+
"key_file": None,
|
|
34
|
+
"ca_cert_file": None,
|
|
35
|
+
},
|
|
36
|
+
"basic": {"username": None, "password": None},
|
|
37
|
+
},
|
|
38
|
+
"ssl": {
|
|
39
|
+
"enabled": False,
|
|
40
|
+
"verify": True,
|
|
41
|
+
"check_hostname": True,
|
|
42
|
+
"cert_file": None,
|
|
43
|
+
"key_file": None,
|
|
44
|
+
"ca_cert_file": None,
|
|
45
|
+
"client_cert_required": False,
|
|
46
|
+
},
|
|
47
|
+
"security": {"enabled": False, "roles_enabled": False, "roles_file": None},
|
|
48
|
+
"logging": {
|
|
49
|
+
"enabled": False,
|
|
50
|
+
"level": "INFO",
|
|
51
|
+
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
52
|
+
},
|
|
53
|
+
"client": {"timeout": 30.0},
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def update_nested_dict(
|
|
58
|
+
target: Dict[str, Any], updates: Dict[str, Any]
|
|
59
|
+
) -> Dict[str, Any]:
|
|
60
|
+
"""Recursively update a nested dictionary in place.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
target: Dictionary to update.
|
|
64
|
+
updates: Dictionary with new values.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
The updated dictionary (same instance as ``target``).
|
|
68
|
+
"""
|
|
69
|
+
for key, value in updates.items():
|
|
70
|
+
if isinstance(value, dict) and key in target and isinstance(target[key], dict):
|
|
71
|
+
update_nested_dict(target[key], value)
|
|
72
|
+
else:
|
|
73
|
+
target[key] = value
|
|
74
|
+
return target
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
__all__ = ["DEFAULT_CONFIG", "update_nested_dict"]
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Configuration examples for all security modes.
|
|
3
|
+
|
|
4
|
+
This module provides ready-to-use configuration examples for all supported
|
|
5
|
+
security modes and authentication methods.
|
|
6
|
+
|
|
7
|
+
Author: Vasiliy Zdanovskiy
|
|
8
|
+
email: vasilyvz@gmail.com
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from typing import Dict, Any, Optional
|
|
12
|
+
from embed_client.config import ClientConfig
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_http_simple_config(host: str = "localhost", port: int = 8001) -> Dict[str, Any]:
|
|
16
|
+
"""
|
|
17
|
+
Get configuration for HTTP connection without authentication.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
host: Server host
|
|
21
|
+
port: Server port
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
Configuration dictionary
|
|
25
|
+
"""
|
|
26
|
+
config = ClientConfig.create_http_config(host, port)
|
|
27
|
+
return config.get_all()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_http_token_config(
|
|
31
|
+
host: str = "localhost", port: int = 8001, api_key: str = "test-token-123"
|
|
32
|
+
) -> Dict[str, Any]:
|
|
33
|
+
"""
|
|
34
|
+
Get configuration for HTTP connection with API key authentication.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
host: Server host
|
|
38
|
+
port: Server port
|
|
39
|
+
api_key: API key for authentication
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
Configuration dictionary
|
|
43
|
+
"""
|
|
44
|
+
config = ClientConfig.create_http_token_config(host, port, api_key)
|
|
45
|
+
return config.get_all()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def get_https_simple_config(
|
|
49
|
+
host: str = "localhost",
|
|
50
|
+
port: int = 8443,
|
|
51
|
+
cert_file: Optional[str] = None,
|
|
52
|
+
key_file: Optional[str] = None,
|
|
53
|
+
ca_cert_file: Optional[str] = None,
|
|
54
|
+
) -> Dict[str, Any]:
|
|
55
|
+
"""
|
|
56
|
+
Get configuration for HTTPS connection without authentication.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
host: Server host
|
|
60
|
+
port: Server port
|
|
61
|
+
cert_file: Client certificate file (optional)
|
|
62
|
+
key_file: Client key file (optional)
|
|
63
|
+
ca_cert_file: CA certificate file (optional)
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
Configuration dictionary
|
|
67
|
+
"""
|
|
68
|
+
config = ClientConfig.create_https_config(
|
|
69
|
+
host, port, cert_file, key_file, ca_cert_file
|
|
70
|
+
)
|
|
71
|
+
return config.get_all()
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def get_https_token_config(
|
|
75
|
+
host: str = "localhost",
|
|
76
|
+
port: int = 8443,
|
|
77
|
+
api_key: str = "test-token-123",
|
|
78
|
+
cert_file: Optional[str] = None,
|
|
79
|
+
key_file: Optional[str] = None,
|
|
80
|
+
ca_cert_file: Optional[str] = None,
|
|
81
|
+
) -> Dict[str, Any]:
|
|
82
|
+
"""
|
|
83
|
+
Get configuration for HTTPS connection with API key authentication.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
host: Server host
|
|
87
|
+
port: Server port
|
|
88
|
+
api_key: API key for authentication
|
|
89
|
+
cert_file: Client certificate file (optional)
|
|
90
|
+
key_file: Client key file (optional)
|
|
91
|
+
ca_cert_file: CA certificate file (optional)
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
Configuration dictionary
|
|
95
|
+
"""
|
|
96
|
+
config = ClientConfig.create_https_token_config(
|
|
97
|
+
host, port, api_key, cert_file, key_file, ca_cert_file
|
|
98
|
+
)
|
|
99
|
+
return config.get_all()
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def get_mtls_config(
|
|
103
|
+
host: str = "localhost",
|
|
104
|
+
port: int = 8443,
|
|
105
|
+
cert_file: str = "certs/client.crt",
|
|
106
|
+
key_file: str = "keys/client.key",
|
|
107
|
+
ca_cert_file: str = "certs/ca.crt",
|
|
108
|
+
) -> Dict[str, Any]:
|
|
109
|
+
"""
|
|
110
|
+
Get configuration for mTLS connection with client certificates.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
host: Server host
|
|
114
|
+
port: Server port
|
|
115
|
+
cert_file: Client certificate file
|
|
116
|
+
key_file: Client key file
|
|
117
|
+
ca_cert_file: CA certificate file
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
Configuration dictionary
|
|
121
|
+
"""
|
|
122
|
+
config = ClientConfig.create_mtls_config(
|
|
123
|
+
host, port, cert_file, key_file, ca_cert_file
|
|
124
|
+
)
|
|
125
|
+
return config.get_all()
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def get_jwt_config(
|
|
129
|
+
host: str = "localhost",
|
|
130
|
+
port: int = 8001,
|
|
131
|
+
username: str = "user",
|
|
132
|
+
password: str = "password",
|
|
133
|
+
secret: str = "jwt-secret",
|
|
134
|
+
expiry_hours: int = 24,
|
|
135
|
+
) -> Dict[str, Any]:
|
|
136
|
+
"""
|
|
137
|
+
Get configuration for HTTP connection with JWT authentication.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
host: Server host
|
|
141
|
+
port: Server port
|
|
142
|
+
username: Username for JWT
|
|
143
|
+
password: Password for JWT
|
|
144
|
+
secret: JWT secret key
|
|
145
|
+
expiry_hours: JWT token expiry in hours
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
Configuration dictionary
|
|
149
|
+
"""
|
|
150
|
+
config = ClientConfig()
|
|
151
|
+
config.configure_server(host, port)
|
|
152
|
+
config.configure_auth_mode(
|
|
153
|
+
"jwt",
|
|
154
|
+
username=username,
|
|
155
|
+
password=password,
|
|
156
|
+
secret=secret,
|
|
157
|
+
expiry_hours=expiry_hours,
|
|
158
|
+
)
|
|
159
|
+
return config.get_all()
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def get_basic_auth_config(
|
|
163
|
+
host: str = "localhost",
|
|
164
|
+
port: int = 8001,
|
|
165
|
+
username: str = "user",
|
|
166
|
+
password: str = "password",
|
|
167
|
+
) -> Dict[str, Any]:
|
|
168
|
+
"""
|
|
169
|
+
Get configuration for HTTP connection with basic authentication.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
host: Server host
|
|
173
|
+
port: Server port
|
|
174
|
+
username: Username for basic auth
|
|
175
|
+
password: Password for basic auth
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
Configuration dictionary
|
|
179
|
+
"""
|
|
180
|
+
config = ClientConfig()
|
|
181
|
+
config.configure_server(host, port)
|
|
182
|
+
config.configure_auth_mode("basic", username=username, password=password)
|
|
183
|
+
return config.get_all()
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def get_all_config_examples() -> Dict[str, Dict[str, Any]]:
|
|
187
|
+
"""
|
|
188
|
+
Get all configuration examples.
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
Dictionary with all configuration examples
|
|
192
|
+
"""
|
|
193
|
+
return {
|
|
194
|
+
"http_simple": get_http_simple_config(),
|
|
195
|
+
"http_token": get_http_token_config(),
|
|
196
|
+
"https_simple": get_https_simple_config(),
|
|
197
|
+
"https_token": get_https_token_config(),
|
|
198
|
+
"mtls": get_mtls_config(),
|
|
199
|
+
"jwt": get_jwt_config(),
|
|
200
|
+
"basic_auth": get_basic_auth_config(),
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def save_config_examples(output_dir: str = "configs") -> None:
|
|
205
|
+
"""
|
|
206
|
+
Save all configuration examples to files.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
output_dir: Output directory for configuration files
|
|
210
|
+
"""
|
|
211
|
+
import os
|
|
212
|
+
import json
|
|
213
|
+
|
|
214
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
215
|
+
|
|
216
|
+
examples = get_all_config_examples()
|
|
217
|
+
|
|
218
|
+
for name, config in examples.items():
|
|
219
|
+
filename = os.path.join(output_dir, f"{name}.json")
|
|
220
|
+
with open(filename, "w", encoding="utf-8") as f:
|
|
221
|
+
json.dump(config, f, indent=2, ensure_ascii=False)
|
|
222
|
+
print(f"Saved configuration: {filename}")
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
if __name__ == "__main__":
|
|
226
|
+
# Save all configuration examples
|
|
227
|
+
save_config_examples()
|
|
228
|
+
print("All configuration examples saved to 'configs/' directory")
|