向 CloudKitty 添加 v2 API¶
https://storyboard.openstack.org/#!/story/2004208
CloudKitty 近期经历了许多变化(v2 存储、Prometheus 支持、独立模式…)。这需要在 API 上进行重大更改:鉴于内部数据格式正在演变,我们需要以不同的方式公开数据,以便支持 v2 存储的新功能:分页、分组、过滤…
问题描述¶
可以识别出几个不同的问题
CloudKitty 的数据需要以更精细的粒度公开。目前缺少的功能列表(不完全):
分页
过滤
分组
…
对于当前的 API,CloudKitty 使用 WSME + pecan。使用这些工具编写的代码对于新贡献者来说可能很难理解。此外,pecan 的开发似乎已经放缓:https://github.com/pecan/pecan/commits/master。
语义。许多端点仍然使用 OpenStack 相关的术语(租户、服务…)。
提议的变更¶
鉴于上述原因,CloudKitty 开发团队建议实现一个新的 API,该 API 将基于 Flask/Werkzeug 和 Flask-RESTful。选择这些框架的原因如下:
Flask 是一个知名且易于使用的框架。这将使新贡献者更容易做出贡献。它非常稳定,并且被其他 OpenStack 项目使用,例如 Keystone。
Flask-RESTful 使代码更易于阅读,并简化了路由。想法是将每个重要的端点(例如
/rating/hashmap)映射到一个蓝图,并将每个子端点(rating/hashmap/services)映射到一个 Flask-RESTful 资源。这将使添加新端点变得容易,并为 v2 API 的演进留出空间。以下是一个可用的代码示例,具有 voluptuous 输入和输出验证:@api_utils.add_output_schema(GET_OUTPUT_EXAMPLE_SCHEMA) def get(self): policy.authorize(flask.request.context, 'example:get_example', {}) return {} @api_utils.add_input_schema(POST_INPUT_EXAMPLE_SCHEMA) def post(self, fruit='banana'): policy.authorize(flask.request.context, 'example:submit_fruit', {}) if fruit not in ['banana', 'strawberry']: raise http_exceptions.Forbidden( 'You submitted a forbidden fruit', ) return { 'msg': 'Your fruit is a ' + fruit }
Flask-RESTful 强制(或至少鼓励)贡献者采用 RESTful 的 API 方法,而 Flask 赋予他们太多的自由。
这个新的 API 将使添加新的端点变得容易,并将成为新功能的容器。任何新的端点都将添加到这个 API 中。
这个 v2 API 将只与 v2 存储兼容,允许新的端点完全利用 v2 存储的容量,而无需处理向后兼容性。v1 API 完全兼容 v2 存储,因此数据仍然可以通过 v1 API 访问,与现有脚本等的兼容性将保持不变。当使用 v1 存储后端时,v2 API 将被禁用。
为了限制工作量,不会一次迁移所有的 v1 端点。建议为每个 API 版本使用一个 WSGI 应用程序,并通过路由来区分它们。这可以使用 Werkzeug 的 DispatcherMiddleware 来完成:http://werkzeug.pocoo.org/docs/0.14/middlewares/#werkzeug.wsgi.DispatcherMiddleware。如果使用 v1 存储后端,则 v2 API 将不会被加载。
v1 端点将逐个迁移。一旦整个 v1 API 迁移完成,v2 API 将被标记为 CURRENT,而 v1 API 将被标记为 DEPRECATED。在此之前,v1 将为 CURRENT,而 v2 将为 EXPERIMENTAL。
添加端点的建议工作流程如下:
编写一个规范,详细说明端点做什么,它对客户端、仪表板和 tempest 插件的影响。
在规范被审查和合并后,创建一个 storyboard 故事,链接到你的规范,并包含以下几点中的每个任务:
将端点添加到 API
为端点添加客户端支持
为 tempest 插件添加此端点的测试
(可选)为端点添加对仪表板的支持
这些任务中的每一个都必须是新的补丁的主题。每个未标记为可选的任务都是强制性的。
添加客户端/仪表板支持的补丁以及添加 tempest 插件测试的补丁必须依赖于将端点添加到 API 的补丁。
一旦 v2 API 稳定并标记为当前 API,它将被 微版本化,以便指示其功能。微版本增加将指示一项新功能(新的端点)。但是,OpenStack 服务目录中的 API 端点将不会被微版本化。API 的确切版本将在 API 根目录 (/) 中可用。
版本控制将使用 语义版本控制 (https://semver.org/) 进行。一旦所有 v1 端点都迁移完成,并且 v2 API 被认为是稳定的,其版本将为 2.0。在此版本之前,每个版本都将以 -beta.version 为后缀。
示例:v2.0-beta.1 -> … -> v2.0-beta.x -> v2.0。
备选方案¶
将整个 v1 API 迁移到 Flask 并扩展现有端点以支持上述功能:这将意味着一次迁移整个 API 代码库,这是不可能做到的。此外,这也不会解决语义问题。
数据模型影响¶
这种特定的更改(创建 v2 WSGI 应用程序并更改请求的路由方式)不会影响数据模型。每个 v2 API 端点都将是新规范的主题。潜在的数据模型影响将在这些即将到来的规范中详细说明。
REST API 影响¶
v1 API 将从
EXPERIMENTAL变为CURRENT当前状态。将提供一个 v2 API,标记为
EXPERIMENTAL。将提供一个新的路由 (
/v2)。它将包含一个占位符,指示这将是所有即将到来的 v2 端点的前缀。
安全影响¶
无
通知影响¶
无
其他最终用户影响¶
无。但是,python-cloudkittyclient 需要与新的 v2 端点兼容。
性能影响¶
分页将允许降低网络负载。
其他部署者影响¶
无
开发人员影响¶
对于开发人员来说,添加一个新的端点应该更容易。
将添加对 Flask 和 Flask-RESTful 的依赖。
实现¶
负责人¶
- 主要负责人
lukapeschke/peschk_l
- Gerrit 主题
cloudkitty-v2-api
工作项¶
将 v1 API 标记为
CURRENT使用 Werkzeug 而不是 Pecan 路由 API
添加一个示例端点,显示如何实现一个端点以及如何记录它。一旦第一个实际端点实现,此示例端点应被删除。
更新文档:更新开发人员文档,解释如何添加一个端点以及如何生成 v2 API 的文档。
依赖项¶
Flask
Flask-RESTful
os-api-ref(用于 API 参考生成)
测试¶
此特定功能将仅使用单元测试进行测试(gabbi 和 unittest)。即将到来的端点还将向 tempest 插件添加一些测试。
文档影响¶
开发人员文档将更新,以详细说明请求的路由方式以及如何添加新的端点。用户文档也将更新,以包含 v2 API 参考。API 参考将使用 os-api-ref 生成。