Expose allow parameters for URL discovery
The Discover class can fiilter API versions by experimental status, deprecated status, and unknown status, and potentially more designations in the future. The parameters that control this were not exposed in the Session or Adapter, so users could not take advantage of this filtering through normal means. This patch creates an 'allow' parameter for the Adapter that will get passed down as keyword arguments into Discover.raw_version_data(). Now, given an unversioned endpoint like: $ openstack endpoint show cinder +--------------+----------------------------------+ | Field | Value | +--------------+----------------------------------+ | adminurl | http://192.168.122.183:8776 | | enabled | True | | id | 485107c1d92b41829c331a2dc82aaaeb | | internalurl | http://192.168.122.183:8776 | | publicurl | http://192.168.122.183:8776 | | region | RegionOne | | service_id | 01b4f36a173d4c59b31fc95763095373 | | service_name | cinder | | service_type | volume | +--------------+----------------------------------+ an Adapter can be used like this (this example would be expected to fail since it disallows the deprecated volume V1 API): auth = Password(<auth_params>) sess = session.Session(auth=auth) adptr = adapter.Adapter(sess) adptr.get('<project-id>/volumes', endpoint_filter={'service_type': 'volume', 'interface': 'public', 'version': 1}, allow={'allow_deprecated': False})) This is inspired by an abandoned patch to keystoneclient[1] that exposed this information as a tuple. The problem with exposing it like that is that raw_version_data() defaults allow_deprecated to True, so including 'deprecated' in the tuple or not including it would have the same result. Using a dict allows us to keep the Discover interface the same. [1] https://review.openstack.org/#/c/130159 Co-authored-by: Endre Karlson <endre.karlson@hp.com> Change-Id: I54c29e1c2a4a2b02a3967f4ea108b8d2533616eb Closes-bug: #1394245
This commit is contained in:
parent
f6e57bc706
commit
118c9629e5
@ -158,7 +158,24 @@ The endpoint filter is a simple key-value filter and can be provided with any
|
||||
number of arguments. It is then up to the auth plugin to correctly use the
|
||||
parameters it understands.
|
||||
|
||||
The session object determines the URL matching the filter and append to it the
|
||||
If you want to further limit your service discovery by allowing experimental
|
||||
APIs or disallowing deprecated APIs, you can use the ``allow`` parameter::
|
||||
|
||||
>>> resp = session.get('/<project-id>/volumes',
|
||||
endpoint_filter={'service_type': 'volume',
|
||||
'interface': 'public',
|
||||
'version': 1},
|
||||
allow={'allow_deprecated': False})
|
||||
|
||||
The discoverable types of endpoints that `allow` can recognize are:
|
||||
|
||||
- `allow_deprecated`: Allow experimental version endpoints.
|
||||
|
||||
- `allow_experimental`: Allow deprecated version endpoints.
|
||||
|
||||
- `allow_unknown`: Allow endpoints with an unrecognised status.
|
||||
|
||||
The session object determines the URL matching the filters and append to it the
|
||||
provided path and so create a valid request. If multiple URL matches are found
|
||||
then any one may be chosen.
|
||||
|
||||
|
@ -43,13 +43,15 @@ class Adapter(object):
|
||||
:param logger: A logging object to use for requests that pass through this
|
||||
adapter.
|
||||
:type logger: logging.Logger
|
||||
:param dict allow: Extra filters to pass when discovering API versions.
|
||||
(optional)
|
||||
"""
|
||||
|
||||
@positional()
|
||||
def __init__(self, session, service_type=None, service_name=None,
|
||||
interface=None, region_name=None, endpoint_override=None,
|
||||
version=None, auth=None, user_agent=None,
|
||||
connect_retries=None, logger=None):
|
||||
connect_retries=None, logger=None, allow={}):
|
||||
# NOTE(jamielennox): when adding new parameters to adapter please also
|
||||
# add them to the adapter call in httpclient.HTTPClient.__init__ as
|
||||
# well as to load_adapter_from_argparse below if the argument is
|
||||
@ -66,6 +68,7 @@ class Adapter(object):
|
||||
self.auth = auth
|
||||
self.connect_retries = connect_retries
|
||||
self.logger = logger
|
||||
self.allow = allow
|
||||
|
||||
def _set_endpoint_filter_kwargs(self, kwargs):
|
||||
if self.service_type:
|
||||
@ -94,6 +97,8 @@ class Adapter(object):
|
||||
kwargs.setdefault('connect_retries', self.connect_retries)
|
||||
if self.logger:
|
||||
kwargs.setdefault('logger', self.logger)
|
||||
if self.allow:
|
||||
kwargs.setdefault('allow', self.allow)
|
||||
|
||||
return self.session.request(url, method, **kwargs)
|
||||
|
||||
|
@ -158,7 +158,7 @@ class BaseIdentityPlugin(plugin.BaseAuthPlugin):
|
||||
|
||||
def get_endpoint(self, session, service_type=None, interface=None,
|
||||
region_name=None, service_name=None, version=None,
|
||||
**kwargs):
|
||||
allow={}, **kwargs):
|
||||
"""Return a valid endpoint for a service.
|
||||
|
||||
If a valid token is not present then a new one will be fetched using
|
||||
@ -180,6 +180,8 @@ class BaseIdentityPlugin(plugin.BaseAuthPlugin):
|
||||
(optional)
|
||||
:param tuple version: The minimum version number required for this
|
||||
endpoint. (optional)
|
||||
:param dict allow: Extra filters to pass when discovering API
|
||||
versions. (optional)
|
||||
|
||||
:raises keystoneauth1.exceptions.http.HttpError: An error from an
|
||||
invalid HTTP response.
|
||||
@ -237,7 +239,7 @@ class BaseIdentityPlugin(plugin.BaseAuthPlugin):
|
||||
'Fallback to using that endpoint as the base url.',
|
||||
url)
|
||||
else:
|
||||
url = disc.url_for(version)
|
||||
url = disc.url_for(version, **allow)
|
||||
|
||||
return url
|
||||
|
||||
|
@ -291,7 +291,7 @@ class Session(object):
|
||||
endpoint_filter=None, auth=None, requests_auth=None,
|
||||
raise_exc=True, allow_reauth=True, log=True,
|
||||
endpoint_override=None, connect_retries=0, logger=_logger,
|
||||
**kwargs):
|
||||
allow={}, **kwargs):
|
||||
"""Send an HTTP request with the specified characteristics.
|
||||
|
||||
Wrapper around `requests.Session.request` to handle tasks such as
|
||||
@ -357,6 +357,8 @@ class Session(object):
|
||||
If not provided the keystoneauth1.session default
|
||||
logger will be used.
|
||||
:type logger: logging.Logger
|
||||
:param dict allow: Extra filters to pass when discovering API
|
||||
versions. (optional)
|
||||
:param kwargs: any other parameter that can be passed to
|
||||
:meth:`requests.Session.request` (such as `headers`).
|
||||
Except:
|
||||
@ -398,7 +400,8 @@ class Session(object):
|
||||
if endpoint_override:
|
||||
base_url = endpoint_override % _StringFormatter(self, auth)
|
||||
elif endpoint_filter:
|
||||
base_url = self.get_endpoint(auth, **endpoint_filter)
|
||||
base_url = self.get_endpoint(auth, allow=allow,
|
||||
**endpoint_filter)
|
||||
|
||||
if not base_url:
|
||||
raise exceptions.EndpointNotFound()
|
||||
|
@ -717,6 +717,9 @@ class AdapterTest(utils.TestCase):
|
||||
REGION_NAME = uuid.uuid4().hex
|
||||
USER_AGENT = uuid.uuid4().hex
|
||||
VERSION = uuid.uuid4().hex
|
||||
ALLOW = {'allow_deprecated': False,
|
||||
'allow_experimental': True,
|
||||
'allow_unknown': True}
|
||||
|
||||
TEST_URL = CalledAuthPlugin.ENDPOINT
|
||||
|
||||
@ -730,7 +733,8 @@ class AdapterTest(utils.TestCase):
|
||||
interface=self.INTERFACE,
|
||||
region_name=self.REGION_NAME,
|
||||
user_agent=self.USER_AGENT,
|
||||
version=self.VERSION)
|
||||
version=self.VERSION,
|
||||
allow=self.ALLOW)
|
||||
|
||||
def _verify_endpoint_called(self, adpt):
|
||||
self.assertEqual(self.SERVICE_TYPE,
|
||||
@ -752,6 +756,8 @@ class AdapterTest(utils.TestCase):
|
||||
self.assertEqual(resp.text, response)
|
||||
|
||||
self._verify_endpoint_called(adpt)
|
||||
self.assertEqual(self.ALLOW,
|
||||
adpt.auth.endpoint_arguments['allow'])
|
||||
self.assertTrue(adpt.auth.get_token_called)
|
||||
self.assertRequestHeaderEqual('User-Agent', self.USER_AGENT)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user