This topic document serves to provide guidance on how to work with microversions in OpenStack REST APIs.
Microversions enables the ability to introduce API changes while being able to allow clients to discover those changes. According to negotiations with servers, clients adjust their behavior to work with server correctly.
Versioning of the API should be single monotonic counter taking the form X.Y following these conventions:
Note
Note that these versions numbers do not follow the rules of Semantic Versioning.
There are minimum and maximum versions which are used to describe what the server can understand. The minimum and maximum versions are the oldest and most recent versions supported. So clients can specify different version in the supporting range for each API call on the same server. The minimum version can be increased when supporting old clients is too great a burden. Increasing the minimum version means breaking the old clients, this happens very rarely also.
Each version includes all the changes since minimum version was introduced. It is not possible to request the feature introduced at microversion X.Y without accepting all the changes before X.Y in the same request. For example, you cannot request the feature which was introduced at microversion 2.100 without backwards incompatible changes which were introduced in microversion 2.99 and earlier.
A client specifies the version of the API they want via the following approach, a new header:
OpenStack-API-Version: [SERVICE_TYPE] [VERSION_STRING]
For example, Keystone will use the header:
OpenStack-API-Version: identity 2.114
This conceptually acts like the accept header.
Clients should expect the following behavior from the server:
Warning
The latest value is mostly meant for integration testing and would be dangerous to rely on in client code since microversions are not following semver and therefore backward compatibility is not guaranteed. Clients should always require a specific microversions but limit what is acceptable to the version range that it understands at the time.
Two extra headers are always returned in the response:
OpenStack-API-Version: [SERVICE_TYPE] version_number
Vary: OpenStack-API-Version
The first header specifies the version number of the API which was executed. An example:
OpenStack-API-Version: compute 2.22
The Vary header is used as a hint to caching proxies and user agents that the response is also dependent on the OpenStack-API-Version and not just the body and query parameters. See RFC 7231 for details.
Note
Servers must be prepared to deal with multiple OpenStack-API-Version headers. This could happen when a client designed to address multiple services always sends the headers it thinks it needs. Most Python frameworks will handle this by setting the value of the header to the values of all matching headers, joined by a ‘,’ (comma). For example compute 2.11,identity 2.114.
Note
A Python library called microversion-parse is available to help with server-side processing of microversion headers, both the new style described in this document and previous forms.
The Version API for each service should return the minimum and maximum versions. These values are used by the client to discover the supported API versions. If a service ever decides to raise the minimum version that will be supported, it should also return the next minimum version, as well as a date until which the current minimum version is guaranteed to be supported. If there are no plans to change the minimum microversion, the next minimum version and support date should be omitted.
A version response for a service that is planning on raising its minimum supported version would look as follows:
GET /
{
"versions": [
{
"id": "v2.1",
"links": [
{
"href": "http://localhost:8774/v2/",
"rel": "self"
}
],
"status": "CURRENT",
"max_version": "2.42",
"min_version": "2.1",
"next_min_version": "2.13",
"not_before": "2019-12-31"
},
]
}
Note
The links conform to the Links guideline.
“max_version” is the maximum version supported; “min_version” is the minimum version supported; “next_min_version” is the planned next minimum version; and “not_before” is the date (in ISO YYYY-MM-DD format) before which the minimum will not change. Note that this doesn’t require that the minimum be raised on that date; that can happen any time afterwards. It is there to give operators a sense of how quickly they need to change their tooling to support it.
If there is no planned change to the minimum version, the response can omit the ‘next_min_version’ and ‘not_before’ values. Such a response would look like:
GET /
{
"versions": [
{
"id": "v2.1",
"links": [
{
"href": "http://localhost:8774/v2/",
"rel": "self"
}
],
"status": "CURRENT",
"max_version": "2.42",
"min_version": "2.1",
},
]
}
While it is typical for there to be a single API for a given service, it is also sometimes useful to be able to offer more than one version of a given API. Common examples of this are when an older version is still made available in order to support clients that have not yet upgraded to the current version, or when a new API version is being tested before it is released. To distinguish these different APIs for the same service, the status value is used. The following values can be returned for status:
Status | Meaning |
---|---|
CURRENT | The newest API that is currently being developed and improved. Unless you need to support old code, use this API. |
SUPPORTED | An older version of the API. No new features will be added to this version, but any bugs discovered in the code may be fixed. |
DEPRECATED | This API will be removed in the foreseeable future. You should start planning on using alternatives. |
EXPERIMENTAL | This API is under development (‘alpha’), and you can expect it to change or even be removed. |
When the requested version is out of range for the server, the server returns status code 406 Not Acceptable along with a response body.
The error response body conforms to the errors guideline Errors with two additional properties as described in the json-schema below:
{
"max_version": {
"type": "string", "pattern": "^([1-9]\d*)\.([1-9]\d*|0)$"
},
"min_version": {
"type": "string", "pattern": "^([1-9]\d*)\.([1-9]\d*|0)$"
}
}
An example HTTP Header response:
HTTP/1.1 406 Not Acceptable
Openstack-API-Version: compute 5.3
Vary: OpenStack-API-Version
An example errors body response:
{
"errors": [
{
"request_id": "2ee92f06-8ede-4fb4-8921-b507601fb59d",
"code": "compute.microverion-unsupported",
"status": 406,
"title": "Requested microversion is unsupported",
"detail": "Version 5.3 is not supported by the API. Minimum is 2.1 and maximum is 5.2.",
"max_version": "5.2",
"min_version": "2.1",
"links": [
{
"rel": "help",
"href": "http://developer.openstack.org/api-guide/compute/microversions.html"
}
]
}
]
}