Merge "Add guidelines on Version Discovery"
This commit is contained in:
commit
81e7685d3c
@ -693,10 +693,11 @@ becomes:
|
||||
}
|
||||
|
||||
* If the document has a key named ``version``, (even if you just created it)
|
||||
grab the ``href`` for the link where ``rel`` is ``self`` link. If the
|
||||
``href`` ends with with a version string of the form "v[0-9]+(\.[0-9]*)?$",
|
||||
pop that element from the end of the endpoint and add an entry to the
|
||||
``links`` list with a ``rel`` of ``collection`` and the resulting endpoint.
|
||||
look for a ``collection`` link in the links list. If one does not exist,
|
||||
grab the ``href`` from the ``self`` link. If the ``self`` link ends with a
|
||||
version string of the form "v[0-9]+(\.[0-9]+)?$", pop that version string
|
||||
from the end of the endpoint and add a ``collection`` entry to the ``links``
|
||||
list with the resulting endpoint.
|
||||
|
||||
For example:
|
||||
|
||||
|
@ -10,6 +10,306 @@ See also the topic document on :ref:`consuming-catalog`.
|
||||
|
||||
See also the topic document on :doc:`consuming-catalog/version-discovery`.
|
||||
|
||||
.. _versioned-and-unversioned-endpoints:
|
||||
|
||||
Versioned and Unversioned Endpoints
|
||||
-----------------------------------
|
||||
|
||||
Each service should have a base endpoint which is referred to as the
|
||||
"Unversioned" endpoint for the service.
|
||||
|
||||
.. note:: It is highly recommended that Cloud Operators register the
|
||||
Unversioned Endpoint for a service in the Keystone Catalog. If they
|
||||
do, the process described in the :ref:`version-discovery-algorithm` will
|
||||
be able to be both the most featureful for the API Consumer and the
|
||||
most efficient.
|
||||
|
||||
Each service must have at least one Major API version.
|
||||
|
||||
If a service has, or expects to have, more than one Major API version,
|
||||
each of those versions should have a base endpoint which is referred to
|
||||
as the "Versioned" endpoint for that version of the service.
|
||||
|
||||
All version discovery documents must be accessible via unauthenticated
|
||||
connection.
|
||||
|
||||
If a service only uses microversions and only has one Major API version,
|
||||
that service should not have any additional "Versioned" endpoints.
|
||||
|
||||
For instance, the Glance service at cloud ``example.com`` might have an
|
||||
Unversioned Endpoint at::
|
||||
|
||||
https://image.example.com
|
||||
|
||||
That Glance service may then also provide three major versions, `v1`, `v2`, and
|
||||
`v3`::
|
||||
|
||||
https://image.example.com/v1
|
||||
https://image.example.com/v2
|
||||
https://image.example.com/v3
|
||||
|
||||
Additionally, the Placement service at cloud ``example.com`` might have
|
||||
an Unversioned Endpoint at::
|
||||
|
||||
https://placement.example.com
|
||||
|
||||
The Placement service only uses microversions, so there are no additional
|
||||
Versioned Endpoints.
|
||||
|
||||
In both cases, the Unversioned Endpoint is the endpoint recommended to be
|
||||
registered in the Service Catalog.
|
||||
|
||||
Preference for Subpaths
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Historically each of the OpenStack services were also given a port. It is
|
||||
strongly recommended to not use those ports and instead use the normal port
|
||||
443 for https. If multiple API services are to be installed on a single
|
||||
machine, it is highly recommended to use subpaths::
|
||||
|
||||
https://api.example.com/compute
|
||||
https://api.example.com/image
|
||||
|
||||
The rationale behind this recommendation is to ease use for users who may have
|
||||
restrictive port-blocking firewalls in their operating environment. Since the
|
||||
traffic is HTTP traffic and not a different protocol, it is not necessary to
|
||||
distinguish it by port number, and doing so increases the chances that users
|
||||
will have problems connecting to individual API endpoints.
|
||||
|
||||
.. _version-discovery:
|
||||
|
||||
Version Discovery
|
||||
-----------------
|
||||
|
||||
Each service should provide a Version Discovery API on both the Unversioned
|
||||
Endpoint and each of Versioned Endpoints of the service to be used by clients
|
||||
to discover the supported API versions.
|
||||
|
||||
.. _unversioned-version-discovery:
|
||||
|
||||
Unversioned Discovery
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Each service should provide a Version Discovery API at the Unversioned Endpoint
|
||||
of the service. It should be exposed to all users without authentication.
|
||||
|
||||
.. note:: It is recommended that the Version Discovery API not be protected
|
||||
by authentication requirements. The information returned is not
|
||||
specific to a user, but is, instead, a fundamental characteristic
|
||||
of the base API of the service running. Additionally, the v2 and
|
||||
v3 authentication API are different, so requiring authentication
|
||||
before version discovery makes it harder to determine reliably
|
||||
whether v2 or v3 authentication should be used.
|
||||
|
||||
The Unversioned Version Discovery API for each service should return a list of
|
||||
Version Information for all of the Base Endpoints the service provides,
|
||||
along with that version's minimum and maximum microversions. These values are
|
||||
used by the client to discover the supported API versions.
|
||||
|
||||
|
||||
:download:`Version Information Schema <version-information-schema.json>`
|
||||
|
||||
.. literalinclude:: version-information-schema.json
|
||||
:language: json
|
||||
|
||||
:download:`Version Discovery Schema <version-discovery-schema.json>`
|
||||
|
||||
.. literalinclude:: version-discovery-schema.json
|
||||
:language: json
|
||||
|
||||
.. _unversioned-discovery-response:
|
||||
|
||||
An Unversioned Version Discovery response would look as follows:
|
||||
|
||||
.. code-block::
|
||||
|
||||
GET /
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"versions": [
|
||||
{
|
||||
"id": "v2.1",
|
||||
"links": [
|
||||
{
|
||||
"href": "https://compute.example.com/v2/",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "https://compute.example.com/",
|
||||
"rel": "collection"
|
||||
}
|
||||
],
|
||||
"status": "CURRENT",
|
||||
"max_version": "5.2",
|
||||
"min_version": "2.1"
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
Each Version Information in the list should contain the following information:
|
||||
|
||||
id
|
||||
The major API version. Follows format outlined in :ref:`versioning`,
|
||||
preceeded by a "v". Required.
|
||||
|
||||
links
|
||||
Contains information about where to find the actual versioned endpoint. See
|
||||
:ref:`version-links` below. Required.
|
||||
|
||||
status
|
||||
Support and lifecycle status of the versioned endpoint. Required.
|
||||
See :ref:`endpoint-status`
|
||||
|
||||
max_version
|
||||
The maximum microversion available if the version of the service supports
|
||||
microversions. Optional. See :ref:`microversion_specification`
|
||||
|
||||
min_version
|
||||
The minimum microversion available if the version of the service supports
|
||||
microversions. Optional. See :ref:`microversion_specification`
|
||||
|
||||
If a service has no Versioned Endpoints, it should simply list its Base
|
||||
Endpoint in the document, like so:
|
||||
|
||||
.. code-block::
|
||||
|
||||
GET /
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"versions": [
|
||||
{
|
||||
"id": "v1.0",
|
||||
"links": [
|
||||
{
|
||||
"href": "https://placement.example.com/",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "https://placement.example.com/",
|
||||
"rel": "collection"
|
||||
}
|
||||
],
|
||||
"status": "CURRENT",
|
||||
"max_version": "1.25",
|
||||
"min_version": "1.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
.. _versioned-version-discovery:
|
||||
|
||||
Versioned Discovery
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Each service should provide a Version Discovery API at each Versioned Endpoint
|
||||
of the service. It should be exposed to all users without authentication.
|
||||
|
||||
The document returned from the Version Discovery API for Versioned Endpoint
|
||||
should be identical to the document returned from the Unversioned Endpoint.
|
||||
In this way, a client that is looking for a version of an API can always
|
||||
get the complete information in one step, rather than a sequence of attempts,
|
||||
failures and re-attempts.
|
||||
|
||||
However, in service of getting to a perfect future from amidst an imperfect
|
||||
past, services that already deliver a different document on their Versioned
|
||||
Endpoints who are concerned with API breakage resulting from changing the
|
||||
payload of their Versioned Version Discovery Document from a single object
|
||||
named ``version`` to a list of objects named ``versions``, it can be
|
||||
nonetheless a step forward to add a link to the list of links provided
|
||||
that points to the Unversioned Discovery Endpoint.
|
||||
|
||||
For services that do not return the Versioned Version Discovery Document
|
||||
inside of an object named ``version`` but instead with the information
|
||||
directly in the root object, it is similarly suggested to add the
|
||||
``collection`` link. (see
|
||||
https://www.iana.org/assignments/link-relations/link-relations.xhtml for
|
||||
the list of defined relation types)
|
||||
|
||||
:download:`Versioned Discovery Schema <versioned-discovery-schema.json>`
|
||||
|
||||
.. literalinclude:: versioned-discovery-schema.json
|
||||
:language: json
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block::
|
||||
|
||||
GET /v2
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"version": {
|
||||
"id": "v2.0",
|
||||
"links": [
|
||||
{
|
||||
"href": "https://image.example.com/v2",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "https://image.example.com/",
|
||||
"rel": "collection"
|
||||
}
|
||||
],
|
||||
"status": "CURRENT"
|
||||
}
|
||||
}
|
||||
|
||||
.. _endpoint-status:
|
||||
|
||||
Endpoint Status
|
||||
---------------
|
||||
|
||||
While it is typical for there to only be a single versioned 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:
|
||||
|
||||
CURRENT
|
||||
The newest API that is currently being developed and improved.
|
||||
Unless you need to support old code, use this API. One and only
|
||||
one API must be marked as CURRENT.
|
||||
|
||||
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.
|
||||
|
||||
.. _version-links:
|
||||
|
||||
Version Links
|
||||
-------------
|
||||
|
||||
.. note:: The ``links`` conform to the :ref:`links` guideline.
|
||||
|
||||
The ``links`` field of the endpoint description should contain at least
|
||||
two entries, listed here by the value of their ``rel`` field.
|
||||
|
||||
self
|
||||
The location of the base endpoint for the given version of the service.
|
||||
|
||||
collection
|
||||
The location of the base endpoint for the Unversioned Version Discovery
|
||||
Endpoint. The ``collection`` entry provides guidance to allow a client to
|
||||
navigate from a Versioned Endpoint that may have been listed in the
|
||||
Service Catalog to the Unversioned Endpoint if they are looking for a
|
||||
different version without resorting to attempting to guess at URL schemes
|
||||
and performing URL manipulation.
|
||||
|
||||
Guidance
|
||||
--------
|
||||
|
||||
|
@ -10,6 +10,8 @@ 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:
|
||||
|
||||
Versioning
|
||||
----------
|
||||
|
||||
@ -43,6 +45,9 @@ 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.
|
||||
|
||||
Services expose information about their minimum and maximum supported
|
||||
microversion range as part of :ref:`version-discovery`.
|
||||
|
||||
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.
|
||||
@ -129,91 +134,6 @@ and not just the body and query parameters. See
|
||||
|
||||
.. _microversion-parse: https://pypi.org/project/microversion_parse
|
||||
|
||||
Version Discovery
|
||||
-----------------
|
||||
|
||||
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 :ref:`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.
|
||||
|
||||
|
15
guidelines/version-discovery-schema.json
Normal file
15
guidelines/version-discovery-schema.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "https://specs.openstack.org/openstack/api-wg/_downloads/unversioned-discovery-schema.json#",
|
||||
"type": "object",
|
||||
"required": ["versions"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"versions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "version-information-schema.json#"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
41
guidelines/version-information-schema.json
Normal file
41
guidelines/version-information-schema.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "https://specs.openstack.org/openstack/api-wg/_downloads/version-information-schema.json#",
|
||||
"type": "object",
|
||||
"additionalProperties":false,
|
||||
"required":[
|
||||
"status",
|
||||
"id",
|
||||
"links"
|
||||
],
|
||||
"properties": {
|
||||
"status": {
|
||||
"description": "Support and lifecycle status of the versioned endpoint.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"CURRENT",
|
||||
"SUPPORTED",
|
||||
"EXPERIMENTAL",
|
||||
"DEPRECATED"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"description": "The major API version.",
|
||||
"type": "string",
|
||||
"pattern": "^v[0-9]{1,2}.?[0-9]{0,2}$"
|
||||
},
|
||||
"links": {
|
||||
"$ref": "http://json-schema.org/draft-04/links#"
|
||||
},
|
||||
"max_version": {
|
||||
"desciption": "The maximum microversion available",
|
||||
"type": "string",
|
||||
"pattern": "^[0-9]{1,2}.[0-9]{1,2}$"
|
||||
},
|
||||
"min_version": {
|
||||
"desciption": "The minimum microversion available",
|
||||
"type": "string",
|
||||
"pattern": "^[0-9]{1,2}.[0-9]{1,2}$"
|
||||
}
|
||||
}
|
||||
}
|
12
guidelines/versioned-discovery-schema.json
Normal file
12
guidelines/versioned-discovery-schema.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "https://specs.openstack.org/openstack/api-wg/_downloads/versioned-discovery-schema.json#",
|
||||
"type": "object",
|
||||
"required": ["version"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"version": {
|
||||
"$ref": "version-information-schema.json#"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user