github.com/qiniu/go-sdk/v7@v7.27.0/examples/sandbox_templates/main.go (about) 1 package main 2 3 import ( 4 "context" 5 "fmt" 6 "log" 7 "os" 8 "time" 9 10 "github.com/qiniu/go-sdk/v7/sandbox" 11 ) 12 13 func main() { 14 apiKey := os.Getenv("QINIU_API_KEY") 15 if apiKey == "" { 16 log.Fatal("请设置 QINIU_API_KEY 环境变量") 17 } 18 19 apiURL := os.Getenv("QINIU_SANDBOX_API_URL") 20 21 c, err := sandbox.NewClient(&sandbox.Config{ 22 APIKey: apiKey, 23 Endpoint: apiURL, 24 }) 25 if err != nil { 26 log.Fatalf("创建客户端失败: %v", err) 27 } 28 29 ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second) 30 defer cancel() 31 32 // 1. 列出默认模板 33 fmt.Println("=== 列出默认模板 ===") 34 defaultTemplates, err := c.ListDefaultTemplates(ctx) 35 if err != nil { 36 log.Fatalf("列出默认模板失败: %v", err) 37 } 38 fmt.Printf("共 %d 个默认模板:\n", len(defaultTemplates)) 39 for _, tmpl := range defaultTemplates { 40 fmt.Printf(" - %s (名称: %v, 构建状态: %s)\n", 41 tmpl.TemplateID, tmpl.Names, tmpl.BuildStatus) 42 } 43 44 // 2. 列出所有模板 45 fmt.Println("\n=== 列出模板 ===") 46 templates, err := c.ListTemplates(ctx, nil) 47 if err != nil { 48 log.Fatalf("列出模板失败: %v", err) 49 } 50 fmt.Printf("共 %d 个模板:\n", len(templates)) 51 for _, tmpl := range templates { 52 names := "-" 53 if len(tmpl.Names) > 0 { 54 names = fmt.Sprintf("%v", tmpl.Names) 55 } 56 aliases := "-" 57 if len(tmpl.Aliases) > 0 { 58 aliases = fmt.Sprintf("%v", tmpl.Aliases) 59 } 60 fmt.Printf(" - %s\n", tmpl.TemplateID) 61 fmt.Printf(" 名称: %s, 旧别名: %s, 公开: %v\n", names, aliases, tmpl.Public) 62 fmt.Printf(" CPU: %d 核, 内存: %d MB, 磁盘: %d MB, envd: %s\n", 63 tmpl.CPUCount, tmpl.MemoryMB, tmpl.DiskSizeMB, tmpl.EnvdVersion) 64 fmt.Printf(" 构建状态: %s, 构建次数: %d, 使用次数: %d\n", 65 tmpl.BuildStatus, tmpl.BuildCount, tmpl.SpawnCount) 66 fmt.Printf(" 创建时间: %s, 更新时间: %s\n", 67 tmpl.CreatedAt.Format(time.RFC3339), tmpl.UpdatedAt.Format(time.RFC3339)) 68 } 69 70 // 3. 获取单个模板详情 71 if len(templates) > 0 { 72 fmt.Println("\n=== 获取模板详情 ===") 73 detail, err := c.GetTemplate(ctx, templates[0].TemplateID, nil) 74 if err != nil { 75 log.Fatalf("获取模板详情失败: %v", err) 76 } 77 fmt.Printf("模板: %s, 名称: %v, 当前用户拥有: %v, 构建数: %d\n", 78 detail.TemplateID, detail.Names, detail.IsOwner, len(detail.Builds)) 79 for i, build := range detail.Builds { 80 if i >= 3 { 81 fmt.Printf(" ... 省略 %d 条\n", len(detail.Builds)-3) 82 break 83 } 84 fmt.Printf(" - %s (状态: %s, CPU: %d, 内存: %d MB)\n", 85 build.BuildID, build.Status, build.CPUCount, build.MemoryMB) 86 } 87 } 88 89 // 模板创建和构建会消耗云端资源,默认只运行上面的只读示例。 90 // 如需继续验证写操作,请显式设置 QINIU_SANDBOX_TEMPLATE_MUTATION_EXAMPLE=true。 91 if os.Getenv("QINIU_SANDBOX_TEMPLATE_MUTATION_EXAMPLE") != "true" { 92 fmt.Println("\n未启用模板写操作示例,跳过创建、构建和删除流程") 93 return 94 } 95 96 // 4. 创建模板 97 fmt.Println("\n=== 创建模板 ===") 98 cpuCount := int32(2) 99 memoryMB := int32(512) 100 templateName := "sdk-example-template" 101 resp, err := c.CreateTemplate(ctx, sandbox.CreateTemplateParams{ 102 Name: &templateName, 103 CPUCount: &cpuCount, 104 MemoryMB: &memoryMB, 105 }) 106 if err != nil { 107 log.Fatalf("创建模板失败: %v", err) 108 } 109 templateID := resp.TemplateID 110 buildID := resp.BuildID 111 fmt.Printf("模板已创建: %s (构建: %s)\n", templateID, buildID) 112 113 // 确保测试结束时清理 114 defer func() { 115 fmt.Println("\n=== 删除模板 ===") 116 if err := c.DeleteTemplate(context.Background(), templateID); err != nil { 117 fmt.Printf("删除模板失败: %v\n", err) 118 } else { 119 fmt.Printf("模板 %s 已删除\n", templateID) 120 } 121 }() 122 123 // 5. 更新模板 124 fmt.Println("\n=== 更新模板 ===") 125 public := true 126 if err := c.UpdateTemplate(ctx, templateID, sandbox.UpdateTemplateParams{ 127 Public: &public, 128 }); err != nil { 129 log.Fatalf("更新模板失败: %v", err) 130 } 131 fmt.Println("模板已更新为公开") 132 133 // 6. 获取构建状态 134 fmt.Println("\n=== 获取构建状态 ===") 135 buildInfo, err := c.GetTemplateBuildStatus(ctx, templateID, buildID, nil) 136 if err != nil { 137 fmt.Printf("获取构建状态失败: %v\n", err) 138 } else { 139 fmt.Printf("构建 %s: 状态=%s, 模板=%s\n", buildInfo.BuildID, buildInfo.Status, buildInfo.TemplateID) 140 } 141 142 // 7. 获取构建日志 143 fmt.Println("\n=== 获取构建日志 ===") 144 buildLogs, err := c.GetTemplateBuildLogs(ctx, templateID, buildID, nil) 145 if err != nil { 146 fmt.Printf("获取构建日志失败: %v\n", err) 147 } else { 148 fmt.Printf("构建日志 (%d 条):\n", len(buildLogs.Logs)) 149 for i, entry := range buildLogs.Logs { 150 if i >= 5 { 151 fmt.Printf(" ... 省略 %d 条\n", len(buildLogs.Logs)-5) 152 break 153 } 154 step := "-" 155 if entry.Step != nil { 156 step = *entry.Step 157 } 158 fmt.Printf(" [%s] [%s] %s: %s\n", 159 entry.Timestamp.Format(time.RFC3339), entry.Level, step, entry.Message) 160 } 161 } 162 163 // 8. 分配模板标签(AssignTemplateTags) 164 fmt.Println("\n=== 分配模板标签 ===") 165 tagResult, err := c.AssignTemplateTags(ctx, sandbox.ManageTagsParams{ 166 Target: fmt.Sprintf("%s:%s", templateName, "v1"), 167 Tags: []string{"latest", "stable"}, 168 }) 169 if err != nil { 170 fmt.Printf("管理模板标签失败: %v\n", err) 171 } else { 172 fmt.Printf("标签已分配, 构建: %s, 标签: %v\n", tagResult.BuildID, tagResult.Tags) 173 } 174 175 // 9. 删除模板标签(DeleteTemplateTags) 176 fmt.Println("\n=== 删除模板标签 ===") 177 if err := c.DeleteTemplateTags(ctx, sandbox.DeleteTagsParams{ 178 Name: templateName, 179 Tags: []string{"stable"}, 180 }); err != nil { 181 fmt.Printf("删除模板标签失败: %v\n", err) 182 } else { 183 fmt.Println("标签 'stable' 已删除") 184 } 185 186 // 10. 通过别名查找模板(GetTemplateByAlias) 187 fmt.Println("\n=== 通过别名查找模板 ===") 188 if len(templates) > 0 && len(templates[0].Aliases) > 0 { 189 alias := templates[0].Aliases[0] 190 aliasResp, err := c.GetTemplateByAlias(ctx, alias) 191 if err != nil { 192 fmt.Printf("通过别名查找模板失败: %v\n", err) 193 } else { 194 fmt.Printf("别名 '%s' -> 模板: %s (公开: %v)\n", alias, aliasResp.TemplateID, aliasResp.Public) 195 } 196 } else { 197 fmt.Println("没有可用的模板别名,跳过") 198 } 199 200 // 11. 获取模板文件上传链接(GetTemplateFiles) 201 fmt.Println("\n=== 获取模板文件上传链接 ===") 202 fileUpload, err := c.GetTemplateFiles(ctx, templateID, "example-hash-value") 203 if err != nil { 204 fmt.Printf("获取文件上传链接失败: %v\n", err) 205 } else { 206 fmt.Printf("文件是否已存在: %v, 已获得上传地址: %v\n", fileUpload.Present, fileUpload.URL != nil) 207 } 208 209 // 12. 启动模板构建(StartTemplateBuild) 210 fmt.Println("\n=== 启动模板构建 ===") 211 fromImage := "ubuntu:latest" 212 if err := c.StartTemplateBuild(ctx, templateID, buildID, sandbox.StartTemplateBuildParams{ 213 FromImage: &fromImage, 214 }); err != nil { 215 fmt.Printf("启动构建失败(可能已在构建中): %v\n", err) 216 } else { 217 fmt.Println("构建已启动") 218 } 219 220 // 13. 等待构建完成(WaitForBuild) 221 fmt.Println("\n=== 等待构建完成 ===") 222 finalBuild, err := c.WaitForBuild(ctx, templateID, buildID, sandbox.WithPollInterval(3*time.Second)) 223 if err != nil { 224 fmt.Printf("等待构建完成失败: %v\n", err) 225 } else { 226 fmt.Printf("构建已完成: %s (状态: %s)\n", finalBuild.BuildID, finalBuild.Status) 227 } 228 229 // 14. 删除模板(通过 defer 执行) 230 }