Skip to content
Open
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
10 changes: 8 additions & 2 deletions .github/workflows/python-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,11 @@ jobs:
- name: Run tests need admin and network
if: success()
run: |
echo "🔐 Running admin and network tests..."
uv run pytest -n auto -m "need_admin_and_network" --reruns 1
echo "🌐 Running admin and network tests..."
uv run pytest -n auto -m "need_admin_and_network" --reruns 1

- name: Run tests need FC
if: success()
run: |
echo "☁️ Running FC tests..."
uv run pytest -n auto -m "need_fc" --reruns 1
378 changes: 378 additions & 0 deletions docs/rock/deployment-architecture.md

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -171,5 +171,6 @@ markers = [
"need_ray: need ray start",
"need_docker: need docker daemon running",
"need_admin: need admin start",
"need_admin_and_network: need install from network"
"need_admin_and_network: need install from network",
"need_fc: need FC (Function Compute) environment"
]
82 changes: 82 additions & 0 deletions rock-conf/rock-fc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# =============================================================================
# ROCK Admin 运行时配置 - FC 环境
# =============================================================================
#
# 用途:ROCK Admin 服务启动时加载的运行时配置
#
# 使用方式:
# rock admin start --env fc
# 或 export ROCK_CONFIG=rock-conf/rock-fc.yml
#
# 注意:此文件不是函数部署配置,FC 函数部署使用
# rock/deployments/fc_rocklet/*/s.yaml + s deploy
#
# =============================================================================
#
# 配置层级说明:
#
# ┌─────────────────────────────────────────────────────────────────────┐
# │ FCConfig (Admin 服务级) - 本文件 │
# │ - Admin 启动时加载,提供默认值和凭证 │
# │ - 服务级设置 (region, account_id, credentials) │
# └─────────────────────────────────────────────────────────────────────┘
# │
# │ merge_with_fc_config()
# ▼
# ┌─────────────────────────────────────────────────────────────────────┐
# │ FCDeploymentConfig (API 调用级) │
# │ - 每个 sandbox API 请求创建 │
# │ - 可覆盖特定字段 (memory, cpus, timeout 等) │
# │ - session_id 与 ROCK sandbox_id 1:1 映射 │
# └─────────────────────────────────────────────────────────────────────┘
# │
# │ 用于调用 FC 函数
# ▼
# ┌─────────────────────────────────────────────────────────────────────┐
# │ s.yaml (FC 函数部署配置) │
# │ - 定义 FC 函数资源规格 │
# │ - Session affinity, memory, CPU, timeout 等 │
# │ - 通过 `s deploy` 命令部署 │
# │ - 位置: rock/deployments/fc_rocklet/{runtime,container,adapter}/ │
# └─────────────────────────────────────────────────────────────────────┘
#
# =============================================================================

# Ray 配置(FC 环境不使用 Ray 进行沙箱调度,但可用于其他分布式任务)
ray:
runtime_env:
working_dir: ./
pip: ./requirements_sandbox_actor.txt
namespace: "rock-sandbox-fc"

# FC 配置(阿里云函数计算服务级别配置)
# FC (Function Compute) 是阿里云的无服务器计算服务
fc:
# 连接设置
region: "cn-hangzhou"
account_id: null # 阿里云账号 ID,运行时从环境变量或 STS 获取

# 函数名(必须与 s.yaml 中部署的函数名一致)
# 部署流程:选择一种方案执行 s deploy → function_name 已统一为 rock-serverless-runtime-rocklet
function_name: "rock-serverless-runtime-rocklet"

# 凭证(建议通过环境变量或 STS 临时凭证提供)
# access_key_id: null
# access_key_secret: null
# security_token: null

# 资源默认值(可被 API 调用覆盖)
default_memory: 4096 # MB
default_cpus: 2.0

# 超时默认值(单位:秒)
default_session_ttl: 600 # 会话生命周期(秒),对应 s.yaml 中的 sessionTTLInSeconds
default_function_timeout: 30.0 # 函数执行超时(秒),单个请求最大执行时长
default_session_idle_timeout: 60 # 会话空闲超时(秒),对应 s.yaml 中的 sessionIdleTimeoutInSeconds

# 协议设置
session_affinity_header: "x-rock-session-id"

# 预热配置(FC 环境无本地镜像需预热)
warmup:
images: []
2 changes: 2 additions & 0 deletions rock/actions/sandbox/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class BashAction(BaseModel):
class WriteFileRequest(BaseModel):
content: str
path: str
encoding: str = "utf-8"
"""Text encoding to use when writing the file. Defaults to utf-8."""


class CloseBashSessionRequest(BaseModel):
Expand Down
80 changes: 80 additions & 0 deletions rock/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,83 @@ class OssConfig:
role_arn: str = ""


@dataclass
class FCConfig:
"""FC (Function Compute) 服务级配置,用于 Admin。

提供 FC 沙箱部署的默认值和凭证。
API 调用可通过 FCDeploymentConfig 覆盖特定字段。

FC (Function Compute) 是阿里云的无服务器计算服务:
https://www.alibabacloud.com/product/function-compute

配置层级:
┌─────────────────────────────────────────────────────────────────────┐
│ FCConfig (Admin 服务级) - 本文件 │
│ - Admin 启动时加载,提供默认值和凭证 │
│ - 服务级设置 (region, account_id, credentials) │
└─────────────────────────────────────────────────────────────────────┘
│ merge_with_fc_config()
┌─────────────────────────────────────────────────────────────────────┐
│ FCDeploymentConfig (API 调用级) │
│ - 每个 sandbox API 请求创建 │
│ - session_id 与 ROCK sandbox_id 1:1 映射 │
│ - 用于调用已部署的 FC 函数,不涉及函数部署 │
└─────────────────────────────────────────────────────────────────────┘
│ 调用已部署的 FC 函数
┌─────────────────────────────────────────────────────────────────────┐
│ s.yaml (FC 函数部署配置) │
│ - 定义 FC 函数资源规格,通过 `s deploy` 部署 │
│ - 函数部署是前置条件,Admin 调用时函数已存在 │
└─────────────────────────────────────────────────────────────────────┘
"""

# Connection settings (service-level defaults)
region: str = "cn-hangzhou"
"""Alibaba Cloud region for FC function."""

account_id: str | None = None
"""Alibaba Cloud account ID."""

function_name: str = "rock-serverless-runtime-rocklet"
"""Default FC function name for sandbox runtime."""

# Credentials (service-level, sensitive)
access_key_id: str | None = None
"""Alibaba Cloud AccessKey ID for authentication."""

access_key_secret: str = field(default="", repr=False)
"""Alibaba Cloud AccessKey Secret for authentication."""

security_token: str | None = None
"""Alibaba Cloud STS security token for temporary credentials."""

# Resource defaults (can be overridden by API)
default_memory: int = 4096
"""Default memory allocation in MB for FC function."""

default_cpus: float = 2.0
"""Default CPU cores for FC function."""

# Timeout defaults (can be overridden by API, all in seconds)
default_session_ttl: int = 600
"""Default session time-to-live in seconds."""

default_function_timeout: float = 30.0
"""Default function execution timeout in seconds for single request."""

default_session_idle_timeout: int = 60
"""Default session idle timeout in seconds. Matches s.yaml sessionIdleTimeoutInSeconds."""

# Protocol settings (service-level fixed)
session_affinity_header: str = "x-rock-session-id"
"""Header field name for session affinity routing."""


@dataclass
class ProxyServiceConfig:
timeout: float = 180.0
Expand Down Expand Up @@ -200,6 +277,7 @@ class RockConfig:
redis: RedisConfig = field(default_factory=RedisConfig)
sandbox_config: SandboxConfig = field(default_factory=SandboxConfig)
oss: OssConfig = field(default_factory=OssConfig)
fc: FCConfig = field(default_factory=FCConfig)
runtime: RuntimeConfig = field(default_factory=RuntimeConfig)
proxy_service: ProxyServiceConfig = field(default_factory=ProxyServiceConfig)
scheduler: SchedulerConfig = field(default_factory=SchedulerConfig)
Expand Down Expand Up @@ -238,6 +316,8 @@ def from_env(cls, config_path: str | None = None):
kwargs["sandbox_config"] = SandboxConfig(**config["sandbox_config"])
if "oss" in config:
kwargs["oss"] = OssConfig(**config["oss"])
if "fc" in config:
kwargs["fc"] = FCConfig(**config["fc"])
if "runtime" in config:
kwargs["runtime"] = RuntimeConfig(**config["runtime"])
if "proxy_service" in config:
Expand Down
122 changes: 122 additions & 0 deletions rock/deployments/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,128 @@ def get_deployment(self) -> AbstractDeployment:
return RemoteDeployment.from_config(self)


class FCDeploymentConfig(DeploymentConfig):
"""Configuration for Alibaba Cloud Function Compute deployment.

This deployment type enables serverless sandbox execution using FC
with WebSocket session management for stateful operations.

FC (Function Compute) is Alibaba Cloud's serverless compute service:
https://www.alibabacloud.com/product/function-compute

Configuration Hierarchy:
┌─────────────────────────────────────────────────────────────────────┐
│ FCConfig (Admin 服务级) - 本文件 │
│ - Admin 启动时加载,提供默认值和凭证 │
│ - 服务级设置 (region, account_id, credentials) │
└─────────────────────────────────────────────────────────────────────┘
│ merge_with_fc_config()
┌─────────────────────────────────────────────────────────────────────┐
│ FCDeploymentConfig (API 调用级) │
│ - 每个 sandbox API 请求创建 │
│ - session_id 与 ROCK sandbox_id 1:1 映射 │
│ - 用于调用已部署的 FC 函数,不涉及函数部署 │
│ - session_ttl/session_idle_timeout: FC 会话生命周期管理 │
└─────────────────────────────────────────────────────────────────────┘
│ 调用已部署的 FC 函数
┌─────────────────────────────────────────────────────────────────────┐
│ s.yaml (FC 函数部署配置) │
│ - 定义 FC 函数资源规格,通过 `s deploy` 部署 │
│ - Session affinity, memory, CPU, timeout 等 │
│ - 位置: rock/deployments/fc_rocklet/{runtime,container,adapter}/ │
│ - 函数部署是前置条件,Admin 调用时函数已存在 │
└─────────────────────────────────────────────────────────────────────┘

The session_id serves as both the FC session identifier (for WebSocket
stateful invocation routing) and the ROCK sandbox_id (for business logic).
"""

type: Literal["fc"] = "fc"
"""Deployment type discriminator for JSON/YAML parsing."""

session_id: str | None = None
"""FC session identifier for stateful invocation routing.

This serves as both:
- FC native session_id: Routes WebSocket requests to the same function instance
- ROCK sandbox_id: Used for lifecycle management, billing, and state tracking

If None, will be auto-generated as 'fc-{uuid}'.
"""

# Connection settings (optional, use FCConfig defaults if not provided)
function_name: str | None = None
"""FC function name. If None, uses FCConfig.function_name."""

region: str | None = None
"""Alibaba Cloud region. If None, uses FCConfig.region."""

account_id: str | None = None
"""Alibaba Cloud account ID. If None, uses FCConfig.account_id."""

access_key_id: str | None = None
"""AccessKey ID. If None, uses FCConfig.access_key_id."""

access_key_secret: str | None = Field(default=None, repr=False, exclude=True)
"""AccessKey Secret. If None, uses FCConfig.access_key_secret."""

security_token: str | None = None
"""STS security token. If None, uses FCConfig.security_token."""

# Resource settings (optional, use FCConfig defaults if not provided)
memory: int | None = None
"""Memory in MB. If None, uses FCConfig.default_memory."""

cpus: float | None = None
"""CPU cores. If None, uses FCConfig.default_cpus."""

# Timeout settings (optional, use FCConfig defaults if not provided, all in seconds)
session_ttl: int | None = None
"""Session time-to-live in seconds. If None, uses FCConfig.default_session_ttl."""

session_idle_timeout: int | None = None
"""Session idle timeout in seconds. If None, uses FCConfig.default_session_idle_timeout."""

function_timeout: float | None = None
"""Function execution timeout in seconds for single request. If None, uses FCConfig.default_function_timeout."""

def get_deployment(self) -> AbstractDeployment:
from rock.deployments.fc import FCDeployment

return FCDeployment.from_config(self)

def merge_with_fc_config(self, fc_config: "FCConfig") -> "FCDeploymentConfig":
"""Merge this config with FCConfig defaults.

Args:
fc_config: Admin-level FC configuration with defaults.

Returns:
New FCDeploymentConfig with all fields populated.
"""
from rock.config import FCConfig

return FCDeploymentConfig(
type=self.type,
session_id=self.session_id,
function_name=self.function_name or fc_config.function_name,
region=self.region or fc_config.region,
account_id=self.account_id or fc_config.account_id,
access_key_id=self.access_key_id or fc_config.access_key_id,
access_key_secret=self.access_key_secret or fc_config.access_key_secret,
security_token=self.security_token or fc_config.security_token,
memory=self.memory or fc_config.default_memory,
cpus=self.cpus or fc_config.default_cpus,
session_ttl=self.session_ttl or fc_config.default_session_ttl,
session_idle_timeout=self.session_idle_timeout or fc_config.default_session_idle_timeout,
function_timeout=self.function_timeout or fc_config.default_function_timeout,
)


def get_deployment(config: DeploymentConfig) -> AbstractDeployment:
"""Create a deployment instance from the given configuration.

Expand Down
Loading
Loading