agent-api-server 2.1.7__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.
Files changed (52) hide show
  1. agent_api_server/__init__.py +0 -0
  2. agent_api_server/api/__init__.py +0 -0
  3. agent_api_server/api/v1/__init__.py +0 -0
  4. agent_api_server/api/v1/api.py +25 -0
  5. agent_api_server/api/v1/config.py +57 -0
  6. agent_api_server/api/v1/graph.py +59 -0
  7. agent_api_server/api/v1/schema.py +57 -0
  8. agent_api_server/api/v1/thread.py +563 -0
  9. agent_api_server/cache/__init__.py +0 -0
  10. agent_api_server/cache/redis_cache.py +385 -0
  11. agent_api_server/callback_handler.py +18 -0
  12. agent_api_server/client/css/styles.css +1202 -0
  13. agent_api_server/client/favicon.ico +0 -0
  14. agent_api_server/client/index.html +102 -0
  15. agent_api_server/client/js/app.js +1499 -0
  16. agent_api_server/client/js/index.umd.js +824 -0
  17. agent_api_server/config_center/config_center.py +239 -0
  18. agent_api_server/configs/__init__.py +3 -0
  19. agent_api_server/configs/config.py +163 -0
  20. agent_api_server/dynamic_llm/__init__.py +0 -0
  21. agent_api_server/dynamic_llm/dynamic_llm.py +331 -0
  22. agent_api_server/listener.py +530 -0
  23. agent_api_server/log/__init__.py +0 -0
  24. agent_api_server/log/formatters.py +122 -0
  25. agent_api_server/log/logging.json +50 -0
  26. agent_api_server/mcp_convert/__init__.py +0 -0
  27. agent_api_server/mcp_convert/mcp_convert.py +375 -0
  28. agent_api_server/memeory/__init__.py +0 -0
  29. agent_api_server/memeory/postgres.py +233 -0
  30. agent_api_server/register/__init__.py +0 -0
  31. agent_api_server/register/register.py +65 -0
  32. agent_api_server/service.py +354 -0
  33. agent_api_server/service_hub/service_hub.py +233 -0
  34. agent_api_server/service_hub/service_hub_test.py +700 -0
  35. agent_api_server/shared/__init__.py +0 -0
  36. agent_api_server/shared/ase.py +54 -0
  37. agent_api_server/shared/base_model.py +103 -0
  38. agent_api_server/shared/common.py +110 -0
  39. agent_api_server/shared/decode_token.py +107 -0
  40. agent_api_server/shared/detect_message.py +410 -0
  41. agent_api_server/shared/get_model_info.py +491 -0
  42. agent_api_server/shared/message.py +419 -0
  43. agent_api_server/shared/util_func.py +372 -0
  44. agent_api_server/sso_service/__init__.py +1 -0
  45. agent_api_server/sso_service/sdk/__init__.py +1 -0
  46. agent_api_server/sso_service/sdk/client.py +224 -0
  47. agent_api_server/sso_service/sdk/credential.py +11 -0
  48. agent_api_server/sso_service/sdk/encoding.py +22 -0
  49. agent_api_server/sso_service/sso_service.py +177 -0
  50. agent_api_server-2.1.7.dist-info/METADATA +130 -0
  51. agent_api_server-2.1.7.dist-info/RECORD +52 -0
  52. agent_api_server-2.1.7.dist-info/WHEEL +4 -0
@@ -0,0 +1,700 @@
1
+ import unittest
2
+ from service_hub import (
3
+ ServiceHubCredentialParser,
4
+ ServiceHubCredentials,
5
+ PostgresCredential,
6
+ RedisCredential,
7
+ BlobstoreCredential,
8
+ CredentialNotFoundError,
9
+ InvalidCredentialError
10
+ )
11
+
12
+
13
+ class TestServiceHubCredentialParser(unittest.TestCase):
14
+ def test_parse_postgres(self):
15
+ data = {
16
+ "postgresql": [{
17
+ "async": False,
18
+ "binding_name": "iothub",
19
+ "credentials": {
20
+ "database": "iothub-qa",
21
+ "externalHosts": "10.1.17.126:5432",
22
+ "host": "10.1.17.126",
23
+ "internalHosts": "10.1.17.126:5432",
24
+ "password": "i1t5ykL3Voh7zy8OcOq1XLiGp",
25
+ "port": 5432,
26
+ "uri": "postgres://c800e6b9-1061-42ce-8517-b534ecce095e:i1t5ykL3Voh7zy8OcOq1XLiGp@10.1.17.126:5432/iothub-qa",
27
+ "username": "c800e6b9-1061-42ce-8517-b534ecce095e"
28
+ },
29
+ "instance_name": "PostgreSQL-APPBUY",
30
+ "label": "PostgreSQL",
31
+ "plan": "Dedicated-Single-Small",
32
+ "serviceInstanceId": "acd174dd-4098-4967-a492-b336337f8d0a",
33
+ "subscriptionId": "2425c243ebd369a03381439378ac78b4"
34
+ }]
35
+ }
36
+
37
+ credentials = ServiceHubCredentialParser.parse(data)
38
+ self.assertEqual(len(credentials.postgres), 1)
39
+ self.assertEqual(credentials.postgres[0].database, "iothub-qa")
40
+ self.assertEqual(credentials.postgres[0].uri,
41
+ "postgres://c800e6b9-1061-42ce-8517-b534ecce095e:i1t5ykL3Voh7zy8OcOq1XLiGp@10.1.17.126:5432/iothub-qa")
42
+
43
+ def test_parse_redis(self):
44
+ data = {
45
+ "redis": [{
46
+ "binding_name": "fms",
47
+ "credentials": {
48
+ "externalHosts": "",
49
+ "host": "redis-6a3adc0c-05ad-44ab-a780-ee943ff7808e-master.wiseiot.svc",
50
+ "internalHosts": "redis-6a3adc0c-05ad-44ab-a780-ee943ff7808e-master.wiseiot.svc",
51
+ "password": "xxxxx",
52
+ "port": 6379
53
+ },
54
+ "instance_name": "Redis",
55
+ "label": "Redis",
56
+ "plan": "Containerized-V2",
57
+ "serviceInstanceId": "6a3adc0c-05ad-44ab-a780-ee943ff7808e",
58
+ "subscriptionId": "77cc3194-b37a-5c91-9063-99c82e57b385"
59
+ }]
60
+ }
61
+
62
+ credentials = ServiceHubCredentialParser.parse(data)
63
+ self.assertEqual(len(credentials.redis), 1)
64
+ self.assertEqual(credentials.redis[0].host, "redis-6a3adc0c-05ad-44ab-a780-ee943ff7808e-master.wiseiot.svc")
65
+ self.assertEqual(credentials.redis[0].port, 6379)
66
+
67
+ def test_parse_redis_with_username(self):
68
+ data = {
69
+ "redis": [{
70
+ "binding_name": "fms",
71
+ "credentials": {
72
+ "externalHosts": "",
73
+ "host": "redis.example.com",
74
+ "internalHosts": "redis.internal.example.com",
75
+ "password": "pass123",
76
+ "username": "user1",
77
+ "port": 6379
78
+ }
79
+ }]
80
+ }
81
+
82
+ credentials = ServiceHubCredentialParser.parse(data)
83
+ self.assertEqual(len(credentials.redis), 1)
84
+ self.assertEqual(credentials.redis[0].username, "user1")
85
+
86
+ def test_parse_blobstore(self):
87
+ """Test parsing blobstore credentials"""
88
+ data = {
89
+ "blobstore": [{
90
+ "binding_name": "storage",
91
+ "credentials": {
92
+ "accessKey": "AKIAIOSFODNN7EXAMPLE",
93
+ "secretKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
94
+ "endpoint": "https://s3.example.com",
95
+ "externalHosts": "s3.example.com",
96
+ "internalHosts": "s3.internal.example.com",
97
+ "signature-version": "s3v4",
98
+ "type": "s3"
99
+ },
100
+ "instance_name": "Blobstore-Example",
101
+ "label": "Blobstore",
102
+ "plan": "Standard",
103
+ "serviceInstanceId": "12345678-1234-1234-1234-123456789012",
104
+ "subscriptionId": "abcdef123456"
105
+ }]
106
+ }
107
+
108
+ credentials = ServiceHubCredentialParser.parse(data)
109
+ self.assertEqual(len(credentials.blobstore), 1)
110
+ blobstore_cred = credentials.blobstore[0]
111
+ self.assertEqual(blobstore_cred.binding_name, "storage")
112
+ self.assertEqual(blobstore_cred.access_key, "AKIAIOSFODNN7EXAMPLE")
113
+ self.assertEqual(blobstore_cred.secret_key, "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY")
114
+ self.assertEqual(blobstore_cred.endpoint, "https://s3.example.com")
115
+ self.assertEqual(blobstore_cred.external_hosts, "s3.example.com")
116
+ self.assertEqual(blobstore_cred.internal_hosts, "s3.internal.example.com")
117
+ self.assertEqual(blobstore_cred.signature_version, "s3v4")
118
+ self.assertEqual(blobstore_cred.type, "s3")
119
+ self.assertEqual(blobstore_cred.instance_name, "Blobstore-Example")
120
+ self.assertEqual(blobstore_cred.service_instance_id, "12345678-1234-1234-1234-123456789012")
121
+
122
+ def test_parse_blobstore_with_minimal_fields(self):
123
+ """Test parsing blobstore with minimal required fields"""
124
+ data = {
125
+ "blobstore": [{
126
+ "binding_name": "minimal-storage",
127
+ "credentials": {
128
+ "accessKey": "minimal-access-key",
129
+ "secretKey": "minimal-secret-key",
130
+ "endpoint": "https://minimal.s3.com",
131
+ "externalHosts": "minimal.s3.com",
132
+ "internalHosts": "minimal.internal.s3.com",
133
+ "signature-version": "s3",
134
+ "type": "s3"
135
+ }
136
+ }]
137
+ }
138
+
139
+ credentials = ServiceHubCredentialParser.parse(data)
140
+ self.assertEqual(len(credentials.blobstore), 1)
141
+ blobstore_cred = credentials.blobstore[0]
142
+ self.assertEqual(blobstore_cred.binding_name, "minimal-storage")
143
+ self.assertEqual(blobstore_cred.access_key, "minimal-access-key")
144
+ self.assertEqual(blobstore_cred.secret_key, "minimal-secret-key")
145
+ self.assertEqual(blobstore_cred.endpoint, "https://minimal.s3.com")
146
+ # 测试默认值
147
+ self.assertEqual(blobstore_cred.instance_name, "")
148
+ self.assertEqual(blobstore_cred.service_instance_id, "")
149
+
150
+ def test_parse_multiple_blobstores(self):
151
+ """Test parsing multiple blobstore entries"""
152
+ data = {
153
+ "blobstore": [
154
+ {
155
+ "binding_name": "storage1",
156
+ "credentials": {
157
+ "accessKey": "key1",
158
+ "secretKey": "secret1",
159
+ "endpoint": "https://s3-1.example.com",
160
+ "externalHosts": "s3-1.example.com",
161
+ "internalHosts": "s3-1.internal.example.com",
162
+ "signature-version": "s3v4",
163
+ "type": "s3"
164
+ }
165
+ },
166
+ {
167
+ "binding_name": "storage2",
168
+ "credentials": {
169
+ "accessKey": "key2",
170
+ "secretKey": "secret2",
171
+ "endpoint": "https://s3-2.example.com",
172
+ "externalHosts": "s3-2.example.com",
173
+ "internalHosts": "s3-2.internal.example.com",
174
+ "signature-version": "s3",
175
+ "type": "s3"
176
+ }
177
+ }
178
+ ]
179
+ }
180
+
181
+ credentials = ServiceHubCredentialParser.parse(data)
182
+ self.assertEqual(len(credentials.blobstore), 2)
183
+ self.assertEqual(credentials.blobstore[0].binding_name, "storage1")
184
+ self.assertEqual(credentials.blobstore[1].binding_name, "storage2")
185
+ self.assertEqual(credentials.blobstore[0].access_key, "key1")
186
+ self.assertEqual(credentials.blobstore[1].access_key, "key2")
187
+
188
+ def test_parse_all_service_types(self):
189
+ data = {
190
+ "postgresql": [{
191
+ "binding_name": "db",
192
+ "credentials": {
193
+ "database": "testdb",
194
+ "host": "localhost",
195
+ "internalHosts": "localhost:5432",
196
+ "password": "dbpass",
197
+ "port": 5432,
198
+ "username": "dbuser"
199
+ }
200
+ }],
201
+ "redis": [{
202
+ "binding_name": "cache",
203
+ "credentials": {
204
+ "host": "localhost",
205
+ "internalHosts": "localhost:6379",
206
+ "password": "redpass",
207
+ "port": 6379
208
+ }
209
+ }],
210
+ "blobstore": [{
211
+ "binding_name": "storage",
212
+ "credentials": {
213
+ "accessKey": "test-key",
214
+ "secretKey": "test-secret",
215
+ "endpoint": "https://test.s3.com",
216
+ "externalHosts": "test.s3.com",
217
+ "internalHosts": "test.internal.s3.com",
218
+ "signature-version": "s3v4",
219
+ "type": "s3"
220
+ }
221
+ }]
222
+ }
223
+
224
+ credentials = ServiceHubCredentialParser.parse(data)
225
+ self.assertEqual(len(credentials.postgres), 1)
226
+ self.assertEqual(len(credentials.redis), 1)
227
+ self.assertEqual(len(credentials.blobstore), 1)
228
+ self.assertEqual(credentials.postgres[0].database, "testdb")
229
+ self.assertEqual(credentials.redis[0].host, "localhost")
230
+ self.assertEqual(credentials.blobstore[0].access_key, "test-key")
231
+
232
+ def test_parse_invalid_json(self):
233
+ with self.assertRaises(InvalidCredentialError):
234
+ ServiceHubCredentialParser.parse("invalid json")
235
+
236
+ def test_parse_invalid_data_type(self):
237
+ with self.assertRaises(InvalidCredentialError):
238
+ ServiceHubCredentialParser.parse(["not", "a", "dict"])
239
+
240
+ def test_parse_json_string(self):
241
+ json_str = '''
242
+ {
243
+ "blobstore": [{
244
+ "binding_name": "json-string-storage",
245
+ "credentials": {
246
+ "accessKey": "json-key",
247
+ "secretKey": "json-secret",
248
+ "endpoint": "https://json.s3.com",
249
+ "externalHosts": "json.s3.com",
250
+ "internalHosts": "json.internal.s3.com",
251
+ "signature-version": "s3v4",
252
+ "type": "s3"
253
+ }
254
+ }]
255
+ }
256
+ '''
257
+ credentials = ServiceHubCredentialParser.parse(json_str)
258
+ self.assertEqual(len(credentials.blobstore), 1)
259
+ self.assertEqual(credentials.blobstore[0].binding_name, "json-string-storage")
260
+
261
+ def test_parse_json_bytes(self):
262
+ json_bytes = b'''{
263
+ "blobstore": [{
264
+ "binding_name": "bytes-storage",
265
+ "credentials": {
266
+ "accessKey": "bytes-key",
267
+ "secretKey": "bytes-secret",
268
+ "endpoint": "https://bytes.s3.com",
269
+ "externalHosts": "bytes.s3.com",
270
+ "internalHosts": "bytes.internal.s3.com",
271
+ "signature-version": "s3v4",
272
+ "type": "s3"
273
+ }
274
+ }]
275
+ }'''
276
+ credentials = ServiceHubCredentialParser.parse(json_bytes)
277
+ self.assertEqual(len(credentials.blobstore), 1)
278
+ self.assertEqual(credentials.blobstore[0].binding_name, "bytes-storage")
279
+
280
+ def test_parse_empty_data(self):
281
+ credentials = ServiceHubCredentialParser.parse({})
282
+ self.assertEqual(len(credentials.postgres), 0)
283
+ self.assertEqual(len(credentials.redis), 0)
284
+ self.assertEqual(len(credentials.blobstore), 0)
285
+
286
+
287
+ class TestServiceHubCredentials(unittest.TestCase):
288
+ def setUp(self):
289
+ self.postgres_cred = PostgresCredential(
290
+ async_flag=False,
291
+ binding_name="iothub",
292
+ database="iothub-qa",
293
+ external_hosts="10.1.17.126:5432",
294
+ host="10.1.17.126",
295
+ internal_hosts="10.1.17.126:5432",
296
+ password="i1t5ykL3Voh7zy8OcOq1XLiGp",
297
+ port=5432,
298
+ uri="postgres://c800e6b9-1061-42ce-8517-b534ecce095e:i1t5ykL3Voh7zy8OcOq1XLiGp@10.1.17.126:5432/iothub-qa",
299
+ username="c800e6b9-1061-42ce-8517-b534ecce095e",
300
+ instance_name="PostgreSQL-APPBUY",
301
+ label="PostgreSQL",
302
+ plan="Dedicated-Single-Small",
303
+ service_instance_id="acd174dd-4098-4967-a492-b336337f8d0a",
304
+ subscription_id="2425c243ebd369a03381439378ac78b4"
305
+ )
306
+
307
+ self.redis_cred_with_password = RedisCredential(
308
+ binding_name="fms",
309
+ external_hosts="",
310
+ host="redis-6a3adc0c-05ad-44ab-a780-ee943ff7808e-master.wiseiot.svc",
311
+ internal_hosts="redis-6a3adc0c-05ad-44ab-a780-ee943ff7808e-master.wiseiot.svc",
312
+ password="xxxxx",
313
+ port=6379,
314
+ instance_name="Redis",
315
+ label="Redis",
316
+ plan="Containerized-V2",
317
+ service_instance_id="6a3adc0c-05ad-44ab-a780-ee943ff7808e",
318
+ subscription_id="77cc3194-b37a-5c91-9063-99c82e57b385"
319
+ )
320
+
321
+ self.redis_cred_with_username_password = RedisCredential(
322
+ binding_name="fms",
323
+ external_hosts="",
324
+ host="redis.example.com",
325
+ internal_hosts="redis.internal.example.com",
326
+ password="pass123",
327
+ username="user1",
328
+ port=6379
329
+ )
330
+
331
+ self.redis_cred_with_username_no_password = RedisCredential(
332
+ binding_name="fms",
333
+ external_hosts="",
334
+ host="redis.example.com",
335
+ internal_hosts="redis.internal.example.com",
336
+ password="",
337
+ username="user1",
338
+ port=6379
339
+ )
340
+
341
+ self.redis_cred_no_auth = RedisCredential(
342
+ binding_name="fms",
343
+ external_hosts="",
344
+ host="redis.example.com",
345
+ internal_hosts="redis.internal.example.com",
346
+ password="",
347
+ username="",
348
+ port=6379
349
+ )
350
+
351
+ self.blobstore_cred_full = BlobstoreCredential(
352
+ binding_name="storage",
353
+ access_key="AKIAIOSFODNN7EXAMPLE",
354
+ secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
355
+ endpoint="https://s3.example.com",
356
+ external_hosts="s3.example.com",
357
+ internal_hosts="s3.internal.example.com",
358
+ signature_version="s3v4",
359
+ type="s3",
360
+ instance_name="Blobstore-Example",
361
+ label="Blobstore",
362
+ plan="Standard",
363
+ service_instance_id="12345678-1234-1234-1234-123456789012",
364
+ subscription_id="abcdef123456"
365
+ )
366
+
367
+ self.blobstore_cred_minimal = BlobstoreCredential(
368
+ binding_name="minimal-storage",
369
+ access_key="minimal-access-key",
370
+ secret_key="minimal-secret-key",
371
+ endpoint="https://minimal.s3.com",
372
+ external_hosts="minimal.s3.com",
373
+ internal_hosts="minimal.internal.s3.com",
374
+ signature_version="s3",
375
+ type="s3"
376
+ )
377
+
378
+ def test_to_postgres_dsn(self):
379
+ credentials = ServiceHubCredentials(postgres=[self.postgres_cred])
380
+ dsn = credentials.to_postgres_dsn()
381
+ expected = "postgresql://c800e6b9-1061-42ce-8517-b534ecce095e:i1t5ykL3Voh7zy8OcOq1XLiGp@10.1.17.126:5432/iothub-qa"
382
+ self.assertEqual(dsn, expected)
383
+
384
+ def test_to_postgres_dsn_no_credentials(self):
385
+ credentials = ServiceHubCredentials()
386
+ with self.assertRaises(CredentialNotFoundError) as context:
387
+ credentials.to_postgres_dsn()
388
+ self.assertIn("PostgreSQL credentials not found", str(context.exception))
389
+
390
+ def test_to_redis_dsn_with_password(self):
391
+ credentials = ServiceHubCredentials(redis=[self.redis_cred_with_password])
392
+ dsn = credentials.to_redis_dsn()
393
+ expected = "redis://:xxxxx@redis-6a3adc0c-05ad-44ab-a780-ee943ff7808e-master.wiseiot.svc:6379"
394
+ self.assertEqual(dsn, expected)
395
+
396
+ def test_to_redis_dsn_with_username_password(self):
397
+ credentials = ServiceHubCredentials(redis=[self.redis_cred_with_username_password])
398
+ dsn = credentials.to_redis_dsn()
399
+ expected = "redis://user1:pass123@redis.internal.example.com:6379"
400
+ self.assertEqual(dsn, expected)
401
+
402
+ def test_to_redis_dsn_with_username_no_password(self):
403
+ credentials = ServiceHubCredentials(redis=[self.redis_cred_with_username_no_password])
404
+ dsn = credentials.to_redis_dsn()
405
+ expected = "redis://user1@redis.internal.example.com:6379"
406
+ self.assertEqual(dsn, expected)
407
+
408
+ def test_to_redis_dsn_no_auth(self):
409
+ credentials = ServiceHubCredentials(redis=[self.redis_cred_no_auth])
410
+ dsn = credentials.to_redis_dsn()
411
+ expected = "redis://redis.internal.example.com:6379"
412
+ self.assertEqual(dsn, expected)
413
+
414
+ def test_to_redis_dsn_no_credentials(self):
415
+ credentials = ServiceHubCredentials()
416
+ with self.assertRaises(CredentialNotFoundError) as context:
417
+ credentials.to_redis_dsn()
418
+ self.assertIn("Redis credentials not found", str(context.exception))
419
+
420
+ def test_get_blobstore_s3_config_full(self):
421
+ credentials = ServiceHubCredentials(blobstore=[self.blobstore_cred_full])
422
+ config = credentials.get_blobstore_s3_config()
423
+
424
+ expected = {
425
+ "access_key": "AKIAIOSFODNN7EXAMPLE",
426
+ "secret_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
427
+ "endpoint": "https://s3.example.com",
428
+ "external_hosts": "s3.example.com",
429
+ "internal_hosts": "s3.internal.example.com",
430
+ "signature_version": "s3v4",
431
+ "type": "s3"
432
+ }
433
+
434
+ self.assertEqual(config, expected)
435
+ self.assertEqual(config["access_key"], "AKIAIOSFODNN7EXAMPLE")
436
+ self.assertEqual(config["secret_key"], "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY")
437
+ self.assertEqual(config["endpoint"], "https://s3.example.com")
438
+
439
+ def test_get_blobstore_s3_config_minimal(self):
440
+ """Test getting minimal blobstore S3 configuration"""
441
+ credentials = ServiceHubCredentials(blobstore=[self.blobstore_cred_minimal])
442
+ config = credentials.get_blobstore_s3_config()
443
+
444
+ expected = {
445
+ "access_key": "minimal-access-key",
446
+ "secret_key": "minimal-secret-key",
447
+ "endpoint": "https://minimal.s3.com",
448
+ "external_hosts": "minimal.s3.com",
449
+ "internal_hosts": "minimal.internal.s3.com",
450
+ "signature_version": "s3",
451
+ "type": "s3"
452
+ }
453
+
454
+ self.assertEqual(config, expected)
455
+ self.assertEqual(config["access_key"], "minimal-access-key")
456
+ self.assertEqual(config["secret_key"], "minimal-secret-key")
457
+ self.assertEqual(config["signature_version"], "s3")
458
+
459
+ def test_get_blobstore_s3_config_no_credentials(self):
460
+ credentials = ServiceHubCredentials()
461
+ with self.assertRaises(CredentialNotFoundError) as context:
462
+ credentials.get_blobstore_s3_config()
463
+ self.assertIn("Blobstore credentials not found", str(context.exception))
464
+
465
+ def test_get_blobstore_s3_config_multiple_blobstores(self):
466
+ blobstore1 = BlobstoreCredential(
467
+ binding_name="first",
468
+ access_key="first-key",
469
+ secret_key="first-secret",
470
+ endpoint="https://first.s3.com",
471
+ external_hosts="first.s3.com",
472
+ internal_hosts="first.internal.s3.com",
473
+ signature_version="s3v4",
474
+ type="s3"
475
+ )
476
+
477
+ blobstore2 = BlobstoreCredential(
478
+ binding_name="second",
479
+ access_key="second-key",
480
+ secret_key="second-secret",
481
+ endpoint="https://second.s3.com",
482
+ external_hosts="second.s3.com",
483
+ internal_hosts="second.internal.s3.com",
484
+ signature_version="s3",
485
+ type="s3"
486
+ )
487
+
488
+ credentials = ServiceHubCredentials(blobstore=[blobstore1, blobstore2])
489
+ config = credentials.get_blobstore_s3_config()
490
+
491
+ self.assertEqual(config["access_key"], "first-key")
492
+ self.assertEqual(config["secret_key"], "first-secret")
493
+ self.assertEqual(config["endpoint"], "https://first.s3.com")
494
+ self.assertEqual(config["signature_version"], "s3v4")
495
+
496
+ def test_get_service_instance_id_from_postgres(self):
497
+ credentials = ServiceHubCredentials(postgres=[self.postgres_cred])
498
+ instance_id = credentials.get_service_instance_id()
499
+ self.assertEqual(instance_id, "acd174dd-4098-4967-a492-b336337f8d0a")
500
+
501
+ def test_get_service_instance_id_from_redis(self):
502
+ credentials = ServiceHubCredentials(redis=[self.redis_cred_with_password])
503
+ instance_id = credentials.get_service_instance_id()
504
+ self.assertEqual(instance_id, "6a3adc0c-05ad-44ab-a780-ee943ff7808e")
505
+
506
+ def test_get_service_instance_id_from_blobstore(self):
507
+ credentials = ServiceHubCredentials(blobstore=[self.blobstore_cred_full])
508
+ instance_id = credentials.get_service_instance_id()
509
+ self.assertEqual(instance_id, "12345678-1234-1234-1234-123456789012")
510
+
511
+ def test_get_service_instance_id_precedence(self):
512
+ blobstore_without_id = BlobstoreCredential(
513
+ binding_name="no-id-storage",
514
+ access_key="key",
515
+ secret_key="secret",
516
+ endpoint="https://s3.com",
517
+ external_hosts="s3.com",
518
+ internal_hosts="s3.internal.com",
519
+ signature_version="s3v4",
520
+ type="s3"
521
+ )
522
+
523
+ credentials1 = ServiceHubCredentials(blobstore=[blobstore_without_id])
524
+ with self.assertRaises(CredentialNotFoundError):
525
+ credentials1.get_service_instance_id()
526
+
527
+ credentials2 = ServiceHubCredentials(
528
+ redis=[self.redis_cred_with_password],
529
+ blobstore=[blobstore_without_id]
530
+ )
531
+ instance_id2 = credentials2.get_service_instance_id()
532
+ self.assertEqual(instance_id2, "6a3adc0c-05ad-44ab-a780-ee943ff7808e")
533
+
534
+ credentials3 = ServiceHubCredentials(
535
+ postgres=[self.postgres_cred],
536
+ redis=[self.redis_cred_with_password],
537
+ blobstore=[self.blobstore_cred_full]
538
+ )
539
+ instance_id3 = credentials3.get_service_instance_id()
540
+ self.assertEqual(instance_id3, "acd174dd-4098-4967-a492-b336337f8d0a")
541
+
542
+ def test_get_service_instance_id_no_credentials(self):
543
+ credentials = ServiceHubCredentials()
544
+ with self.assertRaises(CredentialNotFoundError) as context:
545
+ credentials.get_service_instance_id()
546
+ self.assertIn("No service instance ID found", str(context.exception))
547
+
548
+ def test_multiple_service_types_together(self):
549
+ credentials = ServiceHubCredentials(
550
+ postgres=[self.postgres_cred],
551
+ redis=[self.redis_cred_with_password],
552
+ blobstore=[self.blobstore_cred_full]
553
+ )
554
+
555
+ dsn = credentials.to_postgres_dsn()
556
+ self.assertIn("postgresql://", dsn)
557
+
558
+ redis_dsn = credentials.to_redis_dsn()
559
+ self.assertIn("redis://", redis_dsn)
560
+
561
+ blobstore_config = credentials.get_blobstore_s3_config()
562
+ self.assertIn("access_key", blobstore_config)
563
+ self.assertEqual(blobstore_config["access_key"], "AKIAIOSFODNN7EXAMPLE")
564
+
565
+ instance_id = credentials.get_service_instance_id()
566
+ self.assertEqual(instance_id, "acd174dd-4098-4967-a492-b336337f8d0a")
567
+
568
+ def test_parse_blobstore_real_example(self):
569
+ data = {
570
+ "blobstore": [{
571
+ "async": False,
572
+ "binding_name": "ewm-axa-liding",
573
+ "credentials": {
574
+ "accessKey": "bafH4uDnLYHNfZqcY9dTnvl5",
575
+ "endpoint": "minio.ensaas-db.svc.cluster.local:8999",
576
+ "externalHosts": "172.21.92.232:8999",
577
+ "internalHosts": "minio.ensaas-db.svc.cluster.local:8999",
578
+ "secretKey": "yJxEEEO2wUlf3ZmlsDHQp415",
579
+ "signatureVersion": "v2",
580
+ "type": "s3-compatible"
581
+ },
582
+ "instance_name": "Blobstore",
583
+ "label": "Blobstore",
584
+ "plan": "Standard",
585
+ "serviceInstanceId": "75aebf90-d792-4992-8f5c-4ada33f32fd6",
586
+ "subscriptionId": "1289a66b-5833-4ccd-830b-4b03ea1fc77a-axa.wise-paas.com.cn"
587
+ }]
588
+ }
589
+
590
+ credentials = ServiceHubCredentialParser.parse(data)
591
+ self.assertEqual(len(credentials.blobstore), 1)
592
+ blobstore_cred = credentials.blobstore[0]
593
+
594
+ # 验证基本字段
595
+ self.assertEqual(blobstore_cred.binding_name, "ewm-axa-liding")
596
+ self.assertEqual(blobstore_cred.instance_name, "Blobstore")
597
+ self.assertEqual(blobstore_cred.label, "Blobstore")
598
+ self.assertEqual(blobstore_cred.plan, "Standard")
599
+ self.assertEqual(blobstore_cred.service_instance_id, "75aebf90-d792-4992-8f5c-4ada33f32fd6")
600
+ self.assertEqual(blobstore_cred.subscription_id, "1289a66b-5833-4ccd-830b-4b03ea1fc77a-axa.wise-paas.com.cn")
601
+
602
+ # 验证凭证字段
603
+ self.assertEqual(blobstore_cred.access_key, "bafH4uDnLYHNfZqcY9dTnvl5")
604
+ self.assertEqual(blobstore_cred.secret_key, "yJxEEEO2wUlf3ZmlsDHQp415")
605
+ self.assertEqual(blobstore_cred.endpoint, "minio.ensaas-db.svc.cluster.local:8999")
606
+ self.assertEqual(blobstore_cred.external_hosts, "172.21.92.232:8999")
607
+ self.assertEqual(blobstore_cred.internal_hosts, "minio.ensaas-db.svc.cluster.local:8999")
608
+ self.assertEqual(blobstore_cred.signature_version, "v2")
609
+ self.assertEqual(blobstore_cred.type, "s3-compatible")
610
+
611
+ def test_blobstore_credential_creation_real_example(self):
612
+ """Test creating BlobstoreCredential with real example data"""
613
+ blobstore_cred = BlobstoreCredential(
614
+ binding_name="ewm-axa-liding",
615
+ access_key="bafH4uDnLYHNfZqcY9dTnvl5",
616
+ secret_key="yJxEEEO2wUlf3ZmlsDHQp415",
617
+ endpoint="minio.ensaas-db.svc.cluster.local:8999",
618
+ external_hosts="172.21.92.232:8999",
619
+ internal_hosts="minio.ensaas-db.svc.cluster.local:8999",
620
+ signature_version="v2",
621
+ type="s3-compatible",
622
+ instance_name="Blobstore",
623
+ label="Blobstore",
624
+ plan="Standard",
625
+ service_instance_id="75aebf90-d792-4992-8f5c-4ada33f32fd6",
626
+ subscription_id="1289a66b-5833-4ccd-830b-4b03ea1fc77a-axa.wise-paas.com.cn"
627
+ )
628
+
629
+ self.assertEqual(blobstore_cred.binding_name, "ewm-axa-liding")
630
+ self.assertEqual(blobstore_cred.access_key, "bafH4uDnLYHNfZqcY9dTnvl5")
631
+ self.assertEqual(blobstore_cred.secret_key, "yJxEEEO2wUlf3ZmlsDHQp415")
632
+ self.assertEqual(blobstore_cred.endpoint, "minio.ensaas-db.svc.cluster.local:8999")
633
+ self.assertEqual(blobstore_cred.signature_version, "v2")
634
+ self.assertEqual(blobstore_cred.type, "s3-compatible")
635
+ self.assertEqual(blobstore_cred.service_instance_id, "75aebf90-d792-4992-8f5c-4ada33f32fd6")
636
+
637
+ def test_get_blobstore_s3_config_real_example(self):
638
+ blobstore_cred = BlobstoreCredential(
639
+ binding_name="ewm-axa-liding",
640
+ access_key="bafH4uDnLYHNfZqcY9dTnvl5",
641
+ secret_key="yJxEEEO2wUlf3ZmlsDHQp415",
642
+ endpoint="minio.ensaas-db.svc.cluster.local:8999",
643
+ external_hosts="172.21.92.232:8999",
644
+ internal_hosts="minio.ensaas-db.svc.cluster.local:8999",
645
+ signature_version="v2",
646
+ type="s3-compatible",
647
+ instance_name="Blobstore",
648
+ label="Blobstore",
649
+ plan="Standard",
650
+ service_instance_id="75aebf90-d792-4992-8f5c-4ada33f32fd6",
651
+ subscription_id="1289a66b-5833-4ccd-830b-4b03ea1fc77a-axa.wise-paas.com.cn"
652
+ )
653
+
654
+ credentials = ServiceHubCredentials(blobstore=[blobstore_cred])
655
+ config = credentials.get_blobstore_s3_config()
656
+
657
+ expected = {
658
+ "access_key": "bafH4uDnLYHNfZqcY9dTnvl5",
659
+ "secret_key": "yJxEEEO2wUlf3ZmlsDHQp415",
660
+ "endpoint": "minio.ensaas-db.svc.cluster.local:8999",
661
+ "external_hosts": "172.21.92.232:8999",
662
+ "internal_hosts": "minio.ensaas-db.svc.cluster.local:8999",
663
+ "signature_version": "v2",
664
+ "type": "s3-compatible"
665
+ }
666
+
667
+ self.assertEqual(config, expected)
668
+ self.assertEqual(config["signature_version"], "v2")
669
+ self.assertEqual(config["type"], "s3-compatible")
670
+
671
+ def test_parse_blobstore_with_signature_version_field(self):
672
+ """Test parsing blobstore with 'signatureVersion' field (camelCase)"""
673
+ data = {
674
+ "blobstore": [{
675
+ "async": False,
676
+ "binding_name": "test-minio",
677
+ "credentials": {
678
+ "accessKey": "test-access-key",
679
+ "secretKey": "test-secret-key",
680
+ "endpoint": "minio.local:9000",
681
+ "externalHosts": "minio.local:9000",
682
+ "internalHosts": "minio.internal:9000",
683
+ "signatureVersion": "v4", # 注意:这是camelCase
684
+ "type": "s3-compatible"
685
+ },
686
+ "instance_name": "MinIO-Storage",
687
+ "label": "Blobstore"
688
+ }]
689
+ }
690
+
691
+ credentials = ServiceHubCredentialParser.parse(data)
692
+ self.assertEqual(len(credentials.blobstore), 1)
693
+ blobstore_cred = credentials.blobstore[0]
694
+
695
+ self.assertEqual(blobstore_cred.signature_version, "v4")
696
+ self.assertEqual(blobstore_cred.type, "s3-compatible")
697
+
698
+
699
+ if __name__ == '__main__':
700
+ unittest.main()