diff --git a/README.md b/README.md
index 5e6f65d2..b2f8cd5f 100644
--- a/README.md
+++ b/README.md
@@ -84,9 +84,12 @@ Astron-xmod-shim 也提供了 Helm Chart 部署方式,适用于 Kubernetes 环
# 进入 Helm chart 目录
cd deploy/helm
-# 安装或升级应用
-helm upgrade --install astron-xmod-shim astron-xmod-shim/ -f astron-xmod-shim/values.yaml
-
+# 安装应用
+ helm install astron-xmod-shim ./astron-xmod-shim --kubeconfig ../../conf/shimlets/kubeconfig
+# 升级应用
+ helm upgrade astron-xmod-shim ./astron-xmod-shim --kubeconfig ../../conf/shimlets/kubeconfig
+# 卸载应用
+ helm uninstall astron-xmod-shim --kubeconfig ../../conf/shimlets/kubeconfig
# 验证部署
kubectl get pods -l app.kubernetes.io/name=astron-xmod-shim
```
@@ -118,37 +121,8 @@ kubectl get pods -l app.kubernetes.io/name=astron-xmod-shim
helm uninstall astron-xmod-shim
```
-## API 参考
-
-### 部署模型服务
-
-```bash
-curl -X POST http://localhost:8080/api/v1/modserv/deploy \
- -H "Content-Type: application/json" \
- -d '{
- "modelName": "example-model",
- "modelFile": "/path/to/model",
- "resourceRequirements": {
- "acceleratorType": "NVIDIA GPU",
- "acceleratorCount": 1,
- "cpu": "4",
- "memory": "16Gi"
- },
- "replicaCount": 1
- }'
-```
-
-### 查询服务状态
-
-```bash
-curl http://localhost:8080/api/v1/modserv/{serviceId}
-```
-
-### 列出已加载插件
-
-```bash
-curl http://localhost:8080/api/v1/plugins
-```
+## API 参考文档
+[API参考文档](deploy/docs/api.md)
## 插件开发指南
@@ -162,108 +136,7 @@ Astron-xmod-shim 原生内置了 Kubernetes Shimlet,用于在 Kubernetes 环
Kubernetes 的资源操作(如创建 Deployment 和 Service 等)。
#### 扩展示例:Docker Shimlet 实现
-
-以下是实现 Docker 环境适配插件的示例代码,用于将模型服务部署到 Docker 容器中:
-
-#### 步骤 1:实现 Shimlet 接口
-
-```go
-package dockershimlet
-
-import (
- "astron-xmod-shim/internal/core/shimlet"
- dto "astron-xmod-shim/internal/dto/deploy"
- "astron-xmod-shim/pkg/log"
- // 导入 Docker SDK 相关包
- // "github.com/docker/docker/client"
-)
-
-// DockerShimlet 实现 Docker 环境适配插件
-type DockerShimlet struct {
- // 这里可以添加 Docker 客户端等成员变量
- // client *client.Client
-}
-
-// 确保 DockerShimlet 实现了 Shimlet 接口(编译期检查)
-var _ shimlet.Shimlet = (*DockerShimlet)(nil)
-
-// InitWithConfig 初始化 Docker 客户端和配置
-func (d *DockerShimlet) InitWithConfig(confPath string) error {
- // 实现 Docker 客户端初始化逻辑
- // 1. 解析配置文件
- // 2. 创建 Docker 客户端连接
- // 3. 验证连接是否成功
- log.Info("Initializing Docker shimlet with config: %s", confPath)
- return nil
-}
-
-// Apply 应用部署规范,创建或更新 Docker 容器
-func (d *DockerShimlet) Apply(spec *dto.RequirementSpec) error {
- // 实现 Docker 容器创建/更新逻辑
- // 1. 根据 spec 构建容器配置(镜像、端口映射、卷挂载等)
- // 2. 检查容器是否已存在
- // 3. 存在则更新,不存在则创建新容器
- log.Info("Applying deployment spec to Docker: %s", spec.ModelName)
- return nil
-}
-
-// Delete 删除指定的 Docker 容器资源
-func (d *DockerShimlet) Delete(resourceID string) error {
- // 实现 Docker 容器删除逻辑
- // 1. 根据 resourceID 查找对应的容器
- // 2. 停止并删除容器
- log.Info("Deleting Docker resource: %s", resourceID)
- return nil
-}
-
-// Status 查询 Docker 容器的运行状态
-func (d *DockerShimlet) Status(resourceID string) (*dto.RuntimeStatus, error) {
- // 实现容器状态查询逻辑
- // 1. 根据 resourceID 查找容器
- // 2. 获取容器状态信息
- // 3. 构建并返回 RuntimeStatus 对象
- log.Info("Getting status for Docker resource: %s", resourceID)
- return &dto.RuntimeStatus{}, nil
-}
-
-// ID 返回当前 Shimlet 的唯一标识符
-func (d *DockerShimlet) ID() string {
- // 返回固定的标识符
- return "docker"
-}
-
-// Description 返回当前 Shimlet 的描述信息
-func (d *DockerShimlet) Description() string {
- // 返回描述文本
- return "Docker环境适配插件,用于在Docker容器中部署模型服务"
-}
-
-// ListDeployedServices 列出所有已部署的服务
-func (d *DockerShimlet) ListDeployedServices() ([]string, error) {
- // 实现服务列表查询逻辑
- // 1. 列出所有与模型服务相关的容器
- // 2. 提取并返回服务 ID 列表
- log.Info("Listing all deployed services in Docker")
- return []string{}, nil
-}
-```
-
-#### 步骤 2:注册 Docker Shimlet
-
-```go
-package dockershimlet
-
-import (
- "astron-xmod-shim/internal/core/shimlet"
-)
-
-// init 函数在插件加载时自动调用
-func init() {
- // 注册自定义的 Docker shimlet
- shimlet.Registry.AutoRegister(&DockerShimlet{})
-}
-```
-
+[自定义Shimlet示例](deploy/docs/shimlet-demo.md)
### 预定义收敛目标集合(GoalSet)
@@ -275,80 +148,6 @@ GoalSet 定义了模型部署的具体目标和执行逻辑。Astron-xmod-shim
Astron-xmod-shim 原生内置了 OpenSourceLLM GoalSet,用于开源大模型的部署流程。它采用 Builder
模式实现,包含模型路径映射、部署完成验证、规格一致性检查和服务暴露等关键目标,使用户能够快速部署开源大模型服务。
-#### 步骤 1:定义 Goal
-
-```go
-package mygoalset
-
-import (
- "astron-xmod-shim/internal/core/goal"
- "astron-xmod-shim/pkg/log"
-)
-
-// 定义一个验证模型的 Goal
-var validateModel = goal.Goal{
- Name: "validate-model",
- IsAchieved: func(ctx *goal.Context) bool {
- // 检查目标是否已达成
- return ctx.DeploySpec.ModelName != ""
- },
- Ensure: func(ctx *goal.Context) error {
- log.Info("开始验证模型: %s", ctx.DeploySpec.ModelName)
- // 实现模型验证逻辑
- return nil
- },
-}
-
-// 定义一个准备资源的 Goal
-var prepareResources = goal.Goal{
- Name: "prepare-resources",
- IsAchieved: func(ctx *goal.Context) bool {
- // 检查资源是否已准备好
- // 这里可以检查模型文件、配置等是否存在
- resourceReady, exists := ctx.Get("resourceReady").(bool)
- return exists && resourceReady
- },
- Ensure: func(ctx *goal.Context) error {
- log.Info("准备部署资源")
- // 实现资源准备逻辑
- // 准备完成后设置标记
- ctx.Set("resourceReady", true)
- return nil
- },
-}
-```
-
-#### 步骤 2:创建并注册 GoalSet
-
-```go
-package mygoalset
-
-import (
- "astron-xmod-shim/internal/core/goal"
- "time"
-)
-
-// init 函数在插件加载时自动调用
-func init() {
- // 使用 Builder 模式创建并注册自定义 GoalSet
- newMyGoalSet()
-}
-
-// newMyGoalSet 创建自定义 GoalSet 实例
-func newMyGoalSet() {
- goal.NewGoalSetBuilder("my-goalset").
- AddGoal(validateModel).
- AddGoal(prepareResources).
- WithMaxRetries(3). // 失败最多重试 3 次
- WithTimeout(2 * time.Minute). // 整体超时 2 分钟
- BuildAndRegister()
-}
-```
-
-### 扩展示例:Docker Shimlet
-
-除了内置的Kubernetes Shimlet外,开发者还可以实现Docker环境适配插件,将模型服务部署到Docker容器中。Docker Shimlet通过Docker
-API创建和管理容器,支持模型服务的完整生命周期管理。
### 扩展示例:业务场景 GoalSet
@@ -358,85 +157,14 @@ API创建和管理容器,支持模型服务的完整生命周期管理。
- **边缘部署GoalSet**:添加资源限制检查、模型量化优化、离线推理支持等特殊目标
- **企业级安全GoalSet**:集成身份验证、加密传输、访问控制等安全增强目标
-### 插件集成方式
-
-Astron-xmod-shim 使用 Go 语言的初始化注册机制实现插件集成,而不是通过共享库编译和热加载。
-
-#### 内置插件集成
-
-内置插件(如 Kubernetes Shimlet)通过在 `init()` 函数中自动注册到框架中:
-
-```go
-// K8sShimlet 的注册方式示例
-func init() {
-shimlet.Registry.AutoRegister(&K8sShimlet{})
-}
-```
-
-#### 自定义插件集成
-
-自定义插件可以通过以下方式集成到 Astron-xmod-shim 中:
+[自定义GoalSet示例](deploy/docs/goalset-demo.md)
-1. **实现标准接口**:按照文档中示例实现 `Shimlet` 或创建 `GoalSet`
-2. **自动注册**:在 `init()` 函数中使用注册表完成自动注册
-3. **重新编译**:将自定义插件代码放在正确的包路径下,然后重新编译整个应用程序
-#### 插件选择与配置
-
-通过命令行参数或配置文件指定要使用的插件:
-
-```bash
-# 通过命令行指定插件
-./model-serve-shim --shimlet=k8s --goalset=opensource-llm-deploy
-
-# 通过配置文件指定插件
-# config.yaml 中设置
-defaultShimlet: k8s
-defaultGoalSet: opensource-llm-deploy
-```
-
-## 配置说明
+## 配置文件结构说明
Astron-xmod-shim 支持通过命令行参数和配置文件进行配置:
+[配置文件整体说明](deploy/docs/conf.md)
-### 命令行参数
-
-```bash
-./model-serve-shim --help
-
-Usage of model-serve-shim:
- --port int 服务监听端口 (默认: 8080)
- --config string 配置文件路径
- --shimlet string 默认加载的 shimlet 插件
- --goalset string 默认加载的 goalset 插件
- --plugin-dir string 插件目录路径
- --log-level string 日志级别 (debug, info, warn, error) (默认: "info")
-```
-
-### 配置文件
-
-配置文件采用 YAML 格式:
-
-```yaml
-# config.yaml
-service:
- port: 8080
- readTimeout: 30s
- writeTimeout: 30s
-
-plugins:
- defaultShimlet: k8s
- defaultGoalSet: opensource-llm-deploy
- pluginDir: ./plugins
- preload:
- - type: shimlet
- path: ./plugins/myshimlet.so
-
-logging:
- level: info
- format: text
- output: stdout
-```
## 贡献指南
diff --git a/api/route/route_test.go b/api/route/route_test.go
new file mode 100644
index 00000000..8be0d87b
--- /dev/null
+++ b/api/route/route_test.go
@@ -0,0 +1,108 @@
+package route
+
+import (
+ // 为自定义 http 包添加别名以避免命名冲突
+ xmodhttp "astron-xmod-shim/pkg/http"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/gin-gonic/gin"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+)
+
+// MockServer 模拟 HTTP 服务器
+// 注意:这个结构体现在只用于模拟,不会直接传递给 RegisterRoutes
+type MockServer struct {
+ mock.Mock
+ engine *gin.Engine
+}
+
+func (m *MockServer) GetEngine() *gin.Engine {
+ args := m.Called()
+ return args.Get(0).(*gin.Engine)
+}
+
+func (m *MockServer) Run() error {
+ args := m.Called()
+ return args.Error(0)
+}
+
+func TestRegisterRoutes(t *testing.T) {
+ // 设置测试环境
+ gin.SetMode(gin.TestMode)
+
+ // 创建一个符合 RegisterRoutes 参数要求的服务器
+ // 使用 NewServer 函数而不是直接初始化结构体
+ testServer := xmodhttp.NewServer(":8080")
+ // 获取引擎用于测试
+ engine := testServer.GetEngine()
+
+ // 创建一个模拟的 HTTP 服务器(仅用于验证调用)
+ mockServer := new(MockServer)
+ mockServer.On("GetEngine").Return(engine)
+
+ // 注册路由
+ RegisterRoutes(testServer)
+
+ // 验证路由是否被正确注册
+ // 创建测试请求来验证各个路由
+
+ // 测试部署路由
+ r1, _ := http.NewRequest("POST", "/api/v1/modserv/deploy", nil)
+ w1 := httptest.NewRecorder()
+ engine.ServeHTTP(w1, r1)
+ assert.NotEqual(t, http.StatusNotFound, w1.Code)
+
+ // 测试模型列表路由
+ r2, _ := http.NewRequest("GET", "/api/v1/modserv/list", nil)
+ w2 := httptest.NewRecorder()
+ engine.ServeHTTP(w2, r2)
+ assert.NotEqual(t, http.StatusNotFound, w2.Code)
+
+ // 测试获取服务状态路由
+ r3, _ := http.NewRequest("GET", "/api/v1/modserv/test-service-id", nil)
+ w3 := httptest.NewRecorder()
+ engine.ServeHTTP(w3, r3)
+ assert.NotEqual(t, http.StatusNotFound, w3.Code)
+
+ // 测试删除服务路由
+ r4, _ := http.NewRequest("DELETE", "/api/v1/modserv/test-service-id", nil)
+ w4 := httptest.NewRecorder()
+ engine.ServeHTTP(w4, r4)
+ assert.NotEqual(t, http.StatusNotFound, w4.Code)
+
+ // 测试更新服务路由
+ r5, _ := http.NewRequest("PUT", "/api/v1/modserv/test-service-id", nil)
+ w5 := httptest.NewRecorder()
+ engine.ServeHTTP(w5, r5)
+ assert.NotEqual(t, http.StatusNotFound, w5.Code)
+
+ // 测试指标路由
+ r6, _ := http.NewRequest("GET", "/api/v1/modserv/metrics", nil)
+ w6 := httptest.NewRecorder()
+ engine.ServeHTTP(w6, r6)
+ assert.NotEqual(t, http.StatusNotFound, w6.Code)
+}
+
+func TestRegisterRoutes_NonExistentRoute(t *testing.T) {
+ // 设置测试环境
+ gin.SetMode(gin.TestMode)
+
+ // 创建一个符合 RegisterRoutes 参数要求的服务器
+ testServer := xmodhttp.NewServer(":8080")
+ // 获取引擎用于测试
+ engine := testServer.GetEngine()
+
+ // 注册路由
+ RegisterRoutes(testServer)
+
+ // 测试不存在的路由
+ r, _ := http.NewRequest("GET", "/api/v1/non-existent-route", nil)
+ w := httptest.NewRecorder()
+ engine.ServeHTTP(w, r)
+
+ // 验证返回 404 状态码
+ assert.Equal(t, http.StatusNotFound, w.Code)
+}
\ No newline at end of file
diff --git a/deploy/docs/README.md b/deploy/docs/README.md
deleted file mode 100644
index 038df215..00000000
--- a/deploy/docs/README.md
+++ /dev/null
@@ -1,172 +0,0 @@
-# ModelServeShim
-
-## 一句话介绍
-极致轻量AI服务管控中间件,基于双插件化架构(`shimlet` 基础环境适配 + `pipeline` 部署流程扩展),原生内置集成`k8s-shimlet`(k8s环境支持) 与 `opensourcellm-pipeline`(开源模型部署流程)),支持跨环境部署与自定义流程,简化全生命周期管控。
-
-## 命名释义
-ModelServeShim(简称 astron-xmod-shim)由两部分构成:
-
-ModelServe:体现核心能力 —— 聚焦大模型(Model)的服务化部署与运维(Serve);
-Shim:源自技术术语 “适配层”,指通过抽象接口屏蔽底层环境差异,是实现跨环境统一管控的核心设计。
-
-## 核心特性
-| 特性分类 | 核心能力说明 | 关键价值 |
-|-------------------------|------------------------------------------------------------------------------|--------------------------------------------------------------------------|
-| 插件化跨环境适配架构 | 1. 基于 `shim` 抽象层定义标准化接口,通过 `shimlet` 插件实现环境适配
2. 已实现 `k8sshimlet`(深度对接 K8s Deployment/StatefulSet 资源)
3. 新增环境仅需开发专属 `shimlet`,核心逻辑与配置完全复用 | 一套管控逻辑覆盖多部署场景,环境扩展无需修改核心代码,开发成本显著降低 |
-| 可定制化部署流水线 | 1. 基于 `pipeline` 插件化设计,默认提供 `opensourcellm pipeline`(开源大模型部署流程)
2. 支持自定义 `pipeline` 替换默认流程,可新增量化、权限校验等个性化步骤
3. 流水线步骤支持配置重试策略与超时控制 | 兼顾开源模型快速部署与业务场景定制化需求,流程扩展灵活无侵入 |
-| 轻量架构与便捷部署 | 1. 单二进制文件交付(≈15MB),无外部依赖,解压即可启动
2. 支持插件热加载,新增 `shimlet`/`pipeline` 无需重启服务
3. 配置简洁,仅需指定环境插件与流程插件即可运行 | 部署门槛低,运维成本小,适配中小团队快速落地需求 |
-| 全链路状态可视与监控 | 1. FSM 状态机驱动,实时展示「初始化→流水线执行→环境部署→健康检查→运行中」全流转
2. 每个状态与步骤关联详细日志(操作人、耗时、参数)
3. 暴露 Prometheus 指标:部署成功率、资源使用率、流水线耗时等 | 状态可追溯,故障可快速定位,服务可用性全程可控 |
-
-
-## 技术架构
-采用“核心逻辑+双插件”解耦设计,兼顾稳定性与扩展性:
-
-
-
-## 快速上手(K8s + 开源LLM默认流水线)
-### 1. 环境准备
-- K8s 集群(v1.20+),已配置 GPU 调度(nvidia-device-plugin)
-- 本地 `kubectl` 可访问集群(配置 KUBECONFIG)
-
-### 2. 下载安装
-```bash
-# 下载单文件二进制(Linux x86_64)
-wget https://github.com/your-org/ModelServeShim/releases/latest/download/model-serve-shim
-chmod +x model-serve-shim
-
-# 验证安装(无依赖检查)
-./model-serve-shim --version
-# 输出示例:ModelServeShim v1.0.0 (commit: abc123)
-```
-
-### 3. 启动服务(加载默认插件)
-```bash
-# 启用 K8s shimlet 与开源LLM默认 pipeline
-./model-serve-shim --port=8080 \
- --shimlet=k8s \
- --pipeline=opensourcellm
-```
-
-### 4. 部署开源大模型(Llama-3-8B 示例)
-```bash
-curl -X POST http://localhost:8080/api/v1/modserv/deploy \
- -H "Content-Type: application/json" \
- -d '{
- "modelName": "llama-3-8b",
- "modelFile": "/models/llama-3-8b",
- "resourceRequirements": {
- "acceleratorType": "NVIDIA H20",
- "acceleratorCount": 1,
- "cpu": "4",
- "memory": "16Gi"
- },
- "replicaCount": 1
- }'
-
-# 响应示例(获取 serviceId 跟踪进度)
-{
- "code": 0,
- "data": {
- "serviceId": "llama-3-8b-123e4567-e89b-12d3-a456-426614174000",
- "currentStep": "model-validation",
- "totalSteps": ["model-validation", "config-rendering", "resource-deployment", "health-check"]
- }
-}
-```
-
-### 5. 查看部署状态与流水线进度
-```bash
-# 查看整体状态
-curl http://localhost:8080/api/v1/modserv/llama-3-8b-123e4567-e89b-12d3-a456-426614174000
-
-# 查看流水线详细执行日志
-curl http://localhost:8080/api/v1/modserv/llama-3-8b-123e4567-e89b-12d3-a456-426614174000/pipeline/logs
-```
-
-
-## 插件扩展示例
-### 1. 新增 shimlet(适配 Docker 环境)
-只需实现 `Shim` 抽象接口,即可接入新环境:
-``` go
-// dockershimlet 核心实现
-type DockerShimlet struct{}
-
-// 实现创建资源接口
-func (d *DockerShimlet) Create(ctx *deploy.Context) (string, error) {
- // 调用 Docker SDK 创建容器
- container, err := dockerClient.ContainerCreate(
- context.Background(),
- &container.Config{Image: ctx.ModelImage},
- &container.HostConfig{Resources: getDockerResources(ctx.Requirements)},
- nil, nil, ctx.ModelName)
- if err != nil {
- return "", fmt.Errorf("create docker container failed: %v", err)
- }
- // 启动容器
- return container.ID, dockerClient.ContainerStart(context.Background(), container.ID, types.ContainerStartOptions{})
-}
-
-// 实现查询状态接口
-func (d *DockerShimlet) Status(resourceID string) (deploy.Status, error) {
- // 查询 Docker 容器状态
- inspect, err := dockerClient.ContainerInspect(context.Background(), resourceID)
- if err != nil {
- return deploy.StatusFailed, err
- }
- if inspect.State.Running {
- return deploy.StatusRunning, nil
- }
- return deploy.StatusStopped, nil
-}
-```
-
-### 2. 自定义 pipeline(增加模型量化步骤)
-实现 `Pipeline` 接口,替换默认部署流程:
-``` go
-// 带量化步骤的自定义流水线
-type QuantLLMpipeline struct{}
-
-// 定义流水线步骤
-func (p *QuantLLMpipeline) Steps() []string {
- return []string{"model-validation", "model-quantization", "config-rendering", "resource-deployment", "health-check"}
-}
-
-// 实现步骤执行逻辑
-func (p *QuantLLMpipeline) RunStep(step string, ctx *pipeline.Context) error {
- switch step {
- case "model-quantization":
- // 调用量化工具(如 GGUF)处理模型
- return quantizeModel(ctx.ModelFile, ctx.QuantConfig)
- case "model-validation":
- return validateModel(ctx.ModelFile)
- // 实现其他步骤...
- default:
- return fmt.Errorf("unsupported step: %s", step)
- }
-}
-```
-
-
-## 常用 API 参考
-| 操作类型 | HTTP 方法 | 接口路径 | 说明 |
-|------------------|-----------|-----------------------------------|---------------------------------------|
-| 部署服务 | POST | `/api/v1/modserv/deploy` | 使用指定插件创建模型服务实例 |
-| 查询服务状态 | GET | `/api/v1/modserv/{serviceId}` | 查看服务整体状态与资源信息 |
-| 查询流水线进度 | GET | `/api/v1/modserv/{id}/pipeline` | 查看流水线步骤执行情况 |
-| 列出可用插件 | GET | `/api/v1/plugins` | 查看已加载的shimlet与pipeline |
-| 加载新插件 | POST | `/api/v1/plugins/load` | 热加载自定义插件(无需重启服务) |
-
-
-## 插件生态路线图
-| 插件类型 | 现有实现 | 规划扩展 |
-|----------------|-------------------------|---------------------------|
-| shimlet | k8sshimlet | dockershimlet、edgelet |
-| pipeline | opensourcellm pipeline | privatellm pipeline、quant-pipeline |
-
-## 🛠️ 代码规范
-
-本项目使用 [pre-commit](https://pre-commit.com) 自动检查代码风格,确保提交的代码格式统一。
-
-[](https://pre-commit.com/)
-## 许可证
-Apache License 2.0
\ No newline at end of file
diff --git a/deploy/docs/api.md b/deploy/docs/api.md
new file mode 100644
index 00000000..ccfb2dbc
--- /dev/null
+++ b/deploy/docs/api.md
@@ -0,0 +1,161 @@
+# 模型服务管理 API 文档
+
+## 1. 获取模型路径列表
+
+**请求方法**:`GET`
+**请求 URL**:`/api/v1/modserv/list`
+
+**响应体**:
+```json
+{
+ "code": 0,
+ "message": "success",
+ "data": [
+ {
+ "modelName": "Llama-3-8B",
+ "modelPath": "/models/llama-3-8b"
+ },
+ {
+ "modelName": "bge-Large",
+ "modelPath": "/models/bge-large"
+ },
+ {
+ "modelName": "xdeepseekv3",
+ "modelPath": "/models/xdeepseekv3"
+ }
+ ]
+}
+```
+
+> **说明**:
+> - `code`: `0` 表示成功,`1` 表示失败。
+> - `modelPath` 字段仅供调试使用,前端不应展示。
+
+---
+
+## 2. 部署新服务(创建服务)
+
+**请求方法**:`POST`
+**请求 URL**:`/api/v1/modserv/deploy`
+**请求头**:
+```http
+Content-Type: application/json
+```
+
+**请求体**:
+```json
+{
+ "modelName": "xdeepseekv3",
+ "resourceRequirements": {
+ "acceleratorCount": 8
+ },
+ "replicaCount": 1,
+ "contextLength": 1234
+}
+```
+
+**响应体**:
+```json
+{
+ "code": 0,
+ "message": "deploy submit success",
+ "data": {
+ "serviceId": "xdeepseekv3-"
+ }
+}
+```
+
+> **说明**:
+> - `replicaCount` 当前固定为 `1`,前端可预留字段。
+> - 成功后返回唯一 `serviceId`,用于后续操作。
+
+---
+
+## 3. 更新服务配置
+
+**请求方法**:`PUT`
+**请求 URL**:`/api/v1/modserv/{serviceId}`(例如:`/api/v1/modserv/xdeepseekv3-a1b2c3d4`)
+**请求头**:
+```http
+Content-Type: application/json
+```
+
+**请求体**:
+```json
+{
+ "modelName": "xdeepseekv3",
+ "resourceRequirements": {
+ "acceleratorCount": 2
+ },
+ "replicaCount": 1,
+ "contextLength": 1234
+}
+```
+
+**响应体**:
+```json
+{
+ "code": 0,
+ "message": "update submit success",
+ "data": {
+ "serviceId": "xdeepseekv3-"
+ }
+}
+```
+
+> **说明**:
+> - 通过 URL 中的 `serviceId` 定位要更新的服务。
+> - 更新操作为异步提交,实际生效可能有延迟。
+
+---
+
+## 4. 查看服务状态
+
+**请求方法**:`GET`
+**请求 URL**:`/api/v1/modserv/{serviceId}`
+
+**响应体**:
+```json
+{
+ "code": 0,
+ "message": "success",
+ "data": {
+ "serviceId": "xdeepseekv3-",
+ "modelName": "xdeepseekv3",
+ "status": "running",
+ "endpoint": "http://xxxx:xxxx/xx",
+ "updateTime": "2025-09-01 14:30"
+ }
+}
+```
+
+> **状态说明**:
+> - `running`:运行中
+> - `pending`:阻塞中(资源不足等)
+> - `failed`:部署失败
+> - `initializing`:初始化中
+> - `notExist`:服务不存在
+> - `terminating`:正在删除中
+
+---
+
+## 5. 删除服务
+
+**请求方法**:`DELETE`
+**请求 URL**:`/api/v1/modserv/{serviceId}`
+**请求体**:无
+
+**响应体**:
+```json
+{
+ "code": 0,
+ "message": "delete submit success",
+ "data": {
+ "serviceId": "xdeepseekv3-"
+ }
+}
+```
+
+> **说明**:
+> - 删除为异步操作,服务状态将变为 `terminating`。
+> - 资源释放可能需要一定时间。
diff --git a/deploy/docs/conf.md b/deploy/docs/conf.md
new file mode 100644
index 00000000..684ff09c
--- /dev/null
+++ b/deploy/docs/conf.md
@@ -0,0 +1,9 @@
+## 项目文件结构
+
+
+conf/
+├── base/
+│ └── conf.yaml # 核心配置文件
+└── shimlets/
+ ├── k8s-shimlet.yaml # Kubernetes shimlet 配置
+ └── kubeconfig # Kubernetes 集群连接配置
\ No newline at end of file
diff --git a/deploy/docs/goalset-demo.md b/deploy/docs/goalset-demo.md
new file mode 100644
index 00000000..b704f1c4
--- /dev/null
+++ b/deploy/docs/goalset-demo.md
@@ -0,0 +1,69 @@
+#### 步骤 1:定义 Goal
+
+```go
+package mygoalset
+
+import (
+ "astron-xmod-shim/internal/core/goal"
+ "astron-xmod-shim/pkg/log"
+)
+
+// 定义一个验证模型的 Goal
+var validateModel = goal.Goal{
+ Name: "validate-model",
+ IsAchieved: func(ctx *goal.Context) bool {
+ // 检查目标是否已达成
+ return ctx.DeploySpec.ModelName != ""
+ },
+ Ensure: func(ctx *goal.Context) error {
+ log.Info("开始验证模型: %s", ctx.DeploySpec.ModelName)
+ // 实现模型验证逻辑
+ return nil
+ },
+}
+
+// 定义一个准备资源的 Goal
+var prepareResources = goal.Goal{
+ Name: "prepare-resources",
+ IsAchieved: func(ctx *goal.Context) bool {
+ // 检查资源是否已准备好
+ // 这里可以检查模型文件、配置等是否存在
+ resourceReady, exists := ctx.Get("resourceReady").(bool)
+ return exists && resourceReady
+ },
+ Ensure: func(ctx *goal.Context) error {
+ log.Info("准备部署资源")
+ // 实现资源准备逻辑
+ // 准备完成后设置标记
+ ctx.Set("resourceReady", true)
+ return nil
+ },
+}
+```
+
+#### 步骤 2:创建并注册 GoalSet
+
+```go
+package mygoalset
+
+import (
+ "astron-xmod-shim/internal/core/goal"
+ "time"
+)
+
+// init 函数在插件加载时自动调用
+func init() {
+ // 使用 Builder 模式创建并注册自定义 GoalSet
+ newMyGoalSet()
+}
+
+// newMyGoalSet 创建自定义 GoalSet 实例
+func newMyGoalSet() {
+ goal.NewGoalSetBuilder("my-goalset").
+ AddGoal(validateModel).
+ AddGoal(prepareResources).
+ WithMaxRetries(3). // 失败最多重试 3 次
+ WithTimeout(2 * time.Minute). // 整体超时 2 分钟
+ BuildAndRegister()
+}
+```
\ No newline at end of file
diff --git "a/deploy/docs/modserv-shim \346\212\200\346\234\257\350\256\276\350\256\241\346\226\207\346\241\243.docx" "b/deploy/docs/modserv-shim \346\212\200\346\234\257\350\256\276\350\256\241\346\226\207\346\241\243.docx"
deleted file mode 100644
index dfd11c0a..00000000
Binary files "a/deploy/docs/modserv-shim \346\212\200\346\234\257\350\256\276\350\256\241\346\226\207\346\241\243.docx" and /dev/null differ
diff --git a/deploy/docs/shimlet-demo.md b/deploy/docs/shimlet-demo.md
new file mode 100644
index 00000000..424620c6
--- /dev/null
+++ b/deploy/docs/shimlet-demo.md
@@ -0,0 +1,102 @@
+除了内置的Kubernetes Shimlet外,开发者还可以实现Docker环境适配插件,将模型服务部署到Docker容器中。Docker Shimlet通过Docker
+API创建和管理容器,支持模型服务的完整生命周期管理。
+以下是实现 Docker 环境适配插件的示例代码,用于将模型服务部署到 Docker 容器中:
+
+#### 步骤 1:实现 Shimlet 接口
+
+```go
+package dockershimlet
+
+import (
+ "astron-xmod-shim/internal/core/shimlet"
+ dto "astron-xmod-shim/internal/dto/deploy"
+ "astron-xmod-shim/pkg/log"
+ // 导入 Docker SDK 相关包
+ // "github.com/docker/docker/client"
+)
+
+// DockerShimlet 实现 Docker 环境适配插件
+type DockerShimlet struct {
+ // 这里可以添加 Docker 客户端等成员变量
+ // client *client.Client
+}
+
+// 确保 DockerShimlet 实现了 Shimlet 接口(编译期检查)
+var _ shimlet.Shimlet = (*DockerShimlet)(nil)
+
+// InitWithConfig 初始化 Docker 客户端和配置
+func (d *DockerShimlet) InitWithConfig(confPath string) error {
+ // 实现 Docker 客户端初始化逻辑
+ // 1. 解析配置文件
+ // 2. 创建 Docker 客户端连接
+ // 3. 验证连接是否成功
+ log.Info("Initializing Docker shimlet with config: %s", confPath)
+ return nil
+}
+
+// Apply 应用部署规范,创建或更新 Docker 容器
+func (d *DockerShimlet) Apply(spec *dto.RequirementSpec) error {
+ // 实现 Docker 容器创建/更新逻辑
+ // 1. 根据 spec 构建容器配置(镜像、端口映射、卷挂载等)
+ // 2. 检查容器是否已存在
+ // 3. 存在则更新,不存在则创建新容器
+ log.Info("Applying deployment spec to Docker: %s", spec.ModelName)
+ return nil
+}
+
+// Delete 删除指定的 Docker 容器资源
+func (d *DockerShimlet) Delete(resourceID string) error {
+ // 实现 Docker 容器删除逻辑
+ // 1. 根据 resourceID 查找对应的容器
+ // 2. 停止并删除容器
+ log.Info("Deleting Docker resource: %s", resourceID)
+ return nil
+}
+
+// Status 查询 Docker 容器的运行状态
+func (d *DockerShimlet) Status(resourceID string) (*dto.RuntimeStatus, error) {
+ // 实现容器状态查询逻辑
+ // 1. 根据 resourceID 查找容器
+ // 2. 获取容器状态信息
+ // 3. 构建并返回 RuntimeStatus 对象
+ log.Info("Getting status for Docker resource: %s", resourceID)
+ return &dto.RuntimeStatus{}, nil
+}
+
+// ID 返回当前 Shimlet 的唯一标识符
+func (d *DockerShimlet) ID() string {
+ // 返回固定的标识符
+ return "docker"
+}
+
+// Description 返回当前 Shimlet 的描述信息
+func (d *DockerShimlet) Description() string {
+ // 返回描述文本
+ return "Docker环境适配插件,用于在Docker容器中部署模型服务"
+}
+
+// ListDeployedServices 列出所有已部署的服务
+func (d *DockerShimlet) ListDeployedServices() ([]string, error) {
+ // 实现服务列表查询逻辑
+ // 1. 列出所有与模型服务相关的容器
+ // 2. 提取并返回服务 ID 列表
+ log.Info("Listing all deployed services in Docker")
+ return []string{}, nil
+}
+```
+
+#### 步骤 2:注册 Docker Shimlet
+
+```go
+package dockershimlet
+
+import (
+ "astron-xmod-shim/internal/core/shimlet"
+)
+
+// init 函数在插件加载时自动调用
+func init() {
+ // 注册自定义的 Docker shimlet
+ shimlet.Registry.AutoRegister(&DockerShimlet{})
+}
+```
diff --git a/internal/dto/config/config_test.go b/internal/dto/config/config_test.go
new file mode 100644
index 00000000..928ce989
--- /dev/null
+++ b/internal/dto/config/config_test.go
@@ -0,0 +1,137 @@
+package dto
+
+import (
+ "encoding/json"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+// TestGlobalConfig 测试 GlobalConfig 结构体的基本功能
+func TestGlobalConfig(t *testing.T) {
+ // 准备测试数据
+ globalConfig := &GlobalConfig{
+ K8s: K8sConfig{
+ Kubeconfig: "/path/to/kubeconfig",
+ Context: "test-context",
+ QPS: 10.0,
+ Burst: 20,
+ Timeout: 30,
+ },
+ Server: Server{
+ Port: "8080",
+ },
+ Log: LogConfig{
+ Level: "info",
+ Path: "/var/log/app.log",
+ MaxSize: 100,
+ MaxAge: 7,
+ Compress: true,
+ ShowLine: true,
+ EnableConsole: true,
+ },
+ CurrentShimlet: "kubernetes",
+ Shimlets: map[string]ShimletConfig{
+ "kubernetes": {
+ ConfigPath: "/etc/kubernetes/config.yaml",
+ },
+ },
+ ModelManage: ModelManageConfig{
+ ModelRoot: "/models",
+ },
+ }
+
+ // 验证结构体字段值
+ assert.Equal(t, "/path/to/kubeconfig", globalConfig.K8s.Kubeconfig)
+ assert.Equal(t, "test-context", globalConfig.K8s.Context)
+ assert.Equal(t, float32(10.0), globalConfig.K8s.QPS)
+ assert.Equal(t, 20, globalConfig.K8s.Burst)
+ assert.Equal(t, int64(30), globalConfig.K8s.Timeout)
+ assert.Equal(t, "8080", globalConfig.Server.Port)
+ assert.Equal(t, "info", globalConfig.Log.Level)
+ assert.Equal(t, "/var/log/app.log", globalConfig.Log.Path)
+ assert.Equal(t, 100, globalConfig.Log.MaxSize)
+ assert.Equal(t, 7, globalConfig.Log.MaxAge)
+ assert.Equal(t, true, globalConfig.Log.Compress)
+ assert.Equal(t, true, globalConfig.Log.ShowLine)
+ assert.Equal(t, true, globalConfig.Log.EnableConsole)
+ assert.Equal(t, "kubernetes", globalConfig.CurrentShimlet)
+ assert.Equal(t, "/etc/kubernetes/config.yaml", globalConfig.Shimlets["kubernetes"].ConfigPath)
+ assert.Equal(t, "/models", globalConfig.ModelManage.ModelRoot)
+
+ // 测试 JSON 序列化和反序列化
+ jsonData, err := json.Marshal(globalConfig)
+ assert.NoError(t, err)
+ assert.NotEmpty(t, jsonData)
+
+ var unmarshaled GlobalConfig
+ err = json.Unmarshal(jsonData, &unmarshaled)
+ assert.NoError(t, err)
+ assert.Equal(t, globalConfig.K8s.Kubeconfig, unmarshaled.K8s.Kubeconfig)
+ assert.Equal(t, globalConfig.Server.Port, unmarshaled.Server.Port)
+}
+
+// TestK8sConfig 测试 K8sConfig 结构体的基本功能
+func TestK8sConfig(t *testing.T) {
+ k8sConfig := &K8sConfig{
+ Kubeconfig: "/another/path/to/kubeconfig",
+ Context: "another-context",
+ QPS: 5.0,
+ Burst: 10,
+ Timeout: 15,
+ }
+
+ assert.Equal(t, "/another/path/to/kubeconfig", k8sConfig.Kubeconfig)
+ assert.Equal(t, "another-context", k8sConfig.Context)
+ assert.Equal(t, float32(5.0), k8sConfig.QPS)
+ assert.Equal(t, 10, k8sConfig.Burst)
+ assert.Equal(t, int64(15), k8sConfig.Timeout)
+}
+
+// TestServerConfig 测试 Server 结构体的基本功能
+func TestServerConfig(t *testing.T) {
+ server := &Server{
+ Port: "9090",
+ }
+
+ assert.Equal(t, "9090", server.Port)
+}
+
+// TestLogConfig 测试 LogConfig 结构体的基本功能
+func TestLogConfig(t *testing.T) {
+ logConfig := &LogConfig{
+ Level: "debug",
+ Path: "/var/log/test.log",
+ MaxSize: 50,
+ MaxAge: 3,
+ Compress: false,
+ ShowLine: false,
+ EnableConsole: false,
+ }
+
+ assert.Equal(t, "debug", logConfig.Level)
+ assert.Equal(t, "/var/log/test.log", logConfig.Path)
+ assert.Equal(t, 50, logConfig.MaxSize)
+ assert.Equal(t, 3, logConfig.MaxAge)
+ assert.Equal(t, false, logConfig.Compress)
+ assert.Equal(t, false, logConfig.ShowLine)
+ assert.Equal(t, false, logConfig.EnableConsole)
+}
+
+// TestShimletConfig 测试 ShimletConfig 结构体的基本功能
+func TestShimletConfig(t *testing.T) {
+ shimletConfig := &ShimletConfig{
+ ConfigPath: "/etc/shimlet/config.yaml",
+ }
+
+ assert.Equal(t, "/etc/shimlet/config.yaml", shimletConfig.ConfigPath)
+}
+
+// TestModelManageConfig 测试 ModelManageConfig 结构体的基本功能
+func TestModelManageConfig(t *testing.T) {
+ modelManageConfig := &ModelManageConfig{
+ ModelRoot: "/test/models",
+ }
+
+ assert.Equal(t, "/test/models", modelManageConfig.ModelRoot)
+}