Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 108 additions & 25 deletions veadk/cli/services/vefaas/vefaas.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,36 +59,20 @@ def __init__(self, access_key: str, secret_key: str, region: str = "cn-beijing")

self.template_id = "6874f3360bdbc40008ecf8c7"

def _create_function(self, function_name: str, path: str):
# 1. Read envs
envs = []
for key, value in veadk.config.veadk_environments.items():
envs.append(EnvForCreateFunctionInput(key=key, value=value))
logger.info(
f"Fetch {len(envs)} environment variables.",
)
def _upload_and_mount_code(self, function_id: str, path: str):
"""Upload code to VeFaaS temp bucket and mount to function instance.

# 2. Create function
res = self.client.create_function(
volcenginesdkvefaas.CreateFunctionRequest(
command="./run.sh",
name=function_name,
description="Created by VeADK (Volcengine Agent Development Kit)",
tags=[TagForCreateFunctionInput(key="provider", value="veadk")],
runtime="native-python3.10/v1",
request_timeout=1800,
envs=envs,
)
)
function_id = res.id

# 3. Get a temp bucket to store code
Args:
function_id (str): Target function ID.
path (str): Local project path.
"""
# Get zipped code data
code_zip_data, code_zip_size, error = zip_and_encode_folder(path)
logger.info(
f"Zipped project size: {code_zip_size / 1024 / 1024:.2f} MB",
)

# 4. Upload code to VeFaaS temp bucket
# Upload code to VeFaaS temp bucket
req = volcenginesdkvefaas.GetCodeUploadAddressRequest(
function_id=function_id, content_length=code_zip_size
)
Expand All @@ -103,14 +87,42 @@ def _create_function(self, function_name: str, path: str):
error_message = f"Upload failed to {upload_url} with status code {response.status_code}: {response.text}"
raise ValueError(error_message)

# 5. Mount the TOS bucket to function instance
# Mount the TOS bucket to function instance
res = signed_request(
ak=self.ak,
sk=self.sk,
target="CodeUploadCallback",
body={"FunctionId": function_id},
)

return res

def _create_function(self, function_name: str, path: str):
# Read envs
envs = []
for key, value in veadk.config.veadk_environments.items():
envs.append(EnvForCreateFunctionInput(key=key, value=value))
logger.info(
f"Fetch {len(envs)} environment variables.",
)

# Create function
res = self.client.create_function(
volcenginesdkvefaas.CreateFunctionRequest(
command="./run.sh",
name=function_name,
description="Created by VeADK (Volcengine Agent Development Kit)",
tags=[TagForCreateFunctionInput(key="provider", value="veadk")],
runtime="native-python3.10/v1",
request_timeout=1800,
envs=envs,
)
)
function_id = res.id

# Upload and mount code using extracted method
self._upload_and_mount_code(function_id, path)

return function_name, function_id

def _create_application(
Expand Down Expand Up @@ -202,6 +214,77 @@ def _list_application(self):
)
return response["Result"]["Items"]

def _update_function_code(
self,
application_name: str, # application name
path: str,
) -> tuple[str, str, str]:
"""Update existing application function code while preserving URL.

Args:
application_name (str): Application name to update.
path (str): Local project path.

Returns:
tuple[str, str, str]: URL, app_id, function_id
"""
# Naming check
if "_" in application_name:
raise ValueError("Function or Application name cannot contain '_'.")

# Find existing application
app_id = self.find_app_id_by_name(application_name)
if not app_id:
raise ValueError(
f"Application '{application_name}' not found. Use deploy() for new applications."
)

# Get application status and extract function info
status, full_response = self._get_application_status(app_id)
if status == "deploy_fail":
raise ValueError(
f"Cannot update failed application. Current status: {status}"
)

# Extract function name from application config
cloud_resource = full_response["Result"]["CloudResource"]
cloud_resource = json.loads(cloud_resource)
function_name = cloud_resource["framework"]["function"]["Name"]
# existing_url = cloud_resource["framework"]["url"]["system_url"]
function_id = cloud_resource["framework"]["function"]["Id"]
if not function_id:
raise ValueError(f"Function '{function_name}' not found for update")

logger.info(
f"Start to update VeFaaS function {function_name} with path {path}."
)

# Upload and mount code using extracted method
self._upload_and_mount_code(function_id, path)

# Use update_function client method to apply changes
self.client.update_function(
volcenginesdkvefaas.UpdateFunctionRequest(
id=function_id,
request_timeout=1800, # Keep same timeout as deploy
)
)

logger.info(f"Function updated successfully: {function_id}")

logger.info(f"VeFaaS function {function_name} with ID {function_id} updated.")

# Release the application to apply changes
url = self._release_application(app_id)

logger.info(f"VeFaaS application {application_name} with ID {app_id} released.")

logger.info(
f"VeFaaS application {application_name} with ID {app_id} updated on {url}."
)

return url, app_id, function_id

def get_application_details(self, app_id: str = None, app_name: str = None):
if not app_id and not app_name:
raise ValueError("app_id and app_name cannot be both empty.")
Expand Down
36 changes: 36 additions & 0 deletions veadk/cloud/cloud_agent_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,39 @@ def remove(self, app_name: str):
else:
app_id = self._vefaas_service.find_app_id_by_name(app_name)
self._vefaas_service.delete(app_id)

def update_function_code(
self,
application_name: str,
path: str,
) -> CloudApp:
"""Update existing agent project code while keeping the same URL.

Args:
application_name (str): Existing application name to update.
path (str): Local agent project path.

Returns:
CloudApp: Updated cloud app with same endpoint.
"""
# convert `path` to absolute path
path = str(Path(path).resolve())
self._prepare(path, application_name)

try:
vefaas_application_url, app_id, function_id = (
self._vefaas_service._update_function_code(
application_name=application_name,
path=path,
)
)

return CloudApp(
vefaas_application_name=application_name,
vefaas_endpoint=vefaas_application_url,
vefaas_application_id=app_id,
)
except Exception as e:
raise ValueError(
f"Failed to update agent project on Volcengine FaaS platform. Error: {e}"
)