标签

本文档旨在提供关于如何在 OpenStack REST API 中使用标签的指导。

标签经常与元数据混淆。虽然两者之间存在交集,但标签的主要功能是将实体集合分组分类,而元数据用于向实体附加额外信息。存在一份关于元数据的独立指南文档。

有关此处引用的 REST 指南的背景信息,请参阅关于 命名约定HTTP 指南 的主题文档。

标签表示

标签是附加到实体的字符串,用于将其分类到组中。

一个实体可以具有零个、一个或多个与之关联的标签,因此在父实体中推荐的表示形式是列表。

使用服务器资源作为示例请求

GET /servers/1234567890

响应

{
    'id': '1234567890',

    ... other server resource properties ...

    'tags': ['foo', 'bar', 'baz']
}

标签的更新按照标准的 HTTP 请求方法进行,直接针对父资源发出。要更新资源的标签列表,应向该资源发送一个 PUT 请求,其中包含更新后的标签列表以及完整的资源表示形式在请求体中。在这种情况下,更新不必仅限于标签,其他属性也可以同时更新。请注意,通过使用 PUT 请求,可以一次性添加和/或删除多个标签,只需将更新后的标签列表与资源表示形式一起发送即可。

对于表示形式不是 JSON 的资源,必须创建一个单独的端点来公开标签。有关更多信息,请参阅下面的“标签资源 URL”部分。

标签限制

标签是具有以下基本限制的字符串

  • 标签区分大小写。

  • ‘/’ 不允许出现在标签名称中

  • 逗号不允许出现在标签名称中,以便简化指定标签列表的请求

  • 所有其他字符都允许出现在标签名称中

注意

禁止使用‘/’字符,因为某些服务器在编码此字符时存在问题。问题在于服务器会将‘%2F’作为‘/’处理,即使‘/’已被编码。这是服务器实现不佳的问题。为了避免处理 URL 字符的问题,标签名称中禁止使用‘/’字符。

标签的字符编码

根据 RFC 7159#section-8.1,JSON 文档应以 UTF-8、UTF-16 或 UTF-32 编码,其中 UTF-8 是默认编码,也是为了最大程度的互操作性而推荐的编码。

由于标签是 JSON 文档的一部分,因此标签名称的编码必须与父文档的编码匹配。强烈建议使用 UTF-8 编码。

标签资源 URL

有时,使用完整的资源表示形式处理资源的标签部分可能不方便,因此标签也可以选择作为独立资源公开。如果项目决定提供此功能,则标签管理的根资源 URL 应为属于标签的资源的 URL,后跟 /tags(对于使用用户生成 URL 且组件数量不同的 API,tags/ URL 组件可以作为前缀而不是后缀添加)。

例如,由 URL http://example.com:8774/servers/1234567890 标识的资源必须使用根 URL http://example.com:8774/servers/1234567890/tags 公开其标签。

获取标签列表

要获取资源的标签,必须向根标签 URL 发送一个 GET 请求。成功后,服务器将以 200 状态码和响应体中的完整标签项集进行响应。

示例请求

GET /servers/1234567890/tags

响应

{
    "tags": ['foo', 'bar', 'baz']
}

请注意,此表示形式与 Nova 采用的表示形式不同。原因之一是,使用这种结构可以向请求体添加其他元数据。第二个原因是,发现 JSON 数组作为顶级实体会暴露浏览器中的漏洞,如以下文章所述

修改标签列表

要添加、删除或更改标签,应向根标签 URL 发送一个 PUT 请求,并在请求体中包含更新后的完整标签列表。成功后,服务器将以 200 状态码和响应体中的完整更新后的标签列表进行响应。

示例请求(删除“bar”并添加“qux”)

PUT /servers/1234567890/tags
{
    "tags": ['foo', 'baz', 'qux']
}

响应

{
    "tags": ['foo', 'baz', 'qux']
}

如果标签数量超过 API 允许的限制,则返回码应为 400 Bad Request,如 HTTP 指南所述。为了成功完成请求,客户端应将请求的标签数量更改为低于 API 限制。

删除标签

要删除与资源关联的整个标签列表,必须向根标签 URL 发送一个 DELETE 请求。成功后,服务器将以 204 状态码进行响应。

示例请求

DELETE /servers/1234567890/tags

解决单个标签

为了提供对标签更细粒度的访问,另一个可选的扩展是公开单个标签的资源 URL。如果项目决定实施此选项,则应通过将标签名称附加到根标签 URL 来单独访问每个标签。请注意,此选项不适用于使用用户生成 URL 的 API。

要插入单个标签而无需发送整个标签列表,客户端应向单个标签 URL 发送一个 PUT 请求。成功后,服务器将以 201 状态码进行响应,并在响应的 Location 标头中包含新标签的 URL。

示例请求

PUT /servers/1234567890/tags/qux
<no body>

响应

Location: http://example.com:8774/servers/1234567890/tags/qux
<no body>

要检查标签是否存在,客户端应向单个标签 URL 发送一个 HEAD 请求。如果标签存在,服务器将以状态码 204 和没有响应体进行响应。如果标签不存在,服务器将以状态码 404 进行响应。

要删除单个标签而不影响其余标签,将向单个标签 URL 发送一个 DELETE 请求。成功后,服务器将以 204 状态码进行响应。如果给出了无效的标签,则返回 404 响应。

示例请求

DELETE /servers/1234567890/tags/qux

按标签过滤和搜索

要按其标签搜索实体集合,客户端应向集合 URL 发送一个 GET 请求,并包含定义查询的查询字符串参数。这些参数可以与其他参数结合使用,例如执行标签之外的其他过滤、分页、排序等。推荐的用于过滤标签的查询字符串参数是 tagstags-anynot-tagsnot-tags-any

请注意,这与 nova 规范不同,nova 规范使用重复的 tag 查询参数来指定标签列表。这里的偏好是与排序指南文档保持一致,其中决定重复查询字符串参数不是一个好主意,因为网络客户端和服务器对它的支持不好。

要请求具有单个标签的实体列表,应将 tags 参数设置为所需的标签名称。示例

GET /servers?tags=red

要请求具有两个或多个标签的实体列表,应将 tags 参数设置为用逗号分隔的标签列表。在这种情况下,必须同时存在所有给定的标签,实体才能包含在查询结果中。示例,返回具有“red”和“blue”标签的服务器

GET /servers?tags=red,blue

要请求具有列表中一个或多个标签的实体列表,应将 tags-any 参数设置为用逗号分隔的标签列表。在这种情况下,只要存在一个给定的标签,实体就会包含在查询结果中。示例,返回具有“red”或“blue”标签的服务器

GET /servers?tags-any=red,blue

要请求不具有一个或多个标签的实体列表,应将 not-tags 参数设置为用逗号分隔的标签列表。在这种情况下,只有不具有任何给定标签的实体才会包含在查询结果中。示例,返回不具有“red”或“blue”标签的服务器

GET /servers?not-tags=red,blue

要请求不具有列表中至少一个标签的实体列表,应将 not-tags-any 参数设置为用逗号分隔的标签列表。在这种情况下,只有不具有至少一个给定标签的实体才会包含在查询结果中。示例,返回不具有“red”标签或不具有“blue”标签的服务器

GET /servers?not-tags-any=red,blue

可以将 tagstags-anynot-tagsnot-tags-any 参数组合起来以构建更复杂的查询。示例

GET /servers?tags=red,blue&tags-any=green,orange

上面的示例返回具有“red”和“blue”标签以及“green”和“orange”标签中的至少一个的任何服务器。

可以创建一个自相矛盾的请求。示例

GET /servers?tags=red&not-tags=red

这应被视为一个有效的请求(即不是客户端错误),并应以 2xx 状态码返回一个空结果集。