api-sig/guidelines/consuming-catalog.rst

293 lines
13 KiB
ReStructuredText

.. _consuming-catalog:
=========================
Consuming Service Catalog
=========================
This document describes the process to correctly find a service's endpoint
from the Service Catalog.
.. note:: The process described in this document is compatible with all known
OpenStack Public Clouds and also matches the behavior of the python
library keystoneauth, which is the reference implementation of
authenticating with keystone and consuming information from the
catalog. In some places an argument can be made for a different
process, but given keystoneauth's wide use and reference nature,
we've chosen to keep backwards compatibility with keystoneauth's
behavior rather than design a new perfect process. keystoneauth
itself notes internally places where it kept backwards compatibility
with the libraries that predate it. Notes have been left about
stricter behavior a library or framework could choose to impose.
.. note:: The use of the word "object" in this document refers to a JSON
object, not an Object from any particular programming language.
.. _catalog-user-request:
User Request
============
.. note:: It is worth noting that 'user' is a maleable concept. For instance,
the shade library performs service discovery on behalf of its users
so does not expect its users to provide a 'service-type'. In that
case, shade is the 'user' of the keystoneauth library which is the
discovery implementation. It is definitely not required that all
consumers of OpenStack clouds know all of these things.
The ultimate goal of this process is for a user to find the information about
an endpoint for a service given some inputs. The user will start the process
knowing some number of these parameters. Each additional input expected from
the user without an answer of "where do they learn this information" will
increase the difficulty of a user consuming services, so client libraries and
utilities are strongly encouraged to do whatever they can to be extra helpful
in helping the user ask the right question.
.. note:: Be liberal with what you accept and strict with what you emit.
The following is a list of such pieces of information that can be provided
as user input. When an implementation exposes the ability for a user to
express these parameters it is **STRONGLY** recommended that these names
be used, as they show up across the OpenStack ecosystem and make discussion
easier.
It is assumed that the user has an ``{auth-url}`` and authentication
information. The authentication process itself is out of the scope of this
document.
Required Inputs
---------------
There is one piece of information that is absolutely required that the
user know.
``service-type``
The official name of the service, such as ``compute``, ``image`` or
``block-storage`` as listed in the :doc:`OpenStack Service Types Authority
<consuming-catalog/authority>`.
Required. It is impossible for a user to consume service discovery without
knowing what service they want to discover.
Optional Filters
----------------
There are several optional pieces of information that the user might know,
or additional constraints the user might wish to express to control how the
endpoints for a service are selected.
``region-name``
The region of the service the user desires to work with. May be optional,
depending on whether the cloud has more than one region. Services
all exist within regions, but some clouds only have one region.
If ``{be-strict}`` (see below) has been given, ``{region-name}`` is required.
.. note:: It is highly recommended that ``{region-name}`` always be required
to protect against single-region clouds adding a region in the
future. However, the canonical OpenStack implementation
*keystoneauth* today allows region name to be omitted and there are
a large number of clouds in existence with a single region named
``RegionOne``. For completely new libraries or major versions
where breaking behavior is acceptable, requiring region name
by default would be preferred, but breaking users just to introduce
the restriction is discouraged.
``interface``
Which API interface, such as ``public``, ``internal`` or ``admin``, that
the user wants to use. A user should be able to request a list of interfaces
they find acceptable in the order of their preference, such as
``['internal', 'public']`` (Optional, defaults to ``public``)
``endpoint-version`` OR ``min-endpoint-version``, ``max-endpoint-version``
The **major** version of the service the user desires to work with. Optional.
An endpoint version is inherently a range with a minimum and a maximum value.
Whether it is presented to the user as a single parameter or a pair of
parameters is an implementation detail.
Each endpoint version is a string with one (``3``) or two (``3.1``) numbers,
separated by a dot.
.. warning:: Care has to be taken to not confuse major versions consisting
of two numbers with microversions. Microversions usually exist
within a certain major version, and also have a form of ``X.Y``.
No services currently use both major versions and microversions
in the form of ``X.Y``.
.. TODO(dtantsur): so, what if a service has both major versions in the form
of ``X.Y`` and microversions?
Version strings are not decimals, the are a tuple of 2 numbers combined with
a dot. Therefore, ``3.10`` is higher than ``3.9``.
A user can omit the endpoint-version indicating that they want to use
whatever endpoint is in the ``{service-catalog}``.
A user can desire to work with the latest available version, in which
case the ``{endpoint-version}`` should be ``latest``. If s
``{min-endpoint-version}`` is ``latest``, ``{max-endpoint-version}`` must be
omitted or also ``latest``.
A version can be specified with a minor value of ``latest`` to indicate
the highest minor version of a given major version. For instance,
``3.latest`` would match the highest of ``3.3`` and ``3.4`` but not ``4.0``.
If the parameter is presented as a single string, a single value should be
interpreted as if ``{min-endpoint-version}`` is the value given and
``{max-endpoint-version}`` is ``MAJOR.latest``. For instance, if ``3.4`` is
given as a single value, ``{min-endpoint-version}`` is ``3.4`` and
``{max-endpoint-version}`` is ``3.latest``.
It may seem strange from an individual user perspective to want a range or
``latest`` - but from a library and framework perspective, things like shade
or terraform may have internal logic that can handle more than one version of
a service and want to use the best version available.
.. note:: Guidance around 'latest' is different from that found in
:ref:`the microversion specification
<microversion-client-interaction>`. It is acceptable for a client
library or framework to be interested in the latest version
available but such a specification is internal and not sent to
the server. In the client case with major versions, ``latest`` acts
as an input to the version discovery process.
``service-name``
Arbitrary name given to the service by the deployer. Optional.
.. note:: In all except the most extreme cases this should never be needed
and its use as a meaningful identifier by Deployers is strongly
discouraged. However, the Consumer has no way to otherwise mitigate
the situation if their Deployer has provided them with a catalog
where a ``service-name`` must be used, so ``service-name`` must be
accepted as input.
If ``{be-strict}`` (see below) has been requested, a user supplying
``{service-name}`` should be an error.
``service-id``
Unique identifier for an endpoint in the catalog. Optional.
.. note:: On clouds with well-formed catalogs ``service-id`` should never be
needed. If ``{be-strict}`` has been requested, supplying
``{service-id}`` should be an error.
``endpoint-override``
An endpoint for the service that the user has procured from some other
source. (Optional, defaults to omitted.)
Discovery Behavior Modifiers
----------------------------
The user may also wish to express alterations to the general algorithm.
Implementations may present these flags under any name that makes sense,
or may choose to not present them as behavioral modification options at all.
``be-strict``
Forgo leniant backwards compatibility concessions and be more strict in
input and output validation. Defaults to False.
``skip-discovery``
If the user wants to completely skip the version discovery process even if
logic would otherwise do it. This is useful if the user has specified an
``{endpoint-override}`` or they know they just want to use whatever is in
the catalog and do not need additional metadata about the endpoint. Defaults
to False
``fetch-version-information``
If the user has specified an ``{endpoint-version}`` which can be known to
match just from looking at the URL, the version discovery process will not
fetch version information documents. However, the user may need the
information, such as microversion ranges. Using
``{fetch-version-information}`` allows them to request that the version
document be fetched even when an optimization in the process would otherwise
allow fetching the document to be skipped. Defaults to False.
Discovery Results
=================
At the end of the discovery process, the user should know the following:
If the process was successful:
* The actual values found for all of the input values above.
Found values will be referred to in these documents as ``found-{value}`` to
differentiate. So if a user requested an ``{endpoint-version}`` of
``latest``, ``{found-endpoint-version}`` might be ``3.5``.
* ``service-endpoint``
The endpoint to use as the root of the service.
* ``max-version``
If the service supports microversions, what is the maximum microversion the
service supports. Optional, defaults to omitted, which implies that
microversions are not supported.
* ``min-version``
If the service supports microversions, what is the minimum microversion the
service supports. Optional, defaults to omitted, which implies that
microversions are not supported.
If the process was unsuccessful, an error should be returned explaining which
part failed. For instance, was a matching service not found at all or was
a matching version not found. If a matching version was not found, the error
should contain a list of version that were found.
In the description that follows, each of the above inputs and outputs will
be referred to like ``{endpoint-override}`` so that it is clear whether a user
supplied input to the process or one of the expected outputs is being
discussed. Other values that are fetched at one point in the process and
referred to at a later point are similarly referred to like
``{service-catalog}``. Names will not be reused within the process to
hold different content at different times.
Discovery Algorithm
===================
Services should be registered in the ``{service-catalog}`` using their
``{service-type}`` from the :doc:`OpenStack Service Types Authority
<consuming-catalog/authority>`. However, for historical reasons there are some
services that have old service types found in the wild. To facilitate moving
forward with the correct ``{service-type}`` names, but also support existing
users and installations, the OpenStack Service Types Authority contains a list
of historical aliases for such services.
Clients will need a copy of the data published in the
OpenStack Service Types Authority to be able to complete the full Discovery
Algorithm. A client library could either keep a local copy or fetch the data
from https://service-types.openstack.org/service-types.json and potentially
cache it. It is recommended that client libraries handle consumption of the
historical data for their users but also allow some mechanism for the user to
provide a more up to date verison of the data if necessary.
The basic process is:
#. Authenticate to keystone at the ``{auth-url}``, retreiving a ``token``
which contains the ``{service-catalog}``.
.. note:: This step is obviously skipped for clouds without authentication.
#. If the user has provided ``{endpoint-override}``, it is used as
``{catalog-endpoint}``.
#. If the user has not provided ``{endpoint-override}``, retrieve matching
``{catalog-endpoint}`` from the ``{service-catalog}`` using the procedure
explained in :doc:`consuming-catalog/endpoint`.
#. If ``{skip-discovery}`` is true, STOP and use ``{catalog-endpoint}`` as
``{service-endpoint}``. Otherwise, discover the available API versions
and find the suitable ``{service-endpoint}`` using the version discovery
procedure from :doc:`consuming-catalog/version-discovery`.
#. If the requested ``{service-type}`` is an alias of an official type in the
OpenStack Service Types Authority and any endpoints match the official
type, :ref:`find-endpoint-matching-best-service-type`.
Table of Contents
=================
.. toctree::
consuming-catalog/endpoint
consuming-catalog/version-discovery
consuming-catalog/authority