2024-05-15
Artem Goncharov
The OpenAPI Specification, previously known as the Swagger Specification, is a specification for a machine-readable interface definition language for describing, producing, consuming and visualizing web services.
OpenAPI version 3.1.0, released in 2021, includes JSON schema alignment what allows it to be applied for every API with JSON schema.
openapi: 3.1.0
info:
version: 1.0.0
title: Sample API
description: A sample API to illustrate OpenAPI concepts
paths:
/list:
get:
description: Returns a list of stuff
request:
headers:
..
content:
..
responses:
'200':
headers:
..
content:
application/json:
schema:
description: Stuff items list
type: array
items:
type: string
description: I am the stuff item
Some services (i.e. Swift) support dynamic (not pre-defined) headers to operate on resource metadata:
$> curl -i $publicURL/marktwain/goodbye -X POST -H "X-Object-Meta-Book: GoodbyeColumbus"
Danger
OpenAPI requires all supported request and response headers to be described explicitly (name, data type, description)
“API Microversions” allow changes to the API while preserving backward compatibility. The basic idea is that a user has to explicitly ask for their request to be treated with a particular version of the API.
So breaking changes can be added to the API without breaking users who don’t specifically ask for it.
$> curl -i $publicURL/volumes -X POST -H "OpenStack-API-Version: volume 3.70" ...
Danger
OpenAPI does not support different operations based on the passed headers
Few OpenStack services rely on the RPC like actions where operation is routed based on the body.
$> curl -i $publicURL/servers/fake_id/action -X POST -d '
{
"lock": {"locked_reason": "I don't want to work"}
}
'
Danger
OpenAPI does not support different operations based on the request body
OpenAPI allows X-custom extensions
Custom OpenAPI parameter serialization based on regex (similar to parameter serialization)
JSON schema oneOf
with x-openstack
extension and custom discriminator (polymorphism)
components:
schemas:
VolumesCreateRequest:
oneOf:
- $ref: '#/components/schemas/VolumesCreate_30'
- $ref: '#/components/schemas/VolumesCreate_313'
- $ref: '#/components/schemas/VolumesCreate_347'
- $ref: '#/components/schemas/VolumesCreate_353'
x-openstack:
discriminator: microversion
VolumesCreate_313:
...
x-openstack:
min-ver: 3.13
max-ver: 3.46
...
JSON schema oneOf
with x-openstack
extension and custom discriminator
Just a combination of above methods.
components:
schemas:
server_actions:
oneOf:
- $ref: #/components/schemas/action_foo
- $ref: #/components/schemas/action_bar
x-openstack:
discriminator: action
action_foo:
oneOf:
- $ref: #/components/schemas/action_foo_21
- $ref: #/components/schemas/action_foo_22
x-openstack:
action-name: foo
discriminator: microversion
Inspect source code of services
Some services have json schema attached to the controllers
Services use different frameworks (wsgi + routes, pecan, flask, WSME, etc)
Response descriptions mostly missing
==> CodeGenerator
No naming conventions
Unified behavior for non-standard service functionality is hard
Used JSON schema libraries have limited validation of the schema errors
OpenAPI validation still does not catch all of the JSON schema errors
=> CodeGeneration catches lot of schema errors
Who:
https://github.com/gtema/openstack
$> osc --os-cloud devstack compute server list
+------------------+-------+---------+
| id | name | status |
+------------------+-------+---------+
| aaed1db9-***-*** | s**** | ACTIVE |
| c080769c-***-*** | w**** | ACTIVE |
| 28aef686-***-*** | y**** | ACTIVE |
| 3c178e63-***-*** | h**** | ACTIVE |
| b62f9988-***-*** | 3**** | ACTIVE |
| 1b129bad-***-*** | s**** | SHUTOFF |
+------------------+-------+---------+
Test | OSC (python) | OSC (Rust) |
---|---|---|
catalog list | 1.54s | 68ms |
flavor list | 2.6s | 830ms |
server list (empty) | 1.8s | 210ms |
server list (10 entries) | 4.0s | 709ms |
image list | 2.4s | 560ms |
network list | 1.8s | 330ms |
volume list | 1.9s | 270ms |
container list | 1.3s | 370ms |
object list (3200 files) | 2.4s | 1.0s |
object list (10000 files) | 3.8s | 1.7s |