veadk-python 0.2.5__py3-none-any.whl → 0.2.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.

Potentially problematic release.


This version of veadk-python might be problematic. Click here for more details.

Files changed (94) hide show
  1. veadk/agent.py +29 -22
  2. veadk/agent_builder.py +94 -0
  3. veadk/auth/__init__.py +13 -0
  4. veadk/auth/base_auth.py +22 -0
  5. veadk/auth/veauth/__init__.py +13 -0
  6. veadk/auth/veauth/apmplus_veauth.py +65 -0
  7. veadk/auth/veauth/ark_veauth.py +77 -0
  8. veadk/auth/veauth/base_veauth.py +50 -0
  9. veadk/auth/veauth/cozeloop_veauth.py +13 -0
  10. veadk/auth/veauth/prompt_pilot_veauth.py +60 -0
  11. veadk/auth/veauth/vesearch_veauth.py +62 -0
  12. veadk/cli/cli.py +2 -0
  13. veadk/cli/cli_deploy.py +5 -2
  14. veadk/cli/cli_init.py +25 -6
  15. veadk/cli/cli_pipeline.py +220 -0
  16. veadk/cli/cli_prompt.py +4 -4
  17. veadk/config.py +45 -81
  18. veadk/configs/__init__.py +13 -0
  19. veadk/configs/database_configs.py +83 -0
  20. veadk/configs/model_configs.py +42 -0
  21. veadk/configs/tool_configs.py +42 -0
  22. veadk/configs/tracing_configs.py +110 -0
  23. veadk/consts.py +32 -1
  24. veadk/database/database_adapter.py +256 -3
  25. veadk/database/kv/redis_database.py +47 -0
  26. veadk/database/local_database.py +23 -4
  27. veadk/database/relational/mysql_database.py +58 -0
  28. veadk/database/vector/opensearch_vector_database.py +6 -3
  29. veadk/database/viking/viking_database.py +272 -36
  30. veadk/integrations/ve_code_pipeline/__init__.py +13 -0
  31. veadk/integrations/ve_code_pipeline/ve_code_pipeline.py +431 -0
  32. veadk/integrations/ve_cozeloop/__init__.py +13 -0
  33. veadk/integrations/ve_cozeloop/ve_cozeloop.py +96 -0
  34. veadk/integrations/ve_cr/__init__.py +13 -0
  35. veadk/integrations/ve_cr/ve_cr.py +220 -0
  36. veadk/integrations/ve_faas/template/cookiecutter.json +3 -2
  37. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/deploy.py +2 -2
  38. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/agent.py +1 -1
  39. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/app.py +24 -1
  40. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/requirements.txt +3 -1
  41. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/run.sh +1 -12
  42. veadk/integrations/ve_faas/ve_faas.py +352 -35
  43. veadk/integrations/ve_faas/web_template/cookiecutter.json +17 -0
  44. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/__init__.py +13 -0
  45. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/clean.py +23 -0
  46. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/config.yaml.example +2 -0
  47. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/deploy.py +41 -0
  48. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/Dockerfile +23 -0
  49. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/app.py +123 -0
  50. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/init_db.py +46 -0
  51. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/models.py +36 -0
  52. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/requirements.txt +4 -0
  53. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/run.sh +21 -0
  54. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/css/style.css +368 -0
  55. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/js/admin.js +0 -0
  56. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/dashboard.html +21 -0
  57. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/edit_post.html +24 -0
  58. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/login.html +21 -0
  59. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/posts.html +53 -0
  60. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/base.html +45 -0
  61. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/index.html +29 -0
  62. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/post.html +14 -0
  63. veadk/integrations/ve_prompt_pilot/ve_prompt_pilot.py +6 -3
  64. veadk/integrations/ve_tls/__init__.py +13 -0
  65. veadk/integrations/ve_tls/utils.py +117 -0
  66. veadk/integrations/ve_tls/ve_tls.py +208 -0
  67. veadk/integrations/ve_tos/ve_tos.py +128 -73
  68. veadk/knowledgebase/knowledgebase.py +116 -20
  69. veadk/memory/long_term_memory.py +20 -21
  70. veadk/memory/short_term_memory_processor.py +9 -4
  71. veadk/runner.py +213 -223
  72. veadk/tools/builtin_tools/vesearch.py +2 -2
  73. veadk/tools/builtin_tools/video_generate.py +27 -20
  74. veadk/tracing/telemetry/attributes/extractors/common_attributes_extractors.py +5 -0
  75. veadk/tracing/telemetry/attributes/extractors/llm_attributes_extractors.py +253 -129
  76. veadk/tracing/telemetry/attributes/extractors/types.py +15 -4
  77. veadk/tracing/telemetry/exporters/apmplus_exporter.py +158 -12
  78. veadk/tracing/telemetry/exporters/cozeloop_exporter.py +4 -9
  79. veadk/tracing/telemetry/exporters/tls_exporter.py +4 -10
  80. veadk/tracing/telemetry/opentelemetry_tracer.py +11 -5
  81. veadk/tracing/telemetry/telemetry.py +23 -5
  82. veadk/utils/logger.py +1 -1
  83. veadk/utils/misc.py +48 -0
  84. veadk/utils/volcengine_sign.py +6 -2
  85. veadk/version.py +1 -1
  86. {veadk_python-0.2.5.dist-info → veadk_python-0.2.7.dist-info}/METADATA +2 -1
  87. veadk_python-0.2.7.dist-info/RECORD +172 -0
  88. veadk_python-0.2.5.dist-info/RECORD +0 -127
  89. /veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{{ cookiecutter.app_name|replace('-', '_') }} → {{ cookiecutter.app_name }}}/__init__.py +0 -0
  90. /veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{{ cookiecutter.app_name|replace('-', '_') }} → {{ cookiecutter.app_name }}}/agent.py +0 -0
  91. {veadk_python-0.2.5.dist-info → veadk_python-0.2.7.dist-info}/WHEEL +0 -0
  92. {veadk_python-0.2.5.dist-info → veadk_python-0.2.7.dist-info}/entry_points.txt +0 -0
  93. {veadk_python-0.2.5.dist-info → veadk_python-0.2.7.dist-info}/licenses/LICENSE +0 -0
  94. {veadk_python-0.2.5.dist-info → veadk_python-0.2.7.dist-info}/top_level.txt +0 -0
@@ -13,10 +13,10 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import json
16
+ import os
16
17
  import time
17
18
 
18
19
  import requests
19
- import typer
20
20
  import volcenginesdkcore
21
21
  import volcenginesdkvefaas
22
22
  from volcenginesdkvefaas.models.env_for_create_function_input import (
@@ -118,6 +118,7 @@ class VeFaaS:
118
118
  runtime="native-python3.10/v1",
119
119
  request_timeout=1800,
120
120
  envs=envs,
121
+ memory_mb=2048,
121
122
  )
122
123
  )
123
124
 
@@ -141,6 +142,8 @@ class VeFaaS:
141
142
  upstream_name: str,
142
143
  service_name: str,
143
144
  ):
145
+ enable_key_auth = os.getenv("VEFAAS_ENABLE_KEY_AUTH", "true").lower() == "true"
146
+
144
147
  response = ve_request(
145
148
  request_body={
146
149
  "Name": application_name,
@@ -152,6 +155,8 @@ class VeFaaS:
152
155
  "GatewayName": gateway_name,
153
156
  "ServiceName": service_name,
154
157
  "UpstreamName": upstream_name,
158
+ "EnableKeyAuth": enable_key_auth,
159
+ "EnableMcpSession": True,
155
160
  },
156
161
  "TemplateId": self.template_id,
157
162
  },
@@ -189,16 +194,27 @@ class VeFaaS:
189
194
  time.sleep(10)
190
195
  status, full_response = self._get_application_status(app_id)
191
196
 
192
- assert status == "deploy_success", (
193
- f"Release application failed. Response: {full_response}"
194
- )
195
-
196
- cloud_resource = full_response["Result"]["CloudResource"]
197
- cloud_resource = json.loads(cloud_resource)
198
-
199
- url = cloud_resource["framework"]["url"]["system_url"]
200
-
201
- return url
197
+ if status == "deploy_success":
198
+ cloud_resource = full_response["Result"]["CloudResource"]
199
+ cloud_resource = json.loads(cloud_resource)
200
+ url = cloud_resource["framework"]["url"]["system_url"]
201
+ return url
202
+ else:
203
+ logger.error(
204
+ f"Release application failed. Application ID: {app_id}, Status: {status}"
205
+ )
206
+ import re
207
+
208
+ logs = "\n".join(self._get_application_logs(app_id=app_id))
209
+ log_text = re.sub(
210
+ r'([{"\']?(key|secret|token|pass|auth|credential|access|api|ak|sk|doubao|volces|coze)[^"\'\s]*["\']?\s*[:=]\s*)(["\']?)([^"\'\s]+)(["\']?)|([A-Za-z0-9+/=]{20,})',
211
+ lambda m: f"{m.group(1)}{m.group(3)}******{m.group(5)}"
212
+ if m.group(1)
213
+ else "******",
214
+ logs,
215
+ flags=re.IGNORECASE,
216
+ )
217
+ raise Exception(f"Release application failed. Logs:\n{log_text}")
202
218
 
203
219
  def _get_application_status(self, app_id: str):
204
220
  response = ve_request(
@@ -213,18 +229,51 @@ class VeFaaS:
213
229
  )
214
230
  return response["Result"]["Status"], response
215
231
 
216
- def _list_application(self):
217
- response = ve_request(
218
- request_body={},
219
- action="ListApplications",
220
- ak=self.ak,
221
- sk=self.sk,
222
- service="vefaas",
223
- version="2021-03-03",
224
- region="cn-beijing",
225
- host="open.volcengineapi.com",
226
- )
227
- return response["Result"]["Items"]
232
+ def _list_application(self, app_id: str = None, app_name: str = None):
233
+ # firt match app_id. if app_id is None,then match app_name and remove app_id
234
+ request_body = {
235
+ "OrderBy": {"Key": "CreateTime", "Ascend": False},
236
+ "FunctionId": app_id if app_id else None,
237
+ "Filters": [{"Item": {"Key": "Name", "Value": [app_name]}}]
238
+ if app_name and not app_id
239
+ else None,
240
+ }
241
+ # remove None
242
+ request_body = {k: v for k, v in request_body.items() if v is not None}
243
+
244
+ page_size = 50
245
+ page_number = 1
246
+ all_items = []
247
+ total_page = None
248
+ while True:
249
+ try:
250
+ request_body.update({"PageNumber": page_number, "PageSize": page_size})
251
+ response = ve_request(
252
+ request_body=request_body,
253
+ action="ListApplications",
254
+ ak=self.ak,
255
+ sk=self.sk,
256
+ service="vefaas",
257
+ version="2021-03-03",
258
+ region="cn-beijing",
259
+ host="open.volcengineapi.com",
260
+ )
261
+ result = response.get("Result", {})
262
+ items = result.get("Items", [])
263
+ all_items.extend(items)
264
+
265
+ if total_page is None:
266
+ total = result.get("Total", 0)
267
+ total_page = (total + page_size - 1) // page_size
268
+
269
+ if page_number >= total_page or not items:
270
+ break
271
+ page_number += 1
272
+ except Exception as e:
273
+ raise ValueError(
274
+ f"List application failed. Error: {str(e)}. Response: {response}."
275
+ )
276
+ return all_items
228
277
 
229
278
  def _update_function_code(
230
279
  self,
@@ -253,10 +302,6 @@ class VeFaaS:
253
302
 
254
303
  # Get application status and extract function info
255
304
  status, full_response = self._get_application_status(app_id)
256
- if status == "deploy_fail":
257
- raise ValueError(
258
- f"Cannot update failed application. Current status: {status}"
259
- )
260
305
 
261
306
  # Extract function name from application config
262
307
  cloud_resource = full_response["Result"]["CloudResource"]
@@ -300,7 +345,7 @@ class VeFaaS:
300
345
  def get_application_details(self, app_id: str = None, app_name: str = None):
301
346
  if not app_id and not app_name:
302
347
  raise ValueError("app_id and app_name cannot be both empty.")
303
- apps = self._list_application()
348
+ apps = self._list_application(app_id=app_id, app_name=app_name)
304
349
  if app_id:
305
350
  for app in apps:
306
351
  if app["Id"] == app_id:
@@ -312,7 +357,7 @@ class VeFaaS:
312
357
  return app
313
358
 
314
359
  def find_app_id_by_name(self, name: str):
315
- apps = self._list_application()
360
+ apps = self._list_application(app_name=name)
316
361
  for app in apps:
317
362
  if app["Name"] == name:
318
363
  return app["Id"]
@@ -332,12 +377,7 @@ class VeFaaS:
332
377
  host="open.volcengineapi.com",
333
378
  )
334
379
  except Exception as e:
335
- typer.echo(
336
- typer.style(
337
- f"Delete application failed. Response: {e}",
338
- fg=typer.colors.BRIGHT_RED,
339
- )
340
- )
380
+ logger.error(f"Delete application failed. Response: {e}")
341
381
 
342
382
  def deploy(
343
383
  self,
@@ -409,3 +449,280 @@ class VeFaaS:
409
449
  logger.info(f"VeFaaS application {name} with ID {app_id} deployed on {url}.")
410
450
 
411
451
  return url, app_id, function_id
452
+
453
+ def _create_image_function(self, function_name: str, image: str):
454
+ """Create function using container image instead of code upload."""
455
+ # Read environment variables from veadk configuration
456
+ envs = []
457
+ for key, value in veadk.config.veadk_environments.items():
458
+ envs.append(EnvForCreateFunctionInput(key=key, value=value))
459
+ logger.info(
460
+ f"Fetch {len(envs)} environment variables for image function.",
461
+ )
462
+
463
+ # Create function with container image source configuration
464
+ res = self.client.create_function(
465
+ volcenginesdkvefaas.CreateFunctionRequest(
466
+ command="bash ./run.sh", # Custom startup command
467
+ name=function_name,
468
+ description="Created by VeADK (Volcengine Agent Development Kit)",
469
+ tags=[TagForCreateFunctionInput(key="provider", value="veadk")],
470
+ runtime="native/v1", # Native runtime required for container images
471
+ source_type="image", # Set source type to container image
472
+ source=image, # Container image URL
473
+ request_timeout=1800, # Request timeout in seconds
474
+ envs=envs, # Environment variables from configuration
475
+ )
476
+ )
477
+
478
+ # Log function creation success without exposing sensitive information
479
+ logger.debug(
480
+ f"Function creation in {res.project_name} project with ID {res.id}"
481
+ )
482
+
483
+ function_id = res.id
484
+ logger.info(
485
+ f"Function {function_name} created with image {image} and ID {function_id}"
486
+ )
487
+
488
+ return function_name, function_id
489
+
490
+ def query_user_cr_vpc_tunnel(
491
+ self, registry_name: str, max_attempts: int = 6
492
+ ) -> bool:
493
+ """Query and enable CR VPC tunnel for user registry access."""
494
+ logger.info(f"Setting up CR VPC tunnel for registry: {registry_name}")
495
+ waiting_times = 30
496
+
497
+ try:
498
+ for attempt in range(max_attempts):
499
+ # Check current status
500
+ logger.info(
501
+ f"Checking tunnel status (attempt {attempt + 1}/{max_attempts})"
502
+ )
503
+ query_resp = ve_request(
504
+ request_body={"Registry": registry_name},
505
+ action="QueryUserCrVpcTunnel",
506
+ ak=self.ak,
507
+ sk=self.sk,
508
+ service="vefaas",
509
+ version="2021-03-03",
510
+ region="cn-beijing",
511
+ host="open.volcengineapi.com",
512
+ )
513
+
514
+ current_status = query_resp.get("Result", {}).get("Ready", False)
515
+ logger.info(f"Current tunnel status: {current_status}")
516
+
517
+ # Always try to enable
518
+ logger.info("Enable VPC tunnel")
519
+ enable_resp = ve_request(
520
+ request_body={"Registry": registry_name},
521
+ action="EnableUserCrVpcTunnel",
522
+ ak=self.ak,
523
+ sk=self.sk,
524
+ service="vefaas",
525
+ version="2021-03-03",
526
+ region="cn-beijing",
527
+ host="open.volcengineapi.com",
528
+ )
529
+
530
+ # Handle EnableUserCrVpcTunnel response correctly
531
+ enable_result = enable_resp.get("Result", {})
532
+ enable_status = enable_result.get("Status", "")
533
+ enable_message = enable_result.get("Message", "")
534
+
535
+ if enable_status == "success":
536
+ logger.info("Enable tunnel succeeded")
537
+ elif enable_status == "failed":
538
+ logger.warning(f"Enable tunnel failed: {enable_message}")
539
+ else:
540
+ logger.warning(f"Enable tunnel unknown status: {enable_status}")
541
+
542
+ # Verify final status
543
+ logger.info("Verifying tunnel status")
544
+ verify_resp = ve_request(
545
+ request_body={"Registry": registry_name},
546
+ action="QueryUserCrVpcTunnel",
547
+ ak=self.ak,
548
+ sk=self.sk,
549
+ service="vefaas",
550
+ version="2021-03-03",
551
+ region="cn-beijing",
552
+ host="open.volcengineapi.com",
553
+ )
554
+
555
+ final_status = verify_resp.get("Result", {}).get("Ready", False)
556
+ logger.info(f"Final tunnel status: {final_status}")
557
+
558
+ if final_status:
559
+ logger.info(
560
+ f"CR VPC tunnel successfully enabled for {registry_name}"
561
+ )
562
+ return True
563
+
564
+ # If not ready and not last attempt, wait and retry
565
+ if attempt < max_attempts - 1:
566
+ logger.warning(
567
+ f"Tunnel not ready, waiting {waiting_times}s before retry"
568
+ )
569
+ time.sleep(waiting_times)
570
+
571
+ except Exception as e:
572
+ raise ValueError(f"Failed to setup CR VPC tunnel: {str(e)}")
573
+
574
+ return False
575
+
576
+ def _create_image_function(self, function_name: str, image: str):
577
+ """Create function using container image instead of code upload."""
578
+ # Read environment variables from veadk configuration
579
+ envs = []
580
+ for key, value in veadk.config.veadk_environments.items():
581
+ envs.append(EnvForCreateFunctionInput(key=key, value=value))
582
+ logger.info(
583
+ f"Fetch {len(envs)} environment variables for image function.",
584
+ )
585
+
586
+ # Create function with container image source configuration
587
+ res = self.client.create_function(
588
+ volcenginesdkvefaas.CreateFunctionRequest(
589
+ command="bash ./run.sh", # Custom startup command
590
+ name=function_name,
591
+ description="Created by VeADK (Volcengine Agent Development Kit)",
592
+ tags=[TagForCreateFunctionInput(key="provider", value="veadk")],
593
+ runtime="native/v1", # Native runtime required for container images
594
+ source_type="image", # Set source type to container image
595
+ source=image, # Container image URL
596
+ request_timeout=1800, # Request timeout in seconds
597
+ envs=envs, # Environment variables from configuration
598
+ )
599
+ )
600
+
601
+ # Log function creation success without exposing sensitive information
602
+ logger.debug(
603
+ f"Function creation in {res.project_name} project with ID {res.id}"
604
+ )
605
+
606
+ function_id = res.id
607
+ logger.info(
608
+ f"Function {function_name} created with image {image} and ID {function_id}"
609
+ )
610
+
611
+ return function_name, function_id
612
+
613
+ def deploy_image(
614
+ self,
615
+ name: str,
616
+ image: str,
617
+ registry_name: str,
618
+ gateway_name: str = "",
619
+ gateway_service_name: str = "",
620
+ gateway_upstream_name: str = "",
621
+ ) -> tuple[str, str, str]:
622
+ """Deploy application using container image.
623
+
624
+ Args:
625
+ name (str): Application name.
626
+ image (str): Container image URL.
627
+ gateway_name (str, optional): Gateway name. Defaults to "".
628
+ gateway_service_name (str, optional): Gateway service name. Defaults to "".
629
+ gateway_upstream_name (str, optional): Gateway upstream name. Defaults to "".
630
+
631
+ Returns:
632
+ tuple[str, str, str]: (url, app_id, function_id)
633
+ """
634
+ # Validate application name format
635
+ is_ready = self.query_user_cr_vpc_tunnel(registry_name)
636
+ if not is_ready:
637
+ raise ValueError("CR VPC tunnel is not ready")
638
+
639
+ if "_" in name:
640
+ raise ValueError("Function or Application name cannot contain '_'.")
641
+
642
+ # Generate default gateway names with timestamp if not provided
643
+ if not gateway_name:
644
+ gateway_name = f"{name}-gw-{formatted_timestamp()}"
645
+
646
+ # Check for existing serverless gateways to reuse
647
+ existing_gateways = self.apig_client.list_gateways()
648
+ for gateway_instance in existing_gateways.items:
649
+ if (
650
+ gateway_instance.type == "serverless"
651
+ and gateway_instance.name != gateway_name
652
+ ):
653
+ logger.warning(
654
+ f"You have at least one serverless gateway {gateway_instance.name}, but not {gateway_name}. Using {gateway_instance.name} instead."
655
+ )
656
+ gateway_name = gateway_instance.name
657
+ break
658
+
659
+ # Set default gateway service and upstream names
660
+ if not gateway_service_name:
661
+ gateway_service_name = f"{name}-gw-svr-{formatted_timestamp()}"
662
+ if not gateway_upstream_name:
663
+ gateway_upstream_name = f"{name}-gw-us-{formatted_timestamp()}"
664
+
665
+ function_name = f"{name}-fn"
666
+
667
+ # Log deployment start with image information
668
+ logger.info(
669
+ f"Start to create VeFaaS function {function_name} with image {image}. Gateway: {gateway_name}, Gateway Service: {gateway_service_name}, Gateway Upstream: {gateway_upstream_name}."
670
+ )
671
+
672
+ # Create function using container image method
673
+ function_name, function_id = self._create_image_function(function_name, image)
674
+ logger.info(f"VeFaaS function {function_name} with ID {function_id} created.")
675
+
676
+ # Create application using existing application creation logic
677
+ logger.info(f"Start to create VeFaaS application {name}.")
678
+ app_id = self._create_application(
679
+ name,
680
+ function_name,
681
+ gateway_name,
682
+ gateway_upstream_name,
683
+ gateway_service_name,
684
+ )
685
+
686
+ # Release application and get deployment URL
687
+ logger.info(f"VeFaaS application {name} with ID {app_id} created.")
688
+ logger.info(f"Start to release VeFaaS application {app_id}.")
689
+ # Release application with retry
690
+ max_attempts = 5
691
+ attempt = 0
692
+ while True:
693
+ try:
694
+ url = self._release_application(app_id)
695
+ logger.info(f"VeFaaS application {name} with ID {app_id} released.")
696
+ break
697
+ except Exception:
698
+ attempt += 1
699
+ if attempt < max_attempts:
700
+ wait_time = 30 * attempt
701
+ logger.info(
702
+ f"Image sync still in progress. Waiting {wait_time} seconds before retry {attempt}/{max_attempts}."
703
+ )
704
+ time.sleep(wait_time)
705
+ else:
706
+ raise
707
+
708
+ logger.info(f"VeFaaS application {name} with ID {app_id} deployed on {url}.")
709
+
710
+ return url, app_id, function_id
711
+
712
+ def _get_application_logs(self, app_id: str) -> list[str]:
713
+ response = _ = ve_request(
714
+ request_body={"Id": app_id, "Limit": 99999, "RevisionNumber": 1},
715
+ action="GetApplicationRevisionLog",
716
+ ak=self.ak,
717
+ sk=self.sk,
718
+ service="vefaas",
719
+ version="2021-03-03",
720
+ region="cn-beijing",
721
+ host="open.volcengineapi.com",
722
+ )
723
+
724
+ try:
725
+ logs = response["Result"]["LogLines"]
726
+ return logs
727
+ except Exception as _:
728
+ raise ValueError(f"Get application log failed. Response: {response}")
@@ -0,0 +1,17 @@
1
+ {
2
+ "local_dir_name": "veadk_vefaas_web_proj",
3
+ "app_name": "simple-blog",
4
+ "vefaas_application_name": "simple-blog",
5
+ "veapig_instance_name": "",
6
+ "veapig_service_name": "",
7
+ "veapig_upstream_name": "",
8
+ "use_adk_web": false,
9
+ "veadk_version": "",
10
+ "_copy_without_render": [
11
+ "*.html",
12
+ "*.css",
13
+ "*.js",
14
+ "static/**/*",
15
+ "templates/**/*"
16
+ ]
17
+ }
@@ -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,23 @@
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
+ from veadk.cloud.cloud_app import CloudApp
16
+
17
+ def main() -> None:
18
+ cloud_app = CloudApp(vefaas_application_name="{{cookiecutter.vefaas_application_name}}")
19
+ cloud_app.delete_self()
20
+
21
+
22
+ if __name__ == "__main__":
23
+ main()
@@ -0,0 +1,2 @@
1
+ VOLCENGINE_ACCESS_KEY:
2
+ VOLCENGINE_SECRET_KEY:
@@ -0,0 +1,41 @@
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 asyncio
16
+ from pathlib import Path
17
+
18
+ from veadk.cloud.cloud_agent_engine import CloudAgentEngine
19
+
20
+ async def main():
21
+ engine = CloudAgentEngine()
22
+
23
+ cloud_app = engine.deploy(
24
+ path=str(Path(__file__).parent / "src"),
25
+ application_name="{{cookiecutter.vefaas_application_name}}",
26
+ gateway_name="{{cookiecutter.veapig_instance_name}}",
27
+ gateway_service_name="{{cookiecutter.veapig_service_name}}",
28
+ gateway_upstream_name="{{cookiecutter.veapig_upstream_name}}",
29
+ use_adk_web={{cookiecutter.use_adk_web}},
30
+ local_test=False, # Set to True for local testing before deploy to VeFaaS
31
+ )
32
+ print(f"VeFaaS application ID: {cloud_app.vefaas_application_id}")
33
+
34
+ if {{cookiecutter.use_adk_web}}:
35
+ print(f"Web is running at: {cloud_app.vefaas_endpoint}")
36
+ else:
37
+ print(f"Web template does not support use_adk_web=False")
38
+
39
+
40
+ if __name__ == "__main__":
41
+ asyncio.run(main())
@@ -0,0 +1,23 @@
1
+ # 使用官方Python镜像作为基础镜像
2
+ FROM python:3.9-slim
3
+
4
+ # 设置工作目录
5
+ WORKDIR /app
6
+
7
+ # 复制依赖文件并安装依赖
8
+ COPY requirements.txt .
9
+ RUN pip install --no-cache-dir -r requirements.txt
10
+
11
+ # 复制项目文件
12
+ COPY . .
13
+
14
+ # 设置环境变量
15
+ ENV FLASK_APP=app.py
16
+ ENV FLASK_ENV=production
17
+ ENV PYTHONUNBUFFERED=1
18
+
19
+ # 暴露端口
20
+ EXPOSE 8000
21
+
22
+ # 启动命令
23
+ CMD ["bash", "run.sh"]