Skip to content

Commit 73f6665

Browse files
authored
feat(vefaas): vefaas update function (#33)
* feat(vefaas): vefaas update function * fix(vefaas): fix _update_function_code() without envs; create _upload_and_mount_code() * fix(vefaas): adjust _update_function_code position --------- Co-authored-by: tangou <[email protected]>
1 parent 5134ca8 commit 73f6665

File tree

2 files changed

+144
-25
lines changed

2 files changed

+144
-25
lines changed

veadk/cli/services/vefaas/vefaas.py

Lines changed: 108 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -59,36 +59,20 @@ def __init__(self, access_key: str, secret_key: str, region: str = "cn-beijing")
5959

6060
self.template_id = "6874f3360bdbc40008ecf8c7"
6161

62-
def _create_function(self, function_name: str, path: str):
63-
# 1. Read envs
64-
envs = []
65-
for key, value in veadk.config.veadk_environments.items():
66-
envs.append(EnvForCreateFunctionInput(key=key, value=value))
67-
logger.info(
68-
f"Fetch {len(envs)} environment variables.",
69-
)
62+
def _upload_and_mount_code(self, function_id: str, path: str):
63+
"""Upload code to VeFaaS temp bucket and mount to function instance.
7064
71-
# 2. Create function
72-
res = self.client.create_function(
73-
volcenginesdkvefaas.CreateFunctionRequest(
74-
command="./run.sh",
75-
name=function_name,
76-
description="Created by VeADK (Volcengine Agent Development Kit)",
77-
tags=[TagForCreateFunctionInput(key="provider", value="veadk")],
78-
runtime="native-python3.10/v1",
79-
request_timeout=1800,
80-
envs=envs,
81-
)
82-
)
83-
function_id = res.id
84-
85-
# 3. Get a temp bucket to store code
65+
Args:
66+
function_id (str): Target function ID.
67+
path (str): Local project path.
68+
"""
69+
# Get zipped code data
8670
code_zip_data, code_zip_size, error = zip_and_encode_folder(path)
8771
logger.info(
8872
f"Zipped project size: {code_zip_size / 1024 / 1024:.2f} MB",
8973
)
9074

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

106-
# 5. Mount the TOS bucket to function instance
90+
# Mount the TOS bucket to function instance
10791
res = signed_request(
10892
ak=self.ak,
10993
sk=self.sk,
11094
target="CodeUploadCallback",
11195
body={"FunctionId": function_id},
11296
)
11397

98+
return res
99+
100+
def _create_function(self, function_name: str, path: str):
101+
# Read envs
102+
envs = []
103+
for key, value in veadk.config.veadk_environments.items():
104+
envs.append(EnvForCreateFunctionInput(key=key, value=value))
105+
logger.info(
106+
f"Fetch {len(envs)} environment variables.",
107+
)
108+
109+
# Create function
110+
res = self.client.create_function(
111+
volcenginesdkvefaas.CreateFunctionRequest(
112+
command="./run.sh",
113+
name=function_name,
114+
description="Created by VeADK (Volcengine Agent Development Kit)",
115+
tags=[TagForCreateFunctionInput(key="provider", value="veadk")],
116+
runtime="native-python3.10/v1",
117+
request_timeout=1800,
118+
envs=envs,
119+
)
120+
)
121+
function_id = res.id
122+
123+
# Upload and mount code using extracted method
124+
self._upload_and_mount_code(function_id, path)
125+
114126
return function_name, function_id
115127

116128
def _create_application(
@@ -202,6 +214,77 @@ def _list_application(self):
202214
)
203215
return response["Result"]["Items"]
204216

217+
def _update_function_code(
218+
self,
219+
application_name: str, # application name
220+
path: str,
221+
) -> tuple[str, str, str]:
222+
"""Update existing application function code while preserving URL.
223+
224+
Args:
225+
application_name (str): Application name to update.
226+
path (str): Local project path.
227+
228+
Returns:
229+
tuple[str, str, str]: URL, app_id, function_id
230+
"""
231+
# Naming check
232+
if "_" in application_name:
233+
raise ValueError("Function or Application name cannot contain '_'.")
234+
235+
# Find existing application
236+
app_id = self.find_app_id_by_name(application_name)
237+
if not app_id:
238+
raise ValueError(
239+
f"Application '{application_name}' not found. Use deploy() for new applications."
240+
)
241+
242+
# Get application status and extract function info
243+
status, full_response = self._get_application_status(app_id)
244+
if status == "deploy_fail":
245+
raise ValueError(
246+
f"Cannot update failed application. Current status: {status}"
247+
)
248+
249+
# Extract function name from application config
250+
cloud_resource = full_response["Result"]["CloudResource"]
251+
cloud_resource = json.loads(cloud_resource)
252+
function_name = cloud_resource["framework"]["function"]["Name"]
253+
# existing_url = cloud_resource["framework"]["url"]["system_url"]
254+
function_id = cloud_resource["framework"]["function"]["Id"]
255+
if not function_id:
256+
raise ValueError(f"Function '{function_name}' not found for update")
257+
258+
logger.info(
259+
f"Start to update VeFaaS function {function_name} with path {path}."
260+
)
261+
262+
# Upload and mount code using extracted method
263+
self._upload_and_mount_code(function_id, path)
264+
265+
# Use update_function client method to apply changes
266+
self.client.update_function(
267+
volcenginesdkvefaas.UpdateFunctionRequest(
268+
id=function_id,
269+
request_timeout=1800, # Keep same timeout as deploy
270+
)
271+
)
272+
273+
logger.info(f"Function updated successfully: {function_id}")
274+
275+
logger.info(f"VeFaaS function {function_name} with ID {function_id} updated.")
276+
277+
# Release the application to apply changes
278+
url = self._release_application(app_id)
279+
280+
logger.info(f"VeFaaS application {application_name} with ID {app_id} released.")
281+
282+
logger.info(
283+
f"VeFaaS application {application_name} with ID {app_id} updated on {url}."
284+
)
285+
286+
return url, app_id, function_id
287+
205288
def get_application_details(self, app_id: str = None, app_name: str = None):
206289
if not app_id and not app_name:
207290
raise ValueError("app_id and app_name cannot be both empty.")

veadk/cloud/cloud_agent_engine.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,39 @@ def remove(self, app_name: str):
167167
else:
168168
app_id = self._vefaas_service.find_app_id_by_name(app_name)
169169
self._vefaas_service.delete(app_id)
170+
171+
def update_function_code(
172+
self,
173+
application_name: str,
174+
path: str,
175+
) -> CloudApp:
176+
"""Update existing agent project code while keeping the same URL.
177+
178+
Args:
179+
application_name (str): Existing application name to update.
180+
path (str): Local agent project path.
181+
182+
Returns:
183+
CloudApp: Updated cloud app with same endpoint.
184+
"""
185+
# convert `path` to absolute path
186+
path = str(Path(path).resolve())
187+
self._prepare(path, application_name)
188+
189+
try:
190+
vefaas_application_url, app_id, function_id = (
191+
self._vefaas_service._update_function_code(
192+
application_name=application_name,
193+
path=path,
194+
)
195+
)
196+
197+
return CloudApp(
198+
vefaas_application_name=application_name,
199+
vefaas_endpoint=vefaas_application_url,
200+
vefaas_application_id=app_id,
201+
)
202+
except Exception as e:
203+
raise ValueError(
204+
f"Failed to update agent project on Volcengine FaaS platform. Error: {e}"
205+
)

0 commit comments

Comments
 (0)