分享与复制
模板有两个标识符,它们回答的是不同的问题。
| 标识符 | 形态 | 何时变化 | 回答的问题 |
|---|---|---|---|
id | 一个 UUID | 从不变化 | “这是哪一行模板?” |
hash_id | th_ 加上一段十六进制摘要 | 启动配方变化时 | “这具体是哪一份配方?” |
id 是那一行记录。hash_id 是决定实际启动什么的那些字段的内容哈希,所以两个配方完全相同的模板仍然会得到不同的哈希——行本身的标识也被折进去了——而同一行记录在经历外观性修改后哈希保持不变。
哈希涵盖哪些内容
| 在哈希内 | 不在哈希内 |
|---|---|
image、tag、repo | name、description |
launch_mode、args_str、onstart | readme、链接 |
env、ports、constraints | visibility、排序 |
jupyter_dir、use_jupyter_lab | 私有镜像仓库密码 |
registry_user | use_count、时间戳 |
重命名模板、重写它的 readme、把它从私有翻成公开:哈希纹丝不动。改一个端口、一个环境变量条目、启动脚本或者镜像:哈希当场重新生成。
旧哈希不再属于任何模板,因此用它拼出来的固定链接会返回 TEMPLATE_NOT_FOUND。修改配方之后,重新复制固定链接并重新发送。
分享
模板卡片或详情页上的分享提供两个链接。
| 链接 | 形态 | 行为 |
|---|---|---|
| 引荐链接 | /templates?t=<id> | 跟随模板。接收者始终看到你最新的修改。 |
| 固定链接 | /templates?h=<hash_id> | 指定唯一一份确切的配方,一旦你改动它就无法再解析。 |
两者都会在接收者的模板库中打开模板详情页,从那里他们可以启动或复制它。两者本身都不授予访问权:接收者必须原本就能看到这个模板。也就是说,必须是 system 模板、public 模板,或者是他们所属组织拥有的模板。把私有模板的链接发给组织外的人,他们只会得到 404。
按哈希查找模板
固定链接只是对一个端点的包装:
curl "$SUPERHEAT_API/v1/templates/by-hash/th_9f2c…" \
-H "Authorization: Bearer $SUPERHEAT_KEY"
它返回与 GET /v1/templates/{id} 相同的对象,遵循相同的可见性规则和相同的私密值遮蔽;当哈希匹配不到任何你能看到的模板时,返回 404 TEMPLATE_NOT_FOUND。
这是可复现性的工具。把 hash_id 与一次训练一起记录下来,之后查找要么返回你当时用的那份确切配方,要么告诉你它已经变了——这比无声地递给你一个不同的环境有用得多。
复制
复制是你在无法编辑的模板之上继续构建的方式:精选的 system 模板,或者别的组织的公开模板。
curl -X POST "$SUPERHEAT_API/v1/templates/$TEMPLATE_ID/duplicate" \
-H "Authorization: Bearer $SUPERHEAT_KEY"
副本会立即创建,并且:
- 属于你当前的组织,记录你为创建者
- 无论来源是什么,永远是
private - 命名为
<source name> (copy),若该名称已被占用则是(copy 2)、(copy 3)依此类推 - 带有新的
id和新的hash_id,启动次数从零开始 - 原封不动地复制镜像、启动模式、参数、启动脚本、端口和约束
当来源不是你的时,有两样东西是有意不复制的:
| 不复制的内容 | 原因 |
|---|---|
| 私密环境值 | 你从来没有读取它们的权限;副本中的这些值为空,secret 标志保持不变。 |
| 私有镜像仓库的用户名和密码 | 同样的原因。请在副本上重新填入你自己的凭据。 |
复制你的组织已经拥有的模板则两者都保留,因为并没有泄露任何新东西。
常见工作流
- 找一个和你想要的比较接近的精选模板。
- 复制它。
- 编辑副本——改镜像标签、加端口、写启动脚本。
- 启动它,确认能用,然后把固定链接分享给你的团队。
- 当你修改配方时,重新分享链接。
删除模板不影响已经由它部署出来的实例,除了模板库里的条目和它的链接之外,也不会让任何东西失效。