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
2 changes: 1 addition & 1 deletion .github/workflows/unit-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
run: |
uv venv .venv
source .venv/bin/activate
uv sync
uv sync --all-extras
uv pip install -e .
- name: Run unit tests with pytest
Expand Down
46 changes: 44 additions & 2 deletions docs/docs/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,5 +117,47 @@ app = CloudApp(name="veadk-agent", endpoint=ENDPOINT)
cloud_app.invoke(user_id=USER_ID, session_id=SESSION_ID, message=...)
```

- 更新自身代码
- 删除自身
## 更新云应用

### 通过 CloudAgentEngine 更新

当您需要更新已部署的Agent代码时,可以使用`update_function_code`方法:

```python
from veadk.cloud.cloud_agent_engine import CloudAgentEngine

engine = CloudAgentEngine()

# 更新现有应用的代码,保持相同的访问端点
updated_cloud_app = engine.update_function_code(
application_name="my-agent-app", # 现有应用名称
path="/my-agent-project" # 本地项目路径
)

# 可以使用updated_cloud_app.vefaas_endpoint访问您的项目
```

**注意事项:**
- 更新操作会保持相同的访问端点URL
- 确保项目路径包含`agent.py`文件


## 删除云应用

### 通过 CloudAgentEngine 删除

```python
from veadk.cloud.cloud_agent_engine import CloudAgentEngine

engine = CloudAgentEngine()

# 删除指定的云应用
engine.remove(app_name="my-agent-app")
```

执行时会提示确认:
```
Confirm delete cloud app my-agent-app? (y/N): y
```

输入`y`确认删除,输入其他任何字符或直接回车则取消删除。
124 changes: 124 additions & 0 deletions tests/test_cloud.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import tempfile
import pytest

from unittest.mock import Mock, patch, AsyncMock

os.environ["VOLCENGINE_ACCESS_KEY"] = "test_access_key"
os.environ["VOLCENGINE_SECRET_KEY"] = "test_secret_key"

from veadk.cloud.cloud_agent_engine import CloudAgentEngine


@pytest.mark.asyncio
async def test_cloud():
app_name = "test-app"
key = "CloudTestIdentifier123"
test_endpoint = "https://test-endpoint.volcengine.com"
test_message = "Hello cloud agent"

# Create temporary directory with required agent.py file for testing
with tempfile.TemporaryDirectory() as temp_dir:
with open(os.path.join(temp_dir, "agent.py"), "w") as f:
f.write(f"# Test agent implementation with {key}")

# Mock shutil.copy to avoid template file copying issues
with patch("shutil.copy"):
with patch("veadk.cloud.cloud_agent_engine.VeFaaS") as mock_vefaas_class:
# Setup mock VeFaaS service for all operations
mock_vefaas_service = Mock()
mock_vefaas_class.return_value = mock_vefaas_service

# Mock deploy operation
mock_vefaas_service.deploy.return_value = (
test_endpoint,
"app-123",
"func-456",
)

# Mock update operation
mock_vefaas_service._update_function_code.return_value = (
test_endpoint,
"app-123",
"func-456",
)

# Mock remove operation
mock_vefaas_service.find_app_id_by_name.return_value = "app-123"
mock_vefaas_service.delete.return_value = None

# Test CloudAgentEngine creation and deploy functionality
engine = CloudAgentEngine()

# Test deploy operation
cloud_app = engine.deploy(application_name=app_name, path=temp_dir)

# Verify deployment result contains expected values
assert cloud_app.vefaas_application_name == app_name
assert cloud_app.vefaas_endpoint == test_endpoint
assert cloud_app.vefaas_application_id == "app-123"

# Test update_function_code operation
updated_app = engine.update_function_code(
application_name=app_name, path=temp_dir
)

# Verify update result maintains same endpoint
assert updated_app.vefaas_endpoint == test_endpoint

# Test remove operation with mocked user input
with patch("builtins.input", return_value="y"):
engine.remove(app_name)
mock_vefaas_service.find_app_id_by_name.assert_called_with(app_name)
mock_vefaas_service.delete.assert_called_with("app-123")

# Test CloudApp message_send functionality
mock_response = Mock()
mock_message = Mock()
mock_response.root.result = mock_message

with patch.object(cloud_app, "_get_a2a_client") as mock_get_client:
mock_client = AsyncMock()
mock_client.send_message = AsyncMock(return_value=mock_response)
mock_get_client.return_value = mock_client

# Test message sending to cloud agent
result = await cloud_app.message_send(
message=test_message,
session_id="session-123",
user_id="user-456",
)

# Verify message sending result
assert result == mock_message
mock_client.send_message.assert_called_once()

# Test CloudApp delete_self functionality
with patch("builtins.input", return_value="y"):
with patch(
"veadk.cli.services.vefaas.vefaas.VeFaaS"
) as mock_vefaas_in_app:
mock_vefaas_client = Mock()
mock_vefaas_in_app.return_value = mock_vefaas_client
mock_vefaas_client.delete.return_value = None

cloud_app.delete_self()
mock_vefaas_client.delete.assert_called_with("app-123")

# Verify all mocks were called as expected
mock_vefaas_service.deploy.assert_called_once()
mock_vefaas_service._update_function_code.assert_called_once()