Glare API

https://blueprints.launchpad.net/glance/+spec/glare-api

本规范描述了 Glance 工件仓库服务(又称 Glare)的稳定 API,涵盖了所有最流行的用例。

问题描述

Glare 需要一个满足 API-WG 和 DefCore 要求的稳定 API。

提议的变更

本规范旨在通过完全重构 Glance 工件仓库 API 并更改对 Glare 服务的调用来解决所述问题。

Glare 的服务器行为和 API 调用将发生变化。为了详细描述重构后的服务行为,我们准备了一些词汇表和用例列表。

用户列表

  • 开发者 - 为 Glare 贡献代码的人员。

  • Glare - 代表部署在 OpenStack 中的 Glare 服务。

  • 用户 - 希望使用 Glare 工件的 Glare 用户。用户应在 Keystone 中创建,并属于某个项目和域。

  • 云管理员 - 负责 OpenStack 中 Glare 管理和支持的人员。

术语表

  • Glare (来自 GLance Artifact REpository) - 一种服务,提供对具有结构化元信息以及相关二进制数据(这些结构也称为“工件”)的统一不可变对象目录的访问。Glare 控制工件一致性,并保证二进制数据和属性在工件生命周期内不会改变。

    注意

    工件类型开发者可以声明其值可能更改的属性,但他必须明确声明,因为默认情况下所有属性都被认为是不可变的。

  • 工件 - 在 Glare 术语中,工件是一个结构化的不可变对象,具有一些属性、相关的二进制数据和元数据。

  • 工件版本 - 工件的属性,以 SemVer 格式定义其版本。

  • 工件类型 - 定义工件的二进制数据和属性的结构。Glare 中将支持的 OpenStack 工件类型示例包括:Heat 模板、Murano 包、Nova 镜像、Tacker VNF 等等。

  • 工件状态 - 指定工件的状态以及可以对其执行的操作。可能的工件状态列表

    • queued - 工件已创建但未激活,因此可由工件所有者更改。

    • active - 工件已激活,不可变属性不能更改。工件可供其他用户下载。

    • deactivated - 工件对除管理员以外的其他用户不可用,在云管理员需要检查工件时使用。

    • deleted - 工件已删除。

工件状态转换表

工件状态

queued

active

deactivated

deleted

queued

X

activate Artifact

N/A

delete Artifact

active

N/A

X

de-activate Artifact

delete Artifact

deactivated

N/A

reactivate Artifact

X

delete Artifact

deleted

N/A

N/A

N/A

X

  • 工件属性 - 定义有关工件某些信息的工件属性。工件属性始终具有名称、类型、值和可选的附加参数,如下所述。

    类型基于 oslo.versionedobjects 库中的类型。所有类型都继承自 FieldType 类,并定义自定义行为。

    Glare 直接使用 oslo.versionedobjects 中的几种原始类型

    • 字符串;

    • Integer;

    • Float;

    • 布尔值;

    Glare 还通过自定义类型扩展了此列表

    • Blob;

    • Dependency;

    • 结构化泛型类型 DictList

    每个属性都有额外的参数

    • required_on_activate - 布尔值,指示在激活之前是否应为工件指定属性值。(默认值:True)

    • mutable - 布尔值,指示工件激活后属性值是否可以更改。(默认值:False)

    • system - 布尔值,指示属性值是否不能由用户编辑。(默认值:False)

    • sortable - 布尔值,指示是否可以通过此属性的值进行排序。(默认值:False)

    注意

    只有 4 种原始类型的属性可以排序:整数、字符串、浮点数和布尔值。

    • default - 工件类型可以指定属性的默认值。(默认值:None)

    • validators - 函数或 lambda 列表,如 f(self, v) -> Bool。当用户为带有额外验证器的属性设置值时,Glare 会在设置值之前检查它们,如果至少有一个要求未满足,则会引发 ValueError

    • filter_ops - 属性的可用过滤器运算符列表。有七个可用运算符:“eq”、“neq”、“lt”、“lte”、“gt”、“gte”、“in”。所有这些都只能应用于原始属性。Dict 值可以使用以下语法排序:“?<dict_name>.<key_name>=<op_name>:<value>。”

  • 工件依赖 - 定义工件对另一个工件的软依赖的属性类型。它是一个 URL,允许用户获取一些工件数据。对于外部依赖,格式如下:http(s)://<netloc>/<path> 对于内部依赖,依赖只包含 <path>。<path> 的示例:/artifacts/<artifact_type>/<artifact identifier>。用户可以使用路径中的过滤器和 page_limits 来定义动态依赖。Glare 所做的只是用依赖请求 GET 以接收工件信息。

  • 工件 Blob - 定义工件二进制数据的属性类型。用户可以从 Glare 下载工件 blob。每个 blob 属性都有一个 external 标志,指示该属性是在文件上传期间创建的(False)还是由用户直接请求创建的(True)。换句话说,“external”表示 blob 属性 URL 只是对某个外部文件的引用,在这种情况下 Glare 不管理 blob 操作。定义 blob 格式的 Json 模式

    {
        "type": "object",
        "properties": {
            "size": {
                "type": ["number", "null"]
            },
            "checksum": {
                "type": ["string", "null"]
            },
            "external": {
                "type": "boolean"
            },
            "status": {
                "type": "string",
                "enum": ["saving", "active", "pending_delete"]
            }
        },
        "required": ["size", "checksum", "external", "status"]
    }
    

    工件 blob 属性可能具有以下状态

    • saving - 工件 blob 记录已在表中创建,blob 上传已开始。

    • active - blob 上传成功完成。

    • pending_delete - 指示 blob 将很快被 Scrubber(如果启用了延迟删除)或 Glare 本身删除。

Blob 状态转换表

Blob 状态

saving

active

pending delete

saving

X

finish blob upload

request for artifact delete

active

N/A

X

request for artifact delete

pending_delete

N/A

N/A

X

  • 工件字典和列表 - 分别实现字典或列表接口的复合泛型属性类型,并包含由 element_type 属性定义的某种原始类型的值。

  • 工件可见性 - 定义谁可以访问活动工件。最初有 2 个选项:“private”工件只能由其所有者和管理员访问,“public”则所有用户默认都可以访问该工件。当工件处于“queued”状态时,其可见性为“private”。只有当工件处于“active”状态时才允许更改可见性。

  • 工件锁定 - 当工件处于 queued 状态时,其所有属性都可编辑,但当其变为 active 状态时,它将被“锁定”且无法修改(除非明确声明为可变属性)。

用例列表

  • 用例 1。 添加工件类型。

    先决条件: 无。

    成功条件: 新工件类型已添加到 Glare,其他 OS 用户可以使用。

    步骤

    1. 操作员将工件类型类添加到“glare/objects”文件夹中。

    注意

    工件类型已在 Glance 仓库中预发布。所有这些都将由 Glance 开发人员和审阅者进行审查和提交。

    1. 操作员实现所有抽象方法并定义数据 API。

    注意

    我们使用图像数据 API 用于图像工件类型,并使用通用统一数据 API 用于其他工件。

    1. 操作员重新生成(使用 oslo 配置生成器)或更新 Glare 配置文件以启用新工件类型。

    2. 操作员重启 Glare 服务,Glare 验证新工件类型。

    替代方案

    4A. 工件类型验证失败 - Glare 将无法启动。

  • 用例 2。 更新工件类型。

    先决条件: Glare 支持工件类型(工件类型类已实现)。

    成功条件: 工件类型定义已在 Glare 中更新

    并且可以被其他 OpenStack 用户使用。旧工件(更新前存在的)对 OpenStack 用户可用。

    步骤

    1. 操作员在工件类型类中添加新字段或更新字段。

    2. 操作员更新工件类型类(提升版本)以涵盖数据库和新更改之间的兼容性支持。

    3. 操作员重新生成或更新 Glare 配置文件(如果需要)。

    4. 操作员重启 Glare 服务,Glare 验证更新后的工件类型。

    替代方案

    4A. 工件类型验证失败 - Glare 将无法启动。

  • 用例 3。 禁用工件类型。

    先决条件:Glare 支持工件类型(工件类型类已

    实现)。

    成功条件:工件类型定义已在 Glare 中更新并且

    可以被其他使用。

    步骤

    1. 操作员从 Glare 配置文件中删除工件类型名称。

    2. 操作员重启 Glare。

    替代方案

    • 无。

    注意

    被禁用的工件类型的工件将呈现在数据库中,所有数据都将存储在存储中,但用户将无法通过 Glare API 访问这些工件。

  • 用例 4。 列出工件类型。

    先决条件: 运行 Glare API。

    成功条件: 向用户提供该部署中工件类型定义的列表。

    向用户提供该部署中工件类型定义的列表。

    步骤

    1. 用户请求支持的工件类型列表 (GET /schemas)。

    2. Glare 检查 Glare 配置、工件类型类并生成工件类型的 JSON 表示。

    3. Glare 将表示返回给用户 (200 OK)。

    替代方案

    • 无。

  • 用例 5。 获取工件类型信息。

    先决条件: 运行 Glare API。

    成功条件: 向用户提供工件类型定义

    步骤

    1. 用户请求工件类型信息 (GET /schemas/{artifact_type})。

    2. Glare 检查 Glare 配置、工件类型类并生成 JSON 模式

    3. Glare 将 JSON 模式返回给用户 (200 OK)。

    替代方案

    2A. 未找到请求名称的工件类型 (404 Not Found)

  • 用例 6。 创建工件。

    注意

    这里不上传 blob。只在数据库中创建工件实体。

    先决条件
    • 工件类型定义已添加到 Glare。

    • 工件类型在 Glare 中处于活动状态。

    • 用户有权创建工件。

    成功条件: 工件实体已在 Glare DB 中创建。

    步骤

    1. 用户定义允许的工件属性并请求创建工件 (POST /artifacts/{artifact_type})。

    2. Glare 检查创建工件的可能性。

    3. Glare 在数据库中创建工件实体(仅记录在数据库中)。

    4. Glare 返回创建工件的元数据 (201 Created)。

    替代方案

    2A. 属性值不正确 (400 Bad Request)

    2B. 带有名称的属性不存在 (400 Bad Request)

    2C. 依赖格式不正确 (400 Bad Request)

    2D. 属性是系统属性 (403 Forbidden)

    2E. 未找到工件类型 (404 Not Found)

    2F. 具有所需名称和版本的工件已为该用户存在 (409 Conflict)

  • 用例 7。 上传工件二进制数据。

    先决条件

    • 工件类型定义已添加到 Glare。

    • 工件类型在 Glare 中处于活动状态。

    • 工件实例已成功创建。

    • 用户有足够的配额空间。

    • 工件处于“queued”状态。

    成功条件: 数据已上传到存储,工件 blob 已成功创建并处于“active”状态。

    成功创建并处于“active”状态。

    步骤

    1. 用户指定工件标识符、blob 属性名称、blob 二进制数据、content-type 为 application/octet-stream 并请求上传 (PUT /artifacts/{artifact_type}/{artifacts_id}/{blob_name})。

    2. Glare 检查工件标识符和 blob 属性是否有效。

    3. Glare 在数据库中创建 blob 记录,将其状态更改为“saving”并将其与相关的工件 blob 属性关联。

    4. Glare 将 blob 二进制文件上传到存储后端。

    5. Glare 将所有必需的元数据(“大小”、“校验和”等)设置到 blob 并将其状态更改为“active”。

    注意

    Glare 不使用注册表服务,因此此处不需要信任。

    1. Glare 以 200 OK 响应。

    替代方案

    2A. 未找到工件 (404 Not Found)。

    2B. 未找到 blob 属性 (400 Bad Request)。

    2C. 元数据无效 (400 Bad Request)。

    3C. Blob 已上传并处于“active”状态 (409 Conflict)

    3D. Blob 正在保存 (409 Conflict)。

    4A. 每个租户的工件配额超出 (413 HTTPRequestEntityTooLarge)。

    4B. Blob 上传失败。Glare 启动 Blob 终止并响应适当的错误(取决于后端错误)。

  • 用例 8。 为工件添加自定义位置。

    先决条件

    • 工件类型定义已添加到 Glare。

    • 工件类型在 Glare 中处于活动状态。

    • 工件实例已成功创建。

    • 工件处于“queued”状态。

    成功条件: blob 位置已成功添加到工件。

    步骤

    1. 用户指定工件标识符、blob 属性名称、位置、content-type 为 application/json 并发送请求 (PUT /artifacts/{artifact_type}/{artifacts_id}/{blob_name})。

      • Body

        {"url": "<some_url>"}
        
    2. Glare 检查工件标识符和 blob 属性名称是否有效。

    3. Glare 检查给定位置,在数据库中创建 blob 记录,将其与工件关联,并将位置添加到 blob。

    4. Glare 将 blob 属性状态更改为活动状态。

    5. Glare 以 200 OK 响应。

    替代方案

    2A. 未找到工件 (404 Not Found)。

    2B. 未找到属性 (400 Bad Request)。

    3A. 位置 URL 无效 (400 Bad Request)。

    3B. 位置 URL 不可下载 (400 Bad Request)。

    3C. Blob 记录已存在 (409 Conflict)。

  • 用例 9。 激活工件。

    先决条件

    • 工件类型定义已添加到 Glare。

    • 工件类型在 Glare 中处于活动状态。

    • 工件实例已成功创建。

    • 成功条件:* 工件在 Glare 中已激活(状态为“active”)。

    步骤

    1. 用户定义工件 ID 并请求工件激活 (PATCH /artifacts/{artifact_type}/{artifacts_id})。

      • Body

        [{
            "op": "replace",
            "path": "/status",
            "value": "active"
        }]
        
    2. Glare 检查是否所有必需的工件属性都已根据工件定义指定。

    3. Glare 检查是否所有必需的 blob 属性都已根据工件定义处于活动状态。

    4. Glare 检查所有工件依赖是否正确。

    5. Glare 激活工件,使其对其他用户可见并返回响应 (200 OK)。

    替代方案

    2-4A. 某些必需属性或 blob 未指定,依赖不正确(通过 URL 未找到依赖,或每个依赖有多个工件)(400 Bad Request)。

    2B. 工件不存在或已删除 (404 Not Found)。

  • 用例 10A。 更新工件非 blob 属性,工件已排队。

    先决条件

    • 工件类型定义已添加到 Glare。

    • 工件类型在 Glare 中处于活动状态。

    • 工件实例已成功创建。

    成功条件: 工件属性已在 Glare 中更新。

    步骤

    1. 用户请求更新工件属性、blob 属性或依赖 (PATCH /artifacts/{artifact_type}/{artifacts_id})。

    2. Glare 更新所需属性并返回更新后的工件 (200 OK)。

    替代方案

    2A. 依赖 URL 不正确或不可下载 (400 Bad Request)。

    2B. 工件不存在或已删除 (404 Not Found)。

    2C. 参数不正确 (400 Bad Request)。

    2D. 属性为系统属性 (403 Forbidden)。

    2E. 具有更新名称和版本的工件已为该用户存在 (409 Conflict)。

  • 用例 10B。 更新工件非 blob 属性,工件已激活。

    先决条件

    • 工件类型定义已添加到 Glare。

    • 工件类型在 Glare 中处于活动状态。

    • 工件实例已成功创建。

    成功条件: 工件已在 Glare 中更新。

    步骤

    1. 用户请求更新工件属性或依赖 (PATCH /artifacts/{artifact_type}/{artifacts_id})。

    2. Glare 检查依赖是否可变且可更新。

    3. Glare 检查属性是否可变且可更新。

    4. Glare 更新所需属性 (200 OK)。

    替代方案

    2A. 依赖属性是不可变的 (403 Forbidden)。

    2B. 依赖 URL 不正确或不可下载 (400 Bad Request)。

    3A. 属性是不可变的 (403 Forbidden)。

    3B. 参数不正确 (400 Bad Request)。

  • 用例 11。 下载 blob。

    先决条件

    • 工件类型定义已添加到 Glare。

    • 工件类型在 Glare 中处于活动状态。

    • 工件实例已成功创建。

    成功条件: Blob 已下载。

    步骤

    1. 用户提供 blob 属性名称和工件标识符 (GET /artifacts/{artifact_type}/{artifacts_id}/{blob_name})。

    2. Glare 向用户提供工件二进制流 (200 OK)。

    替代方案

    2A. 工件 blob 不包含数据 (204 No Content)。

    2B. 工件 blob 状态为“saving” (204 No content)。

    2C. 下载不成功(取决于后端错误)。

    2D. 工件已停用且用户没有下载权限 (403 Forbidden)

    下载 (403 Forbidden)

  • 用例 12。 获取工件信息

    先决条件

    • 工件类型定义已添加到 Glare。

    • 工件类型在 Glare 中处于活动状态。

    • 工件实例已成功创建。

    成功条件: 将工件定义返回给用户。

    步骤

    1. 用户使用工件标识符和工件类型请求工件信息 (GET /artifacts/{artifact_type}/{artifacts_id})。

    2. Glare 返回工件属性、blob 信息和依赖信息 (200 OK)。

    替代方案

    2A. 没有查看工件的权限 (403 Forbidden)。

    2B. 未找到工件或工件类型 (404 Not Found)。

  • 用例 13。 停用工件。

    先决条件

    • 工件类型定义已添加到 Glare。

    • 工件类型在 Glare 中处于活动状态。

    • 工件实例已成功创建。

    成功条件: 工件状态已停用。

    步骤

    1. 用户发送停用工件的请求 (PATCH /artifacts/{artifact_type}/{artifacts_id})。

      • Body

        [{
            "op": "replace",
            "path": "/status",
            "value": "deactivated"
        }]
        

    注意

    停用权限由 oslo 策略管理。

    1. Glare 将工件状态从活动更改为停用 (200 OK)。

    注意

    当前依赖是软依赖。因此,这里不进行工件之间的完整性检查。

    替代方案

    2A. 工件状态不是活动状态 (400 Bad Request)。

    2B. 用户没有停用工件的权限 (403 Forbidden)。

  • 用例 14。 重新激活工件。

    先决条件

    • 工件类型定义已添加到 Glare。

    • 工件类型在 Glare 中处于活动状态。

    • 工件实例已成功创建。

    成功条件: 工件处于活动状态。

    步骤

    1. 用户发送重新激活工件的请求 (PATCH /artifacts/{artifact_type}/{artifacts_id})。

      • Body

        [{
            "op": "replace",
            "path": "/status",
            "value": "active"
        }]
        

    注意

    停用权限由 oslo 策略管理。

    1. Glare 将工件状态从停用更改为活动 (200 OK)。

    替代方案

    2A. 工件状态不是停用状态 (400 Bad Request)。

    2B. 用户没有重新激活工件的权限 (403 Forbidden)。

  • 用例 15。 发布工件。

    先决条件

    • 工件类型定义已添加到 Glare。

    • 工件类型在 Glare 中处于活动状态。

    • 工件实例已成功创建。

    • 工件状态为“active”。

    成功条件: 工件已发布(即工件可见性为 public)。

    步骤

    1. 用户发送发布工件的请求 (PATCH /artifacts/{artifact_type}/{artifacts_id})

      • Body

        [{
            "op": "replace",
            "path": "/visibility",
            "value": "public"
        }]
        
    2. Glare 将工件的可见性从“private”更改为“public” (200 OK)。

    替代方案

    2A. 工件状态不是“active” (400 Bad Request)。

    2B. 用户没有发布工件的权限 (403 Forbidden)。

    2C. 具有所需名称和版本的公共工件已存在 (409 Conflict)。

  • 用例 16。 列出工件。

    先决条件

    • 工件类型定义已添加到 Glare。

    • 工件类型在 Glare 中处于活动状态。

    成功条件: 工件列表返回给用户。

    步骤

    1. 用户请求具有指定工件类型、限制、标记、过滤器的工件列表 (GET /artifacts/{artifact_type})。

    2. Glare 将所有工件返回给用户 (200 OK)。

    替代方案

    2A. 工件数量过多 (400 Bad Request)(使用限制来限制响应中的工件数量)。

    2B. 查询参数无效(按不存在的键排序或过滤)(400 Bad Request)。

  • 用例 17。 删除工件。

    先决条件

    • 工件类型定义已添加到 Glare。

    • 工件类型在 Glare 中处于活动状态。

    • 工件实例已成功创建。

    成功条件: 工件已从 Glare 中成功删除。

    步骤

    1. 用户使用工件类型和工件标识符请求删除工件 (DELETE /artifacts/{artifact_type}/{artifacts_id})。

    2. Glare 将工件状态更新为“deleted”,并将所有工件的 blob 状态设置为“pending_delete”。

    注意

    此处没有依赖一致性检查。

    1. Glare 删除所有工件的自定义属性和标签。

    4. Glare 依次从存储中删除 blob 数据,并从数据库中删除 blob 实例。

    1. Glare 响应 204 No Content。

    替代方案

    2A. 某些 blob 正在上传。Glare 完成 blob 上传并立即删除它。

    2B. 某些 blob 正在下载。这取决于存储后端,通常情况下下载将被取消。

    4A. 在删除 blob 期间发生存储错误。Glare 停止删除 blob,用户必须使用 Scrubber 从存储中删除它们。

    4B. 启用了“delayed_delete”配置选项。Glare 不执行任何操作并返回 204 No Content。Blob 数据应稍后使用 Scrubber 删除。

  • 用例 18。 添加工件标签。

    先决条件

    • 工件类型定义已添加到 Glare。

    • 工件类型在 Glare 中处于活动状态。

    • 工件已成功创建。

    成功条件: 工件标签已成功添加到工件。

    步骤

    1. 用户指定标签名称和工件标识符并发送请求。(PUT /artifacts/{artifact_type}/{artifacts_id}/tags/{tag_value})

    2. Glare 将标签添加到工件 (200 OK)。

    替代方案

    2A. 标签已存在 (200 OK)。

    2B. 工件不存在 (404 Not Found)。

  • 用例 19。 删除工件标签。

    先决条件

    • 工件类型定义已添加到 Glare。

    • 工件类型在 Glare 中处于活动状态。

    • 工件已成功创建。

    成功条件: 工件标签已成功从工件中移除。

    步骤

    1. 用户指定标签名称和工件标识符并发送请求。(DELETE /artifacts/{artifact_type}/{artifacts_id}/tags/{tag_value})。

    2. Glare 从工件中移除标签 (204 No Content)。

    替代方案

    2A. 标签或工件不存在 (404 Not Found)。

备选方案

无论如何我们都需要处理 API-WG 和 DefCore 的评论,所以这里没有替代方案。

数据模型影响

没有数据模型影响。

REST API 影响

所有 API 调用都位于 /artifacts/{artifact_type} 分支下,其中 artifact_type 是由工件类型定义的常量,通常应该是工件类型名称的复数形式。例如,对于类型为“template”的工件,此常量应命名为“templates”,因此 API 端点将以 /artifacts/templates 开头。

Glare API 符合 OpenStack API-WG 指南

对于更新工件属性,Glare API 使用 json-patch

Glare 支持微版本来定义它应该使用的 API 版本:API-WG 微版本指南

信息

  • 可用 API 版本列表

    GET /

    返回最小和最大 API 版本的 json 表示。代码 200 OK

  • 可用工件类型模式列表

    GET /schemas

    返回所有活动工件类型的 json 表示。代码 200 OK

  • 工件类型描述

    GET /schemas/{artifact_type}

    返回给定工件类型的 json 模式。代码 200 OK

工件

  • 给定类型名称的工件列表

    GET /artifacts/{artifact_type}

    返回工件列表的 json 表示。代码 200 OK。

    注意

    这些请求支持符合 API-WG 过滤、排序和分页指南 的查询参数

  • 创建给定类型名称的工件

    POST /artifacts/{artifact_type}

    以 json 格式返回有关已创建实例的信息。代码 201 Created。

  • 显示工件

    GET /artifacts/{artifact_type}/{artifacts_id}

    以 json 格式返回有关给定 ID 的工件的信息。代码 200 OK。

  • 更新工件

    PATCH /artifacts/{artifact_type}/{artifacts_id}

    以 json 格式返回更新后的工件信息。代码 200 OK。

  • 删除工件

    DELETE /artifacts/{artifact_type}/{artifacts_id}

    代码 204 No Content。

Blobs

  • 上传文件到工件

    PUT /artifacts/{artifact_type}/{artifacts_id}/{blob_name}

    代码 200 OK。

  • 从工件下载文件

    GET /artifacts/{artifact_type}/{artifacts_id}/{blob_name}

    返回请求 blob 的二进制流。代码 200 OK

标签

注意

这些请求符合 API-WG 标签指南

  • 向工件添加标签

    PUT /artifacts/{artifact_type}/{artifacts_id}/tags/{tag_name}

    代码 200 OK。

  • 从工件中移除标签

    DELETE /artifacts/{artifact_type}/{artifacts_id}/tags/{tag_name}

    代码 200 OK。

  • 从工件中删除所有标签

    DELETE /artifacts/{artifact_type}/{artifacts_id}/tags

    代码 204 No Content。

  • 替换工件的标签列表

    PUT /artifacts/{artifact_type}/{artifacts_id}/tags

    代码 200 OK。

  • 获取工件的标签列表

    GET /artifacts/{artifact_type}/{artifacts_id}/tags

    代码 200 OK。

API 请求示例

例如,我们有一个工件类型“example_type”具有以下属性

  • id: StringField

  • name: StringField

  • visibility: StringField

  • status: StringField

  • blob_file: BlobField

  • metadata: DictOfStringsField

  • version: VersionField

  1. 创建工件

请求

响应

201 Created

{
     "status": "queued",
     "name": "new_art",
     "id": "art_id1",
     "version": null,
     "blob_file": null,
     "metadata": {},
     "visibility": "private"
 }
  1. 获取工件

请求

响应

200 OK

{
    "status": "queued",
    "name": "new_art",
    "id": "art_id1",
    "version": null,
    "blob_file": null,
    "metadata": {},
    "visibility": "private"
}
  1. 列出工件

请求

响应

200 OK

{
    "example_type": [{
        "status": "queued",
        "name": "new_art",
        "id": "art_id1",
        "version": null,
        "blob_file": null,
        "metadata": {},
        "visibility": "private"
    }, {
        "status": "queued",
        "name": "old_art",
        "id": "art_id2",
        "version": null,
        "blob_file": null,
        "metadata": {},
        "visibility": "private"
    }, {
        "status": "queued",
        "name": "old_art",
        "id": "art_id3",
        "version": null,
        "blob_file": null,
        "metadata": {},
        "visibility": "private"
    }],
    "first": "/artifacts/example_type",
    "schema": "/schemas/example_type"
}

请求

响应

200 OK

{
    "example_type": [{
        "status": "queued",
        "name": "old_art",
        "id": "art_id2",
        "version": null,
        "blob_file": null,
        "metadata": {},
        "visibility": "private"
    }, {
        "status": "queued",
        "name": "old_art",
        "id": "art_id3",
        "version": null,
        "blob_file": null,
        "metadata": {},
        "visibility": "private"
    }],
    "first": "/artifacts/example_type?name=ne%3Anew_name",
    "schema": "/schemas/example_type"
}
  1. 更新工件

请求

响应

200 OK

{
    "status": "queued",
    "name": "stark",
    "id": "art_id1",
    "version": null,
    "blob_file": null,
    "metadata": {
        "slogan": "winter is coming"
    },
    "visibility": "private"
}
  1. 上传 blob

请求

响应

200 OK

{
    "status": "queued",
    "name": "stark",
    "id": "art_id1",
    "version": null,
    "metadata": {
        "slogan": "winter is coming"
    },
    "blob_file": {
        "status": "active",
        "checksum": "8452e47f27b9618152a2b172357a547d",
        "external": false,
        "size": 16
    },
    "visibility": "private"
}
  1. 下载 blob

请求

响应

200 OK

亡者永不消逝

  1. 激活工件

请求

响应

200 OK

{
    "status": "active",
    "name": "stark",
    "id": "art_id1",
    "version": null,
    "metadata": {
        "slogan": "winter is coming"
    },
    "blob_file": {
        "status": "active",
        "checksum": "8452e47f27b9618152a2b172357a547d",
        "external": false,
        "size": 16
    },
    "visibility": "private"
}
  1. 停用工件

请求

响应

200 OK

{
    "status": "deactivated",
    "name": "stark",
    "id": "art_id1",
    "version": null,
    "metadata": {
        "slogan": "winter is coming"
    },
    "blob_file": {
        "status": "active",
        "checksum": "8452e47f27b9618152a2b172357a547d",
        "external": false,
        "size": 16
    },
    "visibility": "private"
}
  1. 重新激活工件

请求

响应

200 OK

{
    "status": "active",
    "name": "stark",
    "id": "art_id1",
    "version": null,
    "metadata": {
        "slogan": "winter is coming"
    },
    "blob_file": {
        "status": "active",
        "checksum": "8452e47f27b9618152a2b172357a547d",
        "external": false,
        "size": 16
    },
    "visibility": "private"
}
  1. 发布工件

请求

响应

200 OK

{
    "status": "active",
    "name": "stark",
    "id": "art_id1",
    "version": null,
    "metadata": {
        "slogan": "winter is coming"
    },
    "blob_file": {
        "status": "active",
        "checksum": "8452e47f27b9618152a2b172357a547d",
        "external": false,
        "size": 16
    },
    "visibility": "public"
}
  1. 删除工件

请求

响应

204 No Content

安全影响

无安全影响

通知影响

无通知影响

其他最终用户影响

新 API 需要客户端支持。Glare API v0.1 的支持可以在添加 v1 支持的同时或之后的任何时候移除。

性能影响

无性能影响

其他部署者影响

Glare 服务将遵循 Glance 发布周期。然而,工件类型更新预计将比 6 个月的周期更快。因此,我们希望能够更频繁地更新工件类型,但以一种受控的方式进行,以便部署者轻松操作。

我们建议通过创建一个新的单一存储库来解决此问题,所有新的 glare-objects(工件类型)都将放入其中。它将是一个 oslo-inc 样式的库,但最好是一个非客户端 OpenStack 库,可以发布到 pip,然后 Glare 对象可以使用每个分支的正确上限约束拉入 Glance 存储库,同时遵守 OpenStack 打包基本原则。

创建这个新的独立库仓库的动机、意图和目的是为了形成一个有组织的方式,让 OpenStack 全项目范围内的开发者能够为自定义工件对象类型做出贡献,并提供一致的反馈。同时,glare-objects 可以共享通用代码,并且最佳实践可以在同一地点记录。

所有 glare 对象的发布将与 Glance 的要求保持一致,并且可以在同一库版本中对所有自定义对象进行全面测试(无论子集对象是否发生更改)。这应该会减轻打包的痛苦,并避免操作员/升级的混乱。

开发人员影响

由于该库将是一个 OpenStack 非客户端库,因此它将需要来自非常规 Glance 开发人员(主要从事 Murano 或 Heat 等项目)的源代码特权访问。

我们将在该存储库中为开发人员建立一些通用代码和最佳实践。

由于 Glare v0.1 API 是实验性的,开发人员应该为它的弃用做好准备。

实现

负责人

主要负责人:mfedosin

其他贡献者

kkushaev dshakhray nikhil-komawar

评审人员

Glance 核心团队,因为我们需要将 Glare 的知识传播给整个团队。

工作项

  • 添加新的 API 路由器和控制器。将 v1 标记为 EXPERIMENTAL

  • 编写辅助方法以实现查询参数解析(例如,用于过滤、排序、标签等,根据 API-WG 指南)

  • 使用单元和功能测试覆盖稳定 API。

  • 将 v0.1 API 标记为 DEPRECATED,将 v1 标记为 STABLE

  • 实现 Glare v1 客户端

依赖项

将 Glare API 从 Glance API 分离(即从 Glance v3 到 Glare v0.1 的过渡)的工作,如规范 [6] 中所定义,应首先完成。

测试

Glare API 应由功能和单元测试覆盖。与 Tempest 的集成测试也应实施。

文档影响

Glare API、配置选项和策略应予记录。

必须添加一份新文档——“工件类型开发者指南”。

参考资料

  1. OpenStack 镜像 API v2 参考

  2. 初始规范

  3. API-WG 确定的 API 问题摘要

  4. 过滤和排序 API-WG 指南

  5. 标签 API-WG 指南

  6. 错误 API-WG 指南

  7. 类型版本问题描述

  8. Glare v0.1 过渡规范

  9. json-patch 描述

  10. 如何在 devstack 上安装 Glare