模板管理
通过 Go SDK 进行模板的创建、查询、构建、标签管理和删除操作。模板是预构建的沙箱环境定义,包含基础镜像、依赖、文件和启动命令,实现亚秒级启动。
前置条件:请先完成客户端初始化。
列出模板
templates, err := c.ListTemplates(ctx, nil)
if err != nil {
log.Fatalf("列出模板失败: %v", err)
}
for _, tmpl := range templates {
fmt.Printf("ID: %s, 别名: %v, 公开: %v\n", tmpl.TemplateID, tmpl.Aliases, tmpl.Public)
fmt.Printf(" CPU: %d 核, 内存: %d MB, 磁盘: %d MB\n", tmpl.CPUCount, tmpl.MemoryMB, tmpl.DiskSizeMB)
fmt.Printf(" 构建状态: %s, 使用次数: %d\n", tmpl.BuildStatus, tmpl.SpawnCount)
}
Template 包含以下字段:
| 字段 | 类型 | 说明 |
|---|---|---|
TemplateID |
string |
模板 ID |
Aliases |
[]string |
别名列表 |
BuildID |
string |
当前构建 ID |
BuildStatus |
TemplateBuildStatus |
构建状态 |
BuildCount |
int32 |
构建次数 |
CPUCount |
int32 |
CPU 核数 |
MemoryMB |
int32 |
内存大小(MiB) |
DiskSizeMB |
int32 |
磁盘大小(MiB) |
Public |
bool |
是否公开 |
SpawnCount |
int64 |
使用次数 |
CreatedAt |
time.Time |
创建时间 |
UpdatedAt |
time.Time |
更新时间 |
获取模板详情
返回模板信息及其构建记录。
detail, err := c.GetTemplate(ctx, templateID, nil)
if err != nil {
log.Fatalf("获取模板详情失败: %v", err)
}
fmt.Printf("模板: %s, 构建数: %d\n", detail.TemplateID, len(detail.Builds))
for _, build := range detail.Builds {
fmt.Printf(" 构建 %s: 状态=%s, CPU=%d, 内存=%d MB\n",
build.BuildID, build.Status, build.CPUCount, build.MemoryMB)
}
支持分页查询:
limit := int32(5)
detail, err := c.GetTemplate(ctx, templateID, &sandbox.GetTemplateParams{
Limit: &limit,
})
创建模板
cpuCount := int32(2)
memoryMB := int32(512)
name := "my-template"
resp, err := c.CreateTemplate(ctx, sandbox.CreateTemplateParams{
Name: &name,
CPUCount: &cpuCount,
MemoryMB: &memoryMB,
})
if err != nil {
log.Fatalf("创建模板失败: %v", err)
}
fmt.Printf("模板已创建: %s (构建 ID: %s)\n", resp.TemplateID, resp.BuildID)
CreateTemplateParams 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
Name |
*string |
否 | 模板名称,可包含标签(如 my-template:v1) |
CPUCount |
*int32 |
否 | CPU 核数 |
MemoryMB |
*int32 |
否 | 内存大小(MiB) |
Tags |
*[]string |
否 | 构建标签列表 |
更新模板
public := true
if err := c.UpdateTemplate(ctx, templateID, sandbox.UpdateTemplateParams{
Public: &public,
}); err != nil {
log.Fatalf("更新模板失败: %v", err)
}
fmt.Println("模板已更新为公开")
删除模板
if err := c.DeleteTemplate(ctx, templateID); err != nil {
log.Fatalf("删除模板失败: %v", err)
}
fmt.Printf("模板 %s 已删除\n", templateID)
模板构建
启动构建
fromImage := "ubuntu:latest"
if err := c.StartTemplateBuild(ctx, templateID, buildID, sandbox.StartTemplateBuildParams{
FromImage: &fromImage,
}); err != nil {
log.Fatalf("启动构建失败: %v", err)
}
StartTemplateBuildParams 参数:
| 参数 | 类型 | 说明 |
|---|---|---|
Force |
*bool |
是否强制完整构建(忽略缓存) |
FromImage |
*string |
基础镜像 |
FromTemplate |
*string |
基础模板 |
StartCmd |
*string |
启动命令 |
ReadyCmd |
*string |
就绪检查命令 |
Steps |
*[]TemplateStep |
构建步骤列表 |
TemplateStep 字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
Type |
string |
是 | 步骤类型 |
Args |
*[]string |
否 | 步骤参数 |
FilesHash |
*string |
否 | 步骤中使用文件的哈希值 |
Force |
*bool |
否 | 是否强制执行(忽略缓存) |
等待构建完成
finalBuild, err := c.WaitForBuild(ctx, templateID, buildID,
sandbox.WithPollInterval(3*time.Second),
)
if err != nil {
log.Fatalf("构建失败: %v", err)
}
fmt.Printf("构建完成: %s (状态: %s)\n", finalBuild.BuildID, finalBuild.Status)
获取构建状态
buildInfo, err := c.GetTemplateBuildStatus(ctx, templateID, buildID, nil)
if err != nil {
log.Fatalf("获取构建状态失败: %v", err)
}
fmt.Printf("构建 %s: 状态=%s\n", buildInfo.BuildID, buildInfo.Status)
构建状态:
| 状态 | 说明 |
|---|---|
building |
构建中 |
waiting |
等待中 |
uploaded |
已上传 |
ready |
构建成功 |
error |
构建失败 |
获取构建日志
buildLogs, err := c.GetTemplateBuildLogs(ctx, templateID, buildID, nil)
if err != nil {
log.Fatalf("获取构建日志失败: %v", err)
}
for _, entry := range buildLogs.Logs {
step := ""
if entry.Step != nil {
step = *entry.Step
}
fmt.Printf("[%s] [%s] %s: %s\n", entry.Timestamp.Format(time.RFC3339), entry.Level, step, entry.Message)
}
支持过滤参数:
level := sandbox.LogLevelError
limit := int32(50)
buildLogs, err := c.GetTemplateBuildLogs(ctx, templateID, buildID, &sandbox.GetBuildLogsParams{
Level: &level,
Limit: &limit,
})
获取文件上传链接
构建过程中,可以获取文件上传链接。
upload, err := c.GetTemplateFiles(ctx, templateID, fileHash)
if err != nil {
log.Fatalf("获取上传链接失败: %v", err)
}
if upload.Present {
fmt.Println("文件已存在,无需上传")
} else {
fmt.Printf("上传地址: %s\n", *upload.URL)
}
标签管理
分配标签
将标签分配给指定的模板构建。
tagResult, err := c.AssignTemplateTags(ctx, sandbox.ManageTagsParams{
Target: "my-template:v1",
Tags: []string{"latest", "stable"},
})
if err != nil {
log.Fatalf("分配标签失败: %v", err)
}
fmt.Printf("标签已分配, 构建: %s, 标签: %v\n", tagResult.BuildID, tagResult.Tags)
删除标签
if err := c.DeleteTemplateTags(ctx, sandbox.DeleteTagsParams{
Name: "my-template",
Tags: []string{"stable"},
}); err != nil {
log.Fatalf("删除标签失败: %v", err)
}
fmt.Println("标签已删除")
通过别名查找模板
resp, err := c.GetTemplateByAlias(ctx, "my-template")
if err != nil {
log.Fatalf("查找模板失败: %v", err)
}
fmt.Printf("模板 ID: %s, 公开: %v\n", resp.TemplateID, resp.Public)
完整示例
package main
import (
"context"
"fmt"
"log"
"os"
"time"
"github.com/qiniu/go-sdk/v7/sandbox"
)
func main() {
c, err := sandbox.NewClient(&sandbox.Config{
APIKey: os.Getenv("QINIU_API_KEY"),
Endpoint: os.Getenv("QINIU_SANDBOX_API_URL"),
})
if err != nil {
log.Fatalf("创建客户端失败: %v", err)
}
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
defer cancel()
// 列出所有模板
templates, err := c.ListTemplates(ctx, nil)
if err != nil {
log.Fatalf("列出模板失败: %v", err)
}
fmt.Printf("共 %d 个模板\n", len(templates))
for _, tmpl := range templates {
fmt.Printf(" %s (CPU: %d, 内存: %d MiB, 状态: %s)\n",
tmpl.TemplateID, tmpl.CPUCount, tmpl.MemoryMB, tmpl.BuildStatus)
}
// 创建模板
cpuCount := int32(2)
memoryMB := int32(512)
name := "sdk-example-template"
resp, err := c.CreateTemplate(ctx, sandbox.CreateTemplateParams{
Name: &name,
CPUCount: &cpuCount,
MemoryMB: &memoryMB,
})
if err != nil {
log.Fatalf("创建模板失败: %v", err)
}
templateID := resp.TemplateID
buildID := resp.BuildID
fmt.Printf("模板已创建: %s (构建: %s)\n", templateID, buildID)
// 清理(defer 在 templateID 赋值之后注册,确保参数值正确)
defer c.DeleteTemplate(context.Background(), templateID)
// 启动构建
fromImage := "ubuntu:latest"
c.StartTemplateBuild(ctx, templateID, buildID, sandbox.StartTemplateBuildParams{
FromImage: &fromImage,
})
// 等待构建完成
finalBuild, err := c.WaitForBuild(ctx, templateID, buildID,
sandbox.WithPollInterval(3*time.Second),
)
if err != nil {
fmt.Printf("构建失败: %v\n", err)
} else {
fmt.Printf("构建完成: %s (状态: %s)\n", finalBuild.BuildID, finalBuild.Status)
}
// 分配标签
c.AssignTemplateTags(ctx, sandbox.ManageTagsParams{
Target: fmt.Sprintf("%s:%s", name, "v1"),
Tags: []string{"latest"},
})
// 删除标签
c.DeleteTemplateTags(ctx, sandbox.DeleteTagsParams{
Name: name,
Tags: []string{"latest"},
})
}
文档反馈
(如有产品使用问题,请 提交工单)