veadk-python 0.2.27__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 (218) hide show
  1. veadk/__init__.py +37 -0
  2. veadk/a2a/__init__.py +13 -0
  3. veadk/a2a/agent_card.py +45 -0
  4. veadk/a2a/remote_ve_agent.py +390 -0
  5. veadk/a2a/utils/__init__.py +13 -0
  6. veadk/a2a/utils/agent_to_a2a.py +170 -0
  7. veadk/a2a/ve_a2a_server.py +93 -0
  8. veadk/a2a/ve_agent_executor.py +78 -0
  9. veadk/a2a/ve_middlewares.py +313 -0
  10. veadk/a2a/ve_task_store.py +37 -0
  11. veadk/agent.py +402 -0
  12. veadk/agent_builder.py +93 -0
  13. veadk/agents/loop_agent.py +68 -0
  14. veadk/agents/parallel_agent.py +72 -0
  15. veadk/agents/sequential_agent.py +64 -0
  16. veadk/auth/__init__.py +13 -0
  17. veadk/auth/base_auth.py +22 -0
  18. veadk/auth/ve_credential_service.py +203 -0
  19. veadk/auth/veauth/__init__.py +13 -0
  20. veadk/auth/veauth/apmplus_veauth.py +58 -0
  21. veadk/auth/veauth/ark_veauth.py +75 -0
  22. veadk/auth/veauth/base_veauth.py +50 -0
  23. veadk/auth/veauth/cozeloop_veauth.py +13 -0
  24. veadk/auth/veauth/opensearch_veauth.py +75 -0
  25. veadk/auth/veauth/postgresql_veauth.py +75 -0
  26. veadk/auth/veauth/prompt_pilot_veauth.py +60 -0
  27. veadk/auth/veauth/speech_veauth.py +54 -0
  28. veadk/auth/veauth/utils.py +69 -0
  29. veadk/auth/veauth/vesearch_veauth.py +62 -0
  30. veadk/auth/veauth/viking_mem0_veauth.py +91 -0
  31. veadk/cli/__init__.py +13 -0
  32. veadk/cli/cli.py +58 -0
  33. veadk/cli/cli_clean.py +87 -0
  34. veadk/cli/cli_create.py +163 -0
  35. veadk/cli/cli_deploy.py +233 -0
  36. veadk/cli/cli_eval.py +215 -0
  37. veadk/cli/cli_init.py +214 -0
  38. veadk/cli/cli_kb.py +110 -0
  39. veadk/cli/cli_pipeline.py +285 -0
  40. veadk/cli/cli_prompt.py +86 -0
  41. veadk/cli/cli_update.py +106 -0
  42. veadk/cli/cli_uploadevalset.py +139 -0
  43. veadk/cli/cli_web.py +143 -0
  44. veadk/cloud/__init__.py +13 -0
  45. veadk/cloud/cloud_agent_engine.py +485 -0
  46. veadk/cloud/cloud_app.py +475 -0
  47. veadk/config.py +115 -0
  48. veadk/configs/__init__.py +13 -0
  49. veadk/configs/auth_configs.py +133 -0
  50. veadk/configs/database_configs.py +132 -0
  51. veadk/configs/model_configs.py +78 -0
  52. veadk/configs/tool_configs.py +54 -0
  53. veadk/configs/tracing_configs.py +110 -0
  54. veadk/consts.py +74 -0
  55. veadk/evaluation/__init__.py +17 -0
  56. veadk/evaluation/adk_evaluator/__init__.py +17 -0
  57. veadk/evaluation/adk_evaluator/adk_evaluator.py +302 -0
  58. veadk/evaluation/base_evaluator.py +642 -0
  59. veadk/evaluation/deepeval_evaluator/__init__.py +17 -0
  60. veadk/evaluation/deepeval_evaluator/deepeval_evaluator.py +339 -0
  61. veadk/evaluation/eval_set_file_loader.py +48 -0
  62. veadk/evaluation/eval_set_recorder.py +146 -0
  63. veadk/evaluation/types.py +65 -0
  64. veadk/evaluation/utils/prometheus.py +196 -0
  65. veadk/integrations/__init__.py +13 -0
  66. veadk/integrations/ve_apig/__init__.py +13 -0
  67. veadk/integrations/ve_apig/ve_apig.py +349 -0
  68. veadk/integrations/ve_apig/ve_apig_utils.py +332 -0
  69. veadk/integrations/ve_code_pipeline/__init__.py +13 -0
  70. veadk/integrations/ve_code_pipeline/ve_code_pipeline.py +431 -0
  71. veadk/integrations/ve_cozeloop/__init__.py +13 -0
  72. veadk/integrations/ve_cozeloop/ve_cozeloop.py +96 -0
  73. veadk/integrations/ve_cr/__init__.py +13 -0
  74. veadk/integrations/ve_cr/ve_cr.py +220 -0
  75. veadk/integrations/ve_faas/__init__.py +13 -0
  76. veadk/integrations/ve_faas/template/cookiecutter.json +15 -0
  77. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/__init__.py +13 -0
  78. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/clean.py +23 -0
  79. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/config.yaml.example +6 -0
  80. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/deploy.py +106 -0
  81. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/__init__.py +13 -0
  82. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/agent.py +25 -0
  83. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/app.py +202 -0
  84. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/requirements.txt +3 -0
  85. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/run.sh +49 -0
  86. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name }}/__init__.py +14 -0
  87. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name }}/agent.py +27 -0
  88. veadk/integrations/ve_faas/ve_faas.py +754 -0
  89. veadk/integrations/ve_faas/ve_faas_utils.py +408 -0
  90. veadk/integrations/ve_faas/web_template/cookiecutter.json +20 -0
  91. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/__init__.py +13 -0
  92. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/clean.py +23 -0
  93. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/config.yaml.example +2 -0
  94. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/deploy.py +44 -0
  95. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/Dockerfile +23 -0
  96. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/app.py +123 -0
  97. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/init_db.py +46 -0
  98. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/models.py +36 -0
  99. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/requirements.txt +4 -0
  100. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/run.sh +21 -0
  101. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/css/style.css +368 -0
  102. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/js/admin.js +0 -0
  103. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/dashboard.html +21 -0
  104. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/edit_post.html +24 -0
  105. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/login.html +21 -0
  106. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/posts.html +53 -0
  107. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/base.html +45 -0
  108. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/index.html +29 -0
  109. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/post.html +14 -0
  110. veadk/integrations/ve_identity/__init__.py +110 -0
  111. veadk/integrations/ve_identity/auth_config.py +261 -0
  112. veadk/integrations/ve_identity/auth_mixins.py +650 -0
  113. veadk/integrations/ve_identity/auth_processor.py +385 -0
  114. veadk/integrations/ve_identity/function_tool.py +158 -0
  115. veadk/integrations/ve_identity/identity_client.py +864 -0
  116. veadk/integrations/ve_identity/mcp_tool.py +181 -0
  117. veadk/integrations/ve_identity/mcp_toolset.py +431 -0
  118. veadk/integrations/ve_identity/models.py +228 -0
  119. veadk/integrations/ve_identity/token_manager.py +188 -0
  120. veadk/integrations/ve_identity/utils.py +151 -0
  121. veadk/integrations/ve_prompt_pilot/__init__.py +13 -0
  122. veadk/integrations/ve_prompt_pilot/ve_prompt_pilot.py +85 -0
  123. veadk/integrations/ve_tls/__init__.py +13 -0
  124. veadk/integrations/ve_tls/utils.py +116 -0
  125. veadk/integrations/ve_tls/ve_tls.py +212 -0
  126. veadk/integrations/ve_tos/ve_tos.py +710 -0
  127. veadk/integrations/ve_viking_db_memory/__init__.py +13 -0
  128. veadk/integrations/ve_viking_db_memory/ve_viking_db_memory.py +308 -0
  129. veadk/knowledgebase/__init__.py +17 -0
  130. veadk/knowledgebase/backends/__init__.py +13 -0
  131. veadk/knowledgebase/backends/base_backend.py +72 -0
  132. veadk/knowledgebase/backends/in_memory_backend.py +91 -0
  133. veadk/knowledgebase/backends/opensearch_backend.py +162 -0
  134. veadk/knowledgebase/backends/redis_backend.py +172 -0
  135. veadk/knowledgebase/backends/utils.py +92 -0
  136. veadk/knowledgebase/backends/vikingdb_knowledge_backend.py +608 -0
  137. veadk/knowledgebase/entry.py +25 -0
  138. veadk/knowledgebase/knowledgebase.py +307 -0
  139. veadk/memory/__init__.py +35 -0
  140. veadk/memory/long_term_memory.py +365 -0
  141. veadk/memory/long_term_memory_backends/__init__.py +13 -0
  142. veadk/memory/long_term_memory_backends/base_backend.py +35 -0
  143. veadk/memory/long_term_memory_backends/in_memory_backend.py +67 -0
  144. veadk/memory/long_term_memory_backends/mem0_backend.py +155 -0
  145. veadk/memory/long_term_memory_backends/opensearch_backend.py +124 -0
  146. veadk/memory/long_term_memory_backends/redis_backend.py +140 -0
  147. veadk/memory/long_term_memory_backends/vikingdb_memory_backend.py +189 -0
  148. veadk/memory/short_term_memory.py +252 -0
  149. veadk/memory/short_term_memory_backends/__init__.py +13 -0
  150. veadk/memory/short_term_memory_backends/base_backend.py +31 -0
  151. veadk/memory/short_term_memory_backends/mysql_backend.py +49 -0
  152. veadk/memory/short_term_memory_backends/postgresql_backend.py +49 -0
  153. veadk/memory/short_term_memory_backends/sqlite_backend.py +55 -0
  154. veadk/memory/short_term_memory_processor.py +100 -0
  155. veadk/processors/__init__.py +26 -0
  156. veadk/processors/base_run_processor.py +120 -0
  157. veadk/prompts/__init__.py +13 -0
  158. veadk/prompts/agent_default_prompt.py +30 -0
  159. veadk/prompts/prompt_evaluator.py +20 -0
  160. veadk/prompts/prompt_memory_processor.py +55 -0
  161. veadk/prompts/prompt_optimization.py +150 -0
  162. veadk/runner.py +732 -0
  163. veadk/tools/__init__.py +13 -0
  164. veadk/tools/builtin_tools/__init__.py +13 -0
  165. veadk/tools/builtin_tools/agent_authorization.py +94 -0
  166. veadk/tools/builtin_tools/generate_image.py +23 -0
  167. veadk/tools/builtin_tools/image_edit.py +300 -0
  168. veadk/tools/builtin_tools/image_generate.py +446 -0
  169. veadk/tools/builtin_tools/lark.py +67 -0
  170. veadk/tools/builtin_tools/las.py +24 -0
  171. veadk/tools/builtin_tools/link_reader.py +66 -0
  172. veadk/tools/builtin_tools/llm_shield.py +381 -0
  173. veadk/tools/builtin_tools/load_knowledgebase.py +97 -0
  174. veadk/tools/builtin_tools/mcp_router.py +29 -0
  175. veadk/tools/builtin_tools/run_code.py +113 -0
  176. veadk/tools/builtin_tools/tts.py +253 -0
  177. veadk/tools/builtin_tools/vesearch.py +49 -0
  178. veadk/tools/builtin_tools/video_generate.py +363 -0
  179. veadk/tools/builtin_tools/web_scraper.py +76 -0
  180. veadk/tools/builtin_tools/web_search.py +83 -0
  181. veadk/tools/demo_tools.py +58 -0
  182. veadk/tools/load_knowledgebase_tool.py +149 -0
  183. veadk/tools/sandbox/__init__.py +13 -0
  184. veadk/tools/sandbox/browser_sandbox.py +37 -0
  185. veadk/tools/sandbox/code_sandbox.py +40 -0
  186. veadk/tools/sandbox/computer_sandbox.py +34 -0
  187. veadk/tracing/__init__.py +13 -0
  188. veadk/tracing/base_tracer.py +58 -0
  189. veadk/tracing/telemetry/__init__.py +13 -0
  190. veadk/tracing/telemetry/attributes/attributes.py +29 -0
  191. veadk/tracing/telemetry/attributes/extractors/common_attributes_extractors.py +180 -0
  192. veadk/tracing/telemetry/attributes/extractors/llm_attributes_extractors.py +858 -0
  193. veadk/tracing/telemetry/attributes/extractors/tool_attributes_extractors.py +152 -0
  194. veadk/tracing/telemetry/attributes/extractors/types.py +164 -0
  195. veadk/tracing/telemetry/exporters/__init__.py +13 -0
  196. veadk/tracing/telemetry/exporters/apmplus_exporter.py +558 -0
  197. veadk/tracing/telemetry/exporters/base_exporter.py +39 -0
  198. veadk/tracing/telemetry/exporters/cozeloop_exporter.py +129 -0
  199. veadk/tracing/telemetry/exporters/inmemory_exporter.py +248 -0
  200. veadk/tracing/telemetry/exporters/tls_exporter.py +139 -0
  201. veadk/tracing/telemetry/opentelemetry_tracer.py +320 -0
  202. veadk/tracing/telemetry/telemetry.py +411 -0
  203. veadk/types.py +47 -0
  204. veadk/utils/__init__.py +13 -0
  205. veadk/utils/audio_manager.py +95 -0
  206. veadk/utils/auth.py +294 -0
  207. veadk/utils/logger.py +59 -0
  208. veadk/utils/mcp_utils.py +44 -0
  209. veadk/utils/misc.py +184 -0
  210. veadk/utils/patches.py +101 -0
  211. veadk/utils/volcengine_sign.py +205 -0
  212. veadk/version.py +15 -0
  213. veadk_python-0.2.27.dist-info/METADATA +373 -0
  214. veadk_python-0.2.27.dist-info/RECORD +218 -0
  215. veadk_python-0.2.27.dist-info/WHEEL +5 -0
  216. veadk_python-0.2.27.dist-info/entry_points.txt +2 -0
  217. veadk_python-0.2.27.dist-info/licenses/LICENSE +201 -0
  218. veadk_python-0.2.27.dist-info/top_level.txt +1 -0
@@ -0,0 +1,196 @@
1
+ # Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ from prometheus_client import CollectorRegistry, Gauge, push_to_gateway
17
+ from prometheus_client.exposition import basic_auth_handler
18
+ from pydantic import Field
19
+
20
+ from veadk.config import getenv
21
+ from veadk.evaluation.types import EvalResultCaseData, EvalResultMetadata
22
+
23
+
24
+ class PrometheusPushgatewayConfig:
25
+ """Configures connection to Prometheus Pushgateway for metrics export.
26
+
27
+ This class holds settings for pushing evaluation metrics to Prometheus.
28
+ It uses environment variables for default values.
29
+
30
+ Attributes:
31
+ url (str): URL of the Prometheus Pushgateway endpoint.
32
+ Defaults to OBSERVABILITY_PROMETHEUS_PUSHGATEWAY_URL environment variable.
33
+ username (str): Username for authentication.
34
+ Defaults to OBSERVABILITY_PROMETHEUS_USERNAME environment variable.
35
+ password (str): Password for authentication.
36
+ Defaults to OBSERVABILITY_PROMETHEUS_PASSWORD environment variable.
37
+
38
+ Note:
39
+ All fields are optional and use environment variables if not provided.
40
+ """
41
+
42
+ url: str = Field(
43
+ default_factory=lambda: getenv(
44
+ "OBSERVABILITY_PROMETHEUS_PUSHGATEWAY_URL",
45
+ ),
46
+ )
47
+ username: str = Field(
48
+ default_factory=lambda: getenv(
49
+ "OBSERVABILITY_PROMETHEUS_USERNAME",
50
+ ),
51
+ )
52
+ password: str = Field(
53
+ default_factory=lambda: getenv(
54
+ "OBSERVABILITY_PROMETHEUS_PASSWORD",
55
+ ),
56
+ )
57
+
58
+
59
+ registry = CollectorRegistry()
60
+
61
+ test_cases_total_metric = Gauge(
62
+ "test_cases_total",
63
+ "Total number of test cases in this evaluation",
64
+ registry=registry,
65
+ )
66
+
67
+ test_cases_success_metric = Gauge(
68
+ "test_cases_success", "Success number of test cases", registry=registry
69
+ )
70
+
71
+ test_cases_pass_metric = Gauge(
72
+ "test_cases_pass", "Passed number of test cases", registry=registry
73
+ )
74
+
75
+ test_cases_failure_metric = Gauge(
76
+ "test_cases_failure", "Failuer number of test cases", registry=registry
77
+ )
78
+
79
+ case_threshold_metric = Gauge("threshold", "Threshold of test cases", registry=registry)
80
+ diff_threshold_metric = Gauge(
81
+ "diff_threshold", "Diff threshold of test cases", registry=registry
82
+ )
83
+
84
+ test_cases_data_metric = Gauge(
85
+ "test_cases_data",
86
+ "Specific data of test cases",
87
+ registry=registry,
88
+ labelnames=["data"],
89
+ )
90
+
91
+ eval_data_metric = Gauge(
92
+ "eval_data",
93
+ "Specific data of evaluation",
94
+ registry=registry,
95
+ labelnames=["data"],
96
+ )
97
+
98
+
99
+ def post_pushgateway(
100
+ pushgateway_url: str,
101
+ username: str,
102
+ password: str,
103
+ job_name: str,
104
+ registry: CollectorRegistry,
105
+ grouping_key: dict[str, str] | None = None,
106
+ ):
107
+ """Pushes metrics to Prometheus Pushgateway with authentication.
108
+
109
+ This function sends collected metrics to the specified Pushgateway URL.
110
+ It uses basic authentication and optional grouping keys.
111
+
112
+ Args:
113
+ pushgateway_url (str): URL of the Pushgateway endpoint.
114
+ username (str): Authentication username.
115
+ password (str): Authentication password.
116
+ job_name (str): Name of the job for metrics labeling.
117
+ registry (CollectorRegistry): Registry containing metrics to push.
118
+ grouping_key (dict[str, str] | None): Optional key-value pairs for grouping.
119
+
120
+ Raises:
121
+ Exception: If push operation fails due to network or auth issues.
122
+
123
+ Note:
124
+ Authentication handler is created internally using provided credentials.
125
+ """
126
+
127
+ def auth_handler(url, method, timeout, headers, data):
128
+ return basic_auth_handler(
129
+ url, method, timeout, headers, data, username, password
130
+ )
131
+
132
+ push_to_gateway(
133
+ gateway=pushgateway_url,
134
+ job=job_name,
135
+ registry=registry,
136
+ grouping_key=grouping_key,
137
+ handler=auth_handler,
138
+ )
139
+
140
+
141
+ def push_to_prometheus(
142
+ test_name: str,
143
+ test_cases_total: int,
144
+ test_cases_failure: int,
145
+ test_cases_pass: int,
146
+ test_data_list: list[EvalResultCaseData],
147
+ eval_data: EvalResultMetadata,
148
+ case_threshold: float = 0.5,
149
+ diff_threshold: float = 0.2,
150
+ url: str = "",
151
+ username: str = "",
152
+ password: str = "",
153
+ ):
154
+ """Sets and pushes evaluation metrics to Prometheus.
155
+
156
+ This function updates gauge metrics with evaluation results and pushes them.
157
+ It handles counts, thresholds, and specific data labels.
158
+
159
+ Args:
160
+ test_name (str): Name of the test for grouping.
161
+ test_cases_total (int): Total number of test cases.
162
+ test_cases_failure (int): Number of failed test cases.
163
+ test_cases_pass (int): Number of passed test cases.
164
+ test_data_list (list[EvalResultCaseData]): List of case data for labeling.
165
+ eval_data (EvalResultMetadata): Metadata for evaluation.
166
+ case_threshold (float): Threshold value for cases. Defaults to 0.5.
167
+ diff_threshold (float): Diff threshold value. Defaults to 0.2.
168
+ url (str): Pushgateway URL. Defaults to empty.
169
+ username (str): Auth username. Defaults to empty.
170
+ password (str): Auth password. Defaults to empty.
171
+
172
+ Returns:
173
+ None: Metrics are set and pushed directly.
174
+
175
+ Raises:
176
+ ValueError: If required data is invalid.
177
+ """
178
+ test_cases_total_metric.set(test_cases_total)
179
+ test_cases_failure_metric.set(test_cases_failure)
180
+ test_cases_pass_metric.set(test_cases_pass)
181
+
182
+ for test_data in test_data_list:
183
+ test_cases_data_metric.labels(data=str(test_data.__dict__)).set(1)
184
+
185
+ eval_data_metric.labels(data=str(eval_data.__dict__)).set(1)
186
+ case_threshold_metric.set(case_threshold)
187
+ diff_threshold_metric.set(diff_threshold)
188
+
189
+ post_pushgateway(
190
+ pushgateway_url=url,
191
+ username=username,
192
+ password=password,
193
+ job_name="veadk_eval_job",
194
+ registry=registry,
195
+ grouping_key={"test_name": test_name},
196
+ )
@@ -0,0 +1,13 @@
1
+ # Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
@@ -0,0 +1,13 @@
1
+ # Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
@@ -0,0 +1,349 @@
1
+ # Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import time
16
+
17
+ import volcenginesdkcore
18
+ from volcenginesdkapig import APIGApi
19
+ from volcenginesdkapig20221112 import APIG20221112Api, UpstreamListForCreateRouteInput
20
+
21
+ from veadk.utils.volcengine_sign import ve_request
22
+
23
+
24
+ class APIGateway:
25
+ def __init__(self, access_key: str, secret_key: str, region: str = "cn-beijing"):
26
+ self.ak = access_key
27
+ self.sk = secret_key
28
+ self.region = region
29
+ configuration = volcenginesdkcore.Configuration()
30
+ configuration.ak = self.ak
31
+ configuration.sk = self.sk
32
+ configuration.region = region
33
+
34
+ self.api_client = volcenginesdkcore.ApiClient(configuration=configuration)
35
+ self.apig_20221112_client = APIG20221112Api(api_client=self.api_client)
36
+ self.apig_client = APIGApi(api_client=self.api_client)
37
+
38
+ def list_gateways(self):
39
+ from volcenginesdkapig import ListGatewaysRequest
40
+
41
+ request = ListGatewaysRequest()
42
+ thread = self.apig_client.list_gateways(request, async_req=True)
43
+ result = thread.get()
44
+ return result
45
+
46
+ def create_serverless_gateway(self, instance_name: str) -> str: # instance
47
+ from volcenginesdkapig import (
48
+ CreateGatewayRequest,
49
+ ResourceSpecForCreateGatewayInput,
50
+ ListGatewaysRequest,
51
+ )
52
+
53
+ request = CreateGatewayRequest(
54
+ name=instance_name,
55
+ region=self.region,
56
+ type="serverless",
57
+ resource_spec=ResourceSpecForCreateGatewayInput(
58
+ replicas=2,
59
+ instance_spec_code="1c2g",
60
+ clb_spec_code="small_1",
61
+ public_network_billing_type="traffic",
62
+ network_type={
63
+ "EnablePublicNetwork": True,
64
+ "EnablePrivateNetwork": False,
65
+ },
66
+ ),
67
+ )
68
+ thread = self.apig_client.create_gateway(request, async_req=True)
69
+ result = thread.get()
70
+ gateway_id = result.to_dict()["id"]
71
+
72
+ found = False
73
+ while not found:
74
+ request = ListGatewaysRequest()
75
+ thread = self.apig_client.list_gateways(request, async_req=True)
76
+ result = thread.get()
77
+ for item in result.items:
78
+ if (
79
+ item.to_dict()["id"] == gateway_id
80
+ and item.to_dict()["status"] == "Running"
81
+ ):
82
+ found = True
83
+ break
84
+ if not found:
85
+ time.sleep(5)
86
+ return gateway_id
87
+
88
+ def create_gateway_service(self, gateway_id: str, service_name: str) -> str:
89
+ """
90
+ Create a gateway service. (Domain name)
91
+ Args:
92
+ gateway_id (str): The ID of the gateway to which the service belongs.
93
+ service_name (str): The name of the service to be created.
94
+ Returns:
95
+ str: The ID of the created service.
96
+ """
97
+ from volcenginesdkapig import (
98
+ AuthSpecForCreateGatewayServiceInput,
99
+ CreateGatewayServiceRequest,
100
+ )
101
+
102
+ request = CreateGatewayServiceRequest(
103
+ gateway_id=gateway_id,
104
+ service_name=service_name,
105
+ protocol=["HTTP", "HTTPS"],
106
+ auth_spec=AuthSpecForCreateGatewayServiceInput(enable=False),
107
+ )
108
+ thread = self.apig_client.create_gateway_service(request, async_req=True)
109
+ result = thread.get()
110
+ return result.to_dict()["id"]
111
+
112
+ def create_vefaas_upstream(
113
+ self, function_id: str, gateway_id: str, upstream_name: str
114
+ ):
115
+ from volcenginesdkapig import (
116
+ CreateUpstreamRequest,
117
+ UpstreamSpecForCreateUpstreamInput,
118
+ VeFaasForCreateUpstreamInput,
119
+ )
120
+
121
+ request = CreateUpstreamRequest(
122
+ gateway_id=gateway_id,
123
+ name=upstream_name,
124
+ source_type="VeFaas",
125
+ upstream_spec=UpstreamSpecForCreateUpstreamInput(
126
+ ve_faas=VeFaasForCreateUpstreamInput(function_id=function_id)
127
+ ),
128
+ )
129
+ thread = self.apig_client.create_upstream(request, async_req=True)
130
+ result = thread.get()
131
+ return result.to_dict()["id"]
132
+
133
+ def create_domain_upstream(
134
+ self,
135
+ domain: str,
136
+ port: int,
137
+ is_https: bool,
138
+ gateway_id: str,
139
+ upstream_name: str,
140
+ ) -> str:
141
+ """
142
+ Create a domain upstream.
143
+ Args:
144
+ domain (str): The domain of the upstream.
145
+ port (int): The port of the upstream.
146
+ is_https (bool): Whether the upstream works on HTTPS.
147
+ gateway_id (str): The ID of the gateway to which the upstream belongs.
148
+ upstream_name (str): The name of the upstream.
149
+ Returns:
150
+ str: The ID of the created upstream.
151
+ """
152
+
153
+ request_body = {
154
+ "Name": upstream_name,
155
+ "GatewayId": gateway_id,
156
+ "SourceType": "Domain",
157
+ "UpstreamSpec": {
158
+ "Domain": {"DomainList": [{"Domain": domain, "Port": port}]}
159
+ },
160
+ }
161
+ if is_https:
162
+ request_body["TlsSettings"] = {"TlsMode": "SIMPLE", "Sni": domain}
163
+ else:
164
+ request_body["TlsSettings"] = {"TlsMode": "DISABLE"}
165
+
166
+ response = ve_request(
167
+ request_body=request_body,
168
+ action="CreateUpstream",
169
+ ak=self.ak,
170
+ sk=self.sk,
171
+ service="apig",
172
+ version="2021-03-03",
173
+ region=self.region,
174
+ host="open.volcengineapi.com",
175
+ )
176
+
177
+ try:
178
+ return response["Result"]["Id"]
179
+ except Exception as _:
180
+ raise ValueError(f"Create domain upstream failed: {response}")
181
+
182
+ def check_domain_upstream_exist(
183
+ self, domain: str, port: int, gateway_id: str
184
+ ) -> str | None:
185
+ """
186
+ Check whether the domain upstream exists.
187
+ Args:
188
+ domain (str): The domain of the upstream.
189
+ port (int): The port of the upstream.
190
+ gateway_id (str): The ID of the gateway to which the upstream belongs.
191
+ Returns:
192
+ str | None: The ID of the existed upstream or None if no upstream exists.
193
+ """
194
+
195
+ request_body = {
196
+ "GatewayId": gateway_id,
197
+ "UpstreamSpec": {
198
+ "Domain": {"DomainList": [{"Domain": domain, "Port": port}]}
199
+ },
200
+ }
201
+
202
+ response = ve_request(
203
+ request_body=request_body,
204
+ action="CheckUpstreamSpecExist",
205
+ ak=self.ak,
206
+ sk=self.sk,
207
+ service="apig",
208
+ version="2021-03-03",
209
+ region=self.region,
210
+ host="open.volcengineapi.com",
211
+ )
212
+
213
+ try:
214
+ exist = response["Result"]["Exist"]
215
+ if exist:
216
+ return response["Result"]["Id"]
217
+ else:
218
+ return None
219
+ except Exception as _:
220
+ raise ValueError(f"Check domain upstream spec exist failed: {response}")
221
+
222
+ def create_gateway_service_routes(
223
+ self, service_id: str, upstream_id: str, route_name: str, match_rule: dict
224
+ ):
225
+ """
226
+ Create gateway service routes.
227
+
228
+ Args:
229
+ service_id (str): The ID of the gateway service, used to specify the target service for which the route is to be created.
230
+ upstream_id (str): The ID of the upstream service, to which the route will point.
231
+ route_name (str): The name of the route to be created.
232
+ match_rule (dict): The route matching rule, containing the following key - value pairs:
233
+ - match_content (str): The path matching content, a string like "/abc", used to specify the path to be matched.
234
+ - match_type (str): The path matching type, with optional values "Exact", "Regex", "Prefix".
235
+ - match_method (list[str]): The list of HTTP request methods, possible values include "GET", "POST", etc.
236
+ Returns:
237
+ str: The ID of the created route.
238
+ """
239
+ from volcenginesdkapig20221112 import (
240
+ CreateRouteRequest,
241
+ MatchRuleForCreateRouteInput,
242
+ PathForCreateRouteInput,
243
+ )
244
+
245
+ match_content: str = match_rule["match_content"]
246
+ match_type: str = match_rule["match_type"]
247
+ match_method: list[str] = match_rule["match_method"]
248
+
249
+ request = CreateRouteRequest(
250
+ service_id=service_id,
251
+ enable=True,
252
+ match_rule=MatchRuleForCreateRouteInput(
253
+ path=PathForCreateRouteInput(
254
+ match_content=match_content, match_type=match_type
255
+ ),
256
+ method=match_method,
257
+ ),
258
+ name=route_name,
259
+ priority=1,
260
+ upstream_list=[
261
+ UpstreamListForCreateRouteInput(
262
+ upstream_id=upstream_id,
263
+ weight=1,
264
+ )
265
+ ],
266
+ )
267
+
268
+ thread = self.apig_20221112_client.create_route(request, async_req=True)
269
+ result = thread.get()
270
+ return result.to_dict()["id"]
271
+
272
+ def create_plugin_binding(
273
+ self, scope: str, target: str, plugin_name: str, plugin_config: str
274
+ ) -> str:
275
+ """
276
+ Create a plugin binding.
277
+ Args:
278
+ scope (str): The type of the target.
279
+ Choices are 'GATEWAY', 'SERVICE' or 'ROUTE'.
280
+ target (str): The ID of the gateway, service or route.
281
+ plugin_name (str): The name of the plugin.
282
+ plugin_config (str): The config of the plugin.
283
+ Returns:
284
+ str: The ID of the created service.
285
+ """
286
+
287
+ from volcenginesdkapig import CreatePluginBindingRequest
288
+
289
+ request = CreatePluginBindingRequest(
290
+ scope=scope,
291
+ target=target,
292
+ plugin_name=plugin_name,
293
+ plugin_config=plugin_config,
294
+ enable=True,
295
+ )
296
+ thread = self.apig_client.create_plugin_binding(request, async_req=True)
297
+ result = thread.get()
298
+ return result.to_dict()["id"]
299
+
300
+ def create(
301
+ self,
302
+ function_id: str,
303
+ apig_instance_name: str,
304
+ service_name: str,
305
+ upstream_name: str,
306
+ routes: list[dict],
307
+ ):
308
+ """
309
+ Create an API gateway instance, service, and multiple routes.
310
+
311
+ Args:
312
+ function_id (str): The ID of the function to be associated with the routes.
313
+ apig_instance_name (str): The name of the API gateway instance.
314
+ service_name (str): The name of the service to be created.
315
+ upstream_name (str): The name of the upstream service to be created.
316
+ routes (list[dict]): A list of route configurations. Each dictionary in the list contains the following key - value pairs:
317
+ - route_name (str): The name of the route to be created.
318
+ - match_content (str): The path matching content, a string like "/abc", used to specify the path to be matched.
319
+ - match_type (str): The path matching type, with optional values "Exact", "Regex", "Prefix".
320
+ - match_method (list[str]): The list of HTTP request methods, possible values include "GET", "POST", etc.
321
+
322
+ Returns:
323
+ dict: A dictionary containing the IDs of the created gateway, service, upstream, and routes.
324
+ """
325
+ gateway_id = self.create_serverless_gateway(apig_instance_name)
326
+ service_id = self.create_gateway_service(gateway_id, service_name)
327
+ upstream_id = self.create_vefaas_upstream(
328
+ function_id, gateway_id, upstream_name
329
+ )
330
+
331
+ route_ids = []
332
+ for route in routes:
333
+ route_name = route["route_name"]
334
+ match_rule = {
335
+ "match_content": route["match_content"],
336
+ "match_type": route["match_type"],
337
+ "match_method": route["match_method"],
338
+ }
339
+ route_id = self.create_gateway_service_routes(
340
+ service_id, upstream_id, route_name, match_rule
341
+ )
342
+ route_ids.append(route_id)
343
+
344
+ return {
345
+ "gateway_id": gateway_id,
346
+ "service_id": service_id,
347
+ "upstream_id": upstream_id,
348
+ "route_ids": route_ids,
349
+ }