From 127d7be2b73cdc30ad388e992edba371f0c19f26 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 2 Aug 2024 11:33:43 +0100 Subject: [PATCH] Apply ruff, ruff-format We disable the E203 (whitespace before ':') and E501 (line too long) linter rules since these conflict with ruff-format. We also rework a statement in 'keystoneauth1/tests/unit/test_session.py' since it's triggering a bug in flake8 [1] that is currently (at time of authoring) unresolved. [1] https://github.com/PyCQA/flake8/issues/1948 Signed-off-by: Stephen Finucane Change-Id: Ief5c1c57d1e72db9fc881063d4c7e1030e76da43 --- doc/ext/list_plugins.py | 6 +- doc/source/conf.py | 2 +- keystoneauth1/_fair_semaphore.py | 2 +- keystoneauth1/_utils.py | 4 +- keystoneauth1/access/__init__.py | 10 +- keystoneauth1/access/access.py | 16 +- keystoneauth1/access/service_catalog.py | 196 +- keystoneauth1/access/service_providers.py | 14 +- keystoneauth1/adapter.py | 188 +- keystoneauth1/discover.py | 471 ++-- keystoneauth1/exceptions/auth.py | 4 +- keystoneauth1/exceptions/auth_plugins.py | 22 +- keystoneauth1/exceptions/base.py | 2 +- keystoneauth1/exceptions/catalog.py | 4 +- keystoneauth1/exceptions/connection.py | 16 +- keystoneauth1/exceptions/discovery.py | 29 +- keystoneauth1/exceptions/http.py | 113 +- keystoneauth1/exceptions/oidc.py | 16 +- keystoneauth1/exceptions/response.py | 2 +- keystoneauth1/exceptions/service_providers.py | 4 +- keystoneauth1/extras/_saml2/_loading.py | 76 +- keystoneauth1/extras/_saml2/v3/adfs.py | 255 ++- keystoneauth1/extras/_saml2/v3/base.py | 28 +- keystoneauth1/extras/_saml2/v3/saml2.py | 118 +- keystoneauth1/extras/kerberos/__init__.py | 22 +- keystoneauth1/extras/kerberos/_loading.py | 62 +- keystoneauth1/extras/oauth1/_loading.py | 37 +- keystoneauth1/extras/oauth1/v3.py | 45 +- keystoneauth1/fixture/__init__.py | 23 +- keystoneauth1/fixture/discovery.py | 87 +- keystoneauth1/fixture/keystoneauth_betamax.py | 36 +- keystoneauth1/fixture/plugin.py | 47 +- keystoneauth1/fixture/serializer.py | 23 +- keystoneauth1/fixture/v2.py | 57 +- keystoneauth1/fixture/v3.py | 159 +- keystoneauth1/hacking/checks.py | 10 +- keystoneauth1/http_basic.py | 7 +- keystoneauth1/identity/__init__.py | 36 +- keystoneauth1/identity/access.py | 3 +- keystoneauth1/identity/base.py | 188 +- keystoneauth1/identity/generic/__init__.py | 5 +- keystoneauth1/identity/generic/base.py | 144 +- keystoneauth1/identity/generic/password.py | 45 +- keystoneauth1/identity/generic/token.py | 4 +- keystoneauth1/identity/v2.py | 63 +- keystoneauth1/identity/v3/__init__.py | 63 +- .../identity/v3/application_credential.py | 25 +- keystoneauth1/identity/v3/base.py | 108 +- keystoneauth1/identity/v3/federation.py | 32 +- keystoneauth1/identity/v3/k2k.py | 61 +- keystoneauth1/identity/v3/multi_factor.py | 7 +- .../identity/v3/oauth2_client_credential.py | 34 +- .../v3/oauth2_mtls_client_credential.py | 51 +- keystoneauth1/identity/v3/oidc.py | 301 ++- keystoneauth1/identity/v3/password.py | 17 +- keystoneauth1/identity/v3/receipt.py | 2 +- keystoneauth1/identity/v3/token.py | 2 +- keystoneauth1/identity/v3/tokenless_auth.py | 35 +- keystoneauth1/identity/v3/totp.py | 15 +- keystoneauth1/loading/__init__.py | 9 +- keystoneauth1/loading/_plugins/admin_token.py | 26 +- keystoneauth1/loading/_plugins/http_basic.py | 33 +- .../loading/_plugins/identity/generic.py | 45 +- keystoneauth1/loading/_plugins/identity/v2.py | 38 +- keystoneauth1/loading/_plugins/identity/v3.py | 496 ++-- keystoneauth1/loading/_plugins/noauth.py | 15 +- keystoneauth1/loading/_utils.py | 10 +- keystoneauth1/loading/adapter.py | 259 ++- keystoneauth1/loading/base.py | 48 +- keystoneauth1/loading/cli.py | 36 +- keystoneauth1/loading/conf.py | 18 +- keystoneauth1/loading/identity.py | 190 +- keystoneauth1/loading/opts.py | 74 +- keystoneauth1/loading/session.py | 135 +- keystoneauth1/plugin.py | 46 +- keystoneauth1/service_token.py | 3 +- keystoneauth1/session.py | 456 ++-- .../tests/unit/access/test_v2_access.py | 25 +- .../unit/access/test_v2_service_catalog.py | 190 +- .../tests/unit/access/test_v3_access.py | 36 +- .../unit/access/test_v3_service_catalog.py | 461 ++-- keystoneauth1/tests/unit/client_fixtures.py | 94 +- .../tests/unit/exceptions/test_exceptions.py | 7 +- .../tests/unit/extras/kerberos/base.py | 5 +- .../extras/kerberos/test_fedkerb_loading.py | 42 +- .../extras/kerberos/test_kerberos_loading.py | 30 +- .../tests/unit/extras/kerberos/test_mapped.py | 71 +- .../tests/unit/extras/kerberos/test_v3.py | 22 +- .../tests/unit/extras/kerberos/utils.py | 69 +- .../tests/unit/extras/oauth1/test_oauth1.py | 92 +- .../unit/extras/oauth1/test_oauth1_loading.py | 29 +- .../unit/extras/saml2/fixtures/__init__.py | 59 +- .../tests/unit/extras/saml2/test_auth_adfs.py | 195 +- .../unit/extras/saml2/test_auth_saml2.py | 257 ++- .../tests/unit/extras/saml2/utils.py | 3 +- .../tests/unit/identity/test_access.py | 20 +- .../unit/identity/test_identity_common.py | 2038 +++++++++-------- .../tests/unit/identity/test_identity_v2.py | 403 ++-- .../tests/unit/identity/test_identity_v3.py | 1138 +++++---- .../identity/test_identity_v3_federation.py | 190 +- .../unit/identity/test_identity_v3_oidc.py | 314 ++- .../tests/unit/identity/test_password.py | 71 +- .../tests/unit/identity/test_token.py | 33 +- .../unit/identity/test_tokenless_auth.py | 86 +- keystoneauth1/tests/unit/identity/utils.py | 59 +- keystoneauth1/tests/unit/k2k_fixtures.py | 22 +- .../tests/unit/loading/test_adapter.py | 230 +- keystoneauth1/tests/unit/loading/test_cli.py | 69 +- keystoneauth1/tests/unit/loading/test_conf.py | 145 +- .../tests/unit/loading/test_entry_points.py | 5 +- .../tests/unit/loading/test_fixtures.py | 36 +- .../tests/unit/loading/test_generic.py | 68 +- .../tests/unit/loading/test_loading.py | 44 +- .../tests/unit/loading/test_session.py | 23 +- keystoneauth1/tests/unit/loading/test_v3.py | 435 ++-- keystoneauth1/tests/unit/loading/utils.py | 17 +- keystoneauth1/tests/unit/matchers.py | 18 +- keystoneauth1/tests/unit/oidc_fixtures.py | 32 +- .../tests/unit/test_betamax_fixture.py | 18 +- .../tests/unit/test_betamax_hooks.py | 115 +- .../tests/unit/test_betamax_serializer.py | 23 +- keystoneauth1/tests/unit/test_discovery.py | 1162 +++++----- .../tests/unit/test_fair_sempahore.py | 3 +- keystoneauth1/tests/unit/test_fixtures.py | 129 +- .../tests/unit/test_hacking_checks.py | 7 +- keystoneauth1/tests/unit/test_http_basic.py | 9 +- keystoneauth1/tests/unit/test_matchers.py | 4 +- keystoneauth1/tests/unit/test_noauth.py | 1 - .../tests/unit/test_service_token.py | 74 +- keystoneauth1/tests/unit/test_session.py | 1208 ++++++---- .../tests/unit/test_token_endpoint.py | 14 +- keystoneauth1/tests/unit/test_utils.py | 7 +- keystoneauth1/tests/unit/utils.py | 7 +- keystoneauth1/token_endpoint.py | 17 +- releasenotes/source/conf.py | 7 +- setup.py | 4 +- tox.ini | 8 +- 137 files changed, 8999 insertions(+), 6392 deletions(-) diff --git a/doc/ext/list_plugins.py b/doc/ext/list_plugins.py index 0998084a..8e540fc8 100644 --- a/doc/ext/list_plugins.py +++ b/doc/ext/list_plugins.py @@ -35,7 +35,7 @@ class ListAuthPluginsDirective(rst.Directive): has_content = True def report_load_failure(mgr, ep, err): - LOG.warning(u'Failed to load %s: %s' % (ep.module_name, err)) + LOG.warning(f'Failed to load {ep.module_name}: {err}') def display_plugin(self, ext): overline_style = self.options.get('overline-style', '') @@ -60,7 +60,7 @@ def display_plugin(self, ext): yield "\n" for opt in ext.obj.get_options(): - yield ":%s: %s" % (opt.name, opt.help) + yield f":{opt.name}: {opt.help}" yield "\n" @@ -68,7 +68,7 @@ def run(self): mgr = extension.ExtensionManager( 'keystoneauth1.plugin', on_load_failure_callback=self.report_load_failure, - invoke_on_load=True, + invoke_on_load=True, ) result = ViewList() diff --git a/doc/source/conf.py b/doc/source/conf.py index 48306f79..3848add6 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -81,7 +81,7 @@ 'Openstack Developers', 'manual', True, - ), + ) ] # Disable usage of xindy https://bugzilla.redhat.com/show_bug.cgi?id=1643664 diff --git a/keystoneauth1/_fair_semaphore.py b/keystoneauth1/_fair_semaphore.py index e7e2fdc3..96c2e133 100644 --- a/keystoneauth1/_fair_semaphore.py +++ b/keystoneauth1/_fair_semaphore.py @@ -15,7 +15,7 @@ import time -class FairSemaphore(object): +class FairSemaphore: """Semaphore class that notifies in order of request. We cannot use a normal Semaphore because it doesn't give any ordering, diff --git a/keystoneauth1/_utils.py b/keystoneauth1/_utils.py index c010c109..bd0c7446 100644 --- a/keystoneauth1/_utils.py +++ b/keystoneauth1/_utils.py @@ -78,7 +78,7 @@ def before_utcnow(**timedelta_kwargs): # Detect if running on the Windows Subsystem for Linux try: - with open('/proc/version', 'r') as f: + with open('/proc/version') as f: is_windows_linux_subsystem = 'microsoft' in f.read().lower() -except IOError: +except OSError: is_windows_linux_subsystem = False diff --git a/keystoneauth1/access/__init__.py b/keystoneauth1/access/__init__.py index b7e474a4..c349e183 100644 --- a/keystoneauth1/access/__init__.py +++ b/keystoneauth1/access/__init__.py @@ -13,7 +13,9 @@ from keystoneauth1.access.access import * # noqa -__all__ = ('AccessInfo', # noqa: F405 - 'AccessInfoV2', # noqa: F405 - 'AccessInfoV3', # noqa: F405 - 'create') # noqa: F405 +__all__ = ( # noqa: F405 + 'AccessInfo', + 'AccessInfoV2', + 'AccessInfoV3', + 'create', +) diff --git a/keystoneauth1/access/access.py b/keystoneauth1/access/access.py index 4a9d83c5..29b16054 100644 --- a/keystoneauth1/access/access.py +++ b/keystoneauth1/access/access.py @@ -25,10 +25,7 @@ STALE_TOKEN_DURATION = 30 -__all__ = ('AccessInfo', - 'AccessInfoV2', - 'AccessInfoV3', - 'create') +__all__ = ('AccessInfo', 'AccessInfoV2', 'AccessInfoV3', 'create') def create(resp=None, body=None, auth_token=None): @@ -47,7 +44,6 @@ def create(resp=None, body=None, auth_token=None): def _missingproperty(f): - @functools.wraps(f) def inner(self): try: @@ -58,7 +54,7 @@ def inner(self): return property(inner) -class AccessInfo(object): +class AccessInfo: """Encapsulates a raw authentication token from keystone. Provides helper methods for extracting useful values from that token. @@ -77,7 +73,8 @@ def __init__(self, body, auth_token=None): def service_catalog(self): if not self._service_catalog: self._service_catalog = self._service_catalog_class.from_token( - self._data) + self._data + ) return self._service_catalog @@ -422,7 +419,7 @@ def has_service_catalog(self): @_missingproperty def auth_token(self): - set_token = super(AccessInfoV2, self).auth_token + set_token = super().auth_token return set_token or self._data['access']['token']['id'] @property @@ -775,7 +772,8 @@ def audit_chain_id(self): def service_providers(self): if not self._service_providers: self._service_providers = ( - service_providers.ServiceProviders.from_token(self._data)) + service_providers.ServiceProviders.from_token(self._data) + ) return self._service_providers diff --git a/keystoneauth1/access/service_catalog.py b/keystoneauth1/access/service_catalog.py index c4ab694b..09cfc91e 100644 --- a/keystoneauth1/access/service_catalog.py +++ b/keystoneauth1/access/service_catalog.py @@ -114,7 +114,8 @@ def normalize_catalog(self): service.setdefault('id', None) service['endpoints'] = self._normalize_endpoints( - service.get('endpoints', [])) + service.get('endpoints', []) + ) for endpoint in service['endpoints']: endpoint['region_name'] = self._get_endpoint_region(endpoint) @@ -129,9 +130,15 @@ def _get_interface_list(self, interface): interface = [interface] return [self.normalize_interface(i) for i in interface] - def get_endpoints_data(self, service_type=None, interface=None, - region_name=None, service_name=None, - service_id=None, endpoint_id=None): + def get_endpoints_data( + self, + service_type=None, + interface=None, + region_name=None, + service_name=None, + service_id=None, + endpoint_id=None, + ): """Fetch and filter endpoint data for the specified service(s). Returns endpoints for the specified service (or all) containing @@ -164,17 +171,19 @@ def get_endpoints_data(self, service_type=None, interface=None, matching_endpoints = {} for service in self.normalize_catalog(): - if service_type and not discover._SERVICE_TYPES.is_match( - service_type, service['type']): + service_type, service['type'] + ): continue - if (service_name and service['name'] and - service_name != service['name']): + if ( + service_name + and service['name'] + and service_name != service['name'] + ): continue - if (service_id and service['id'] and - service_id != service['id']): + if service_id and service['id'] and service_id != service['id']: continue matching_endpoints.setdefault(service['type'], []) @@ -198,7 +207,9 @@ def get_endpoints_data(self, service_type=None, interface=None, interface=endpoint['interface'], region_name=endpoint['region_name'], endpoint_id=endpoint['id'], - raw_endpoint=endpoint['raw_endpoint'])) + raw_endpoint=endpoint['raw_endpoint'], + ) + ) if not interfaces: return self._endpoints_by_type(service_type, matching_endpoints) @@ -212,8 +223,9 @@ def get_endpoints_data(self, service_type=None, interface=None, for endpoint in endpoints: matches_by_interface.setdefault(endpoint.interface, []) matches_by_interface[endpoint.interface].append(endpoint) - best_interface = [i for i in interfaces - if i in matches_by_interface.keys()][0] + best_interface = [ + i for i in interfaces if i in matches_by_interface.keys() + ][0] ret[matched_service_type] = matches_by_interface[best_interface] return self._endpoints_by_type(service_type, ret) @@ -279,9 +291,15 @@ def _endpoints_by_type(self, requested, endpoints): # part if we do. Raise this so that we can panic in unit tests. raise ValueError("Programming error choosing an endpoint.") - def get_endpoints(self, service_type=None, interface=None, - region_name=None, service_name=None, - service_id=None, endpoint_id=None): + def get_endpoints( + self, + service_type=None, + interface=None, + region_name=None, + service_name=None, + service_id=None, + endpoint_id=None, + ): """Fetch and filter endpoint data for the specified service(s). Returns endpoints for the specified service (or all) containing @@ -294,17 +312,27 @@ def get_endpoints(self, service_type=None, interface=None, Returns a dict keyed by service_type with a list of endpoint dicts """ endpoints_data = self.get_endpoints_data( - service_type=service_type, interface=interface, - region_name=region_name, service_name=service_name, - service_id=service_id, endpoint_id=endpoint_id) + service_type=service_type, + interface=interface, + region_name=region_name, + service_name=service_name, + service_id=service_id, + endpoint_id=endpoint_id, + ) endpoints = {} for service_type, data in endpoints_data.items(): endpoints[service_type] = self._denormalize_endpoints(data) return endpoints - def get_endpoint_data_list(self, service_type=None, interface='public', - region_name=None, service_name=None, - service_id=None, endpoint_id=None): + def get_endpoint_data_list( + self, + service_type=None, + interface='public', + region_name=None, + service_name=None, + service_id=None, + endpoint_id=None, + ): """Fetch a flat list of matching EndpointData objects. Fetch the endpoints from the service catalog for a particular @@ -327,17 +355,25 @@ def get_endpoint_data_list(self, service_type=None, interface='public', :returns: a list of matching EndpointData objects :rtype: list(`keystoneauth1.discover.EndpointData`) """ - endpoints = self.get_endpoints_data(service_type=service_type, - interface=interface, - region_name=region_name, - service_name=service_name, - service_id=service_id, - endpoint_id=endpoint_id) + endpoints = self.get_endpoints_data( + service_type=service_type, + interface=interface, + region_name=region_name, + service_name=service_name, + service_id=service_id, + endpoint_id=endpoint_id, + ) return [endpoint for data in endpoints.values() for endpoint in data] - def get_urls(self, service_type=None, interface='public', - region_name=None, service_name=None, - service_id=None, endpoint_id=None): + def get_urls( + self, + service_type=None, + interface='public', + region_name=None, + service_name=None, + service_id=None, + endpoint_id=None, + ): """Fetch endpoint urls from the service catalog. Fetch the urls of endpoints from the service catalog for a particular @@ -359,17 +395,25 @@ def get_urls(self, service_type=None, interface='public', :returns: tuple of urls """ - endpoints = self.get_endpoint_data_list(service_type=service_type, - interface=interface, - region_name=region_name, - service_name=service_name, - service_id=service_id, - endpoint_id=endpoint_id) + endpoints = self.get_endpoint_data_list( + service_type=service_type, + interface=interface, + region_name=region_name, + service_name=service_name, + service_id=service_id, + endpoint_id=endpoint_id, + ) return tuple([endpoint.url for endpoint in endpoints]) - def url_for(self, service_type=None, interface='public', - region_name=None, service_name=None, - service_id=None, endpoint_id=None): + def url_for( + self, + service_type=None, + interface='public', + region_name=None, + service_name=None, + service_id=None, + endpoint_id=None, + ): """Fetch an endpoint from the service catalog. Fetch the specified endpoint from the service catalog for @@ -389,16 +433,24 @@ def url_for(self, service_type=None, interface='public', :param string service_id: The identifier of a service. :param string endpoint_id: The identifier of an endpoint. """ - return self.endpoint_data_for(service_type=service_type, - interface=interface, - region_name=region_name, - service_name=service_name, - service_id=service_id, - endpoint_id=endpoint_id).url - - def endpoint_data_for(self, service_type=None, interface='public', - region_name=None, service_name=None, - service_id=None, endpoint_id=None): + return self.endpoint_data_for( + service_type=service_type, + interface=interface, + region_name=region_name, + service_name=service_name, + service_id=service_id, + endpoint_id=endpoint_id, + ).url + + def endpoint_data_for( + self, + service_type=None, + interface='public', + region_name=None, + service_name=None, + service_id=None, + endpoint_id=None, + ): """Fetch endpoint data from the service catalog. Fetch the specified endpoint data from the service catalog for @@ -427,34 +479,30 @@ def endpoint_data_for(self, service_type=None, interface='public', region_name=region_name, service_name=service_name, service_id=service_id, - endpoint_id=endpoint_id) + endpoint_id=endpoint_id, + ) if endpoint_data_list: return endpoint_data_list[0] if service_name and region_name: - msg = ('%(interface)s endpoint for %(service_type)s service ' - 'named %(service_name)s in %(region_name)s region not ' - 'found' % - {'interface': interface, - 'service_type': service_type, 'service_name': service_name, - 'region_name': region_name}) + msg = ( + f'{interface} endpoint for {service_type} service ' + f'named {service_name} in {region_name} region not ' + 'found' + ) elif service_name: - msg = ('%(interface)s endpoint for %(service_type)s service ' - 'named %(service_name)s not found' % - {'interface': interface, - 'service_type': service_type, - 'service_name': service_name}) + msg = ( + f'{interface} endpoint for {service_type} service ' + f'named {service_name} not found' + ) elif region_name: - msg = ('%(interface)s endpoint for %(service_type)s service ' - 'in %(region_name)s region not found' % - {'interface': interface, - 'service_type': service_type, 'region_name': region_name}) + msg = ( + f'{interface} endpoint for {service_type} service ' + f'in {region_name} region not found' + ) else: - msg = ('%(interface)s endpoint for %(service_type)s service ' - 'not found' % - {'interface': interface, - 'service_type': service_type}) + msg = f'{interface} endpoint for {service_type} service not found' raise exceptions.EndpointNotFound(msg) @@ -498,8 +546,9 @@ def _normalize_endpoints(self, endpoints): for endpoint in endpoints: raw_endpoint = endpoint.copy() interface_urls = {} - interface_keys = [key for key in endpoint.keys() - if key.endswith('URL')] + interface_keys = [ + key for key in endpoint.keys() if key.endswith('URL') + ] for key in interface_keys: interface = self.normalize_interface(key) interface_urls[interface] = endpoint.pop(key) @@ -522,8 +571,7 @@ def _denormalize_endpoints(self, endpoints): :returns: List of endpoint description dicts in original catalog format """ - raw_endpoints = super(ServiceCatalogV2, self)._denormalize_endpoints( - endpoints) + raw_endpoints = super()._denormalize_endpoints(endpoints) # The same raw endpoint content will be in the list once for each # v2 endpoint_type entry. We only need one of them in the resulting # list. So keep a list of the string versions. diff --git a/keystoneauth1/access/service_providers.py b/keystoneauth1/access/service_providers.py index 83a27ccd..99d4614d 100644 --- a/keystoneauth1/access/service_providers.py +++ b/keystoneauth1/access/service_providers.py @@ -13,22 +13,24 @@ from keystoneauth1 import exceptions -class ServiceProviders(object): +class ServiceProviders: """Helper methods for dealing with Service Providers.""" @classmethod def from_token(cls, token): if 'token' not in token: - raise ValueError('Token format does not support service' - 'providers.') + raise ValueError( + 'Token format does not support service providers.' + ) return cls(token['token'].get('service_providers', [])) def __init__(self, service_providers): - def normalize(service_providers_list): - return dict((sp['id'], sp) for sp in service_providers_list - if 'id' in sp) + return { + sp['id']: sp for sp in service_providers_list if 'id' in sp + } + self._service_providers = normalize(service_providers) def _get_service_provider(self, sp_id): diff --git a/keystoneauth1/adapter.py b/keystoneauth1/adapter.py index 3856b9a4..a4c1d8cd 100644 --- a/keystoneauth1/adapter.py +++ b/keystoneauth1/adapter.py @@ -19,7 +19,7 @@ from keystoneauth1 import session -class Adapter(object): +class Adapter: """An instance of a session with local variables. A session is a global object that is shared around amongst many clients. It @@ -118,23 +118,41 @@ class Adapter(object): client_name = None client_version = None - 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, allow=None, - additional_headers=None, client_name=None, - client_version=None, allow_version_hack=None, - global_request_id=None, - min_version=None, max_version=None, - default_microversion=None, status_code_retries=None, - retriable_status_codes=None, raise_exc=None, - rate_limit=None, concurrency=None, - connect_retry_delay=None, status_code_retry_delay=None, - ): + 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, + allow=None, + additional_headers=None, + client_name=None, + client_version=None, + allow_version_hack=None, + global_request_id=None, + min_version=None, + max_version=None, + default_microversion=None, + status_code_retries=None, + retriable_status_codes=None, + raise_exc=None, + rate_limit=None, + concurrency=None, + connect_retry_delay=None, + status_code_retry_delay=None, + ): if version and (min_version or max_version): raise TypeError( "version is mutually exclusive with min_version and" - " max_version") + " max_version" + ) # 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 @@ -177,7 +195,8 @@ def __init__(self, session, service_type=None, service_name=None, rate_delay = 1.0 / rate_limit self._rate_semaphore = _fair_semaphore.FairSemaphore( - concurrency, rate_delay) + concurrency, rate_delay + ) def _set_endpoint_filter_kwargs(self, kwargs): if self.service_type: @@ -205,7 +224,8 @@ def request(self, url, method, **kwargs): # case insensitive. if kwargs.get('headers'): kwargs['headers'] = requests.structures.CaseInsensitiveDict( - kwargs['headers']) + kwargs['headers'] + ) else: kwargs['headers'] = requests.structures.CaseInsensitiveDict() if self.endpoint_override: @@ -215,9 +235,13 @@ def request(self, url, method, **kwargs): kwargs.setdefault('auth', self.auth) if self.user_agent: kwargs.setdefault('user_agent', self.user_agent) - for arg in ('connect_retries', 'status_code_retries', - 'connect_retry_delay', 'status_code_retry_delay', - 'retriable_status_codes'): + for arg in ( + 'connect_retries', + 'status_code_retries', + 'connect_retry_delay', + 'status_code_retry_delay', + 'retriable_status_codes', + ): if getattr(self, arg) is not None: kwargs.setdefault(arg, getattr(self, arg)) if self.logger: @@ -239,15 +263,18 @@ def request(self, url, method, **kwargs): kwargs.setdefault('rate_semaphore', self._rate_semaphore) else: - warnings.warn('Using keystoneclient sessions has been deprecated. ' - 'Please update your software to use keystoneauth1.') + warnings.warn( + 'Using keystoneclient sessions has been deprecated. ' + 'Please update your software to use keystoneauth1.' + ) for k, v in self.additional_headers.items(): kwargs.setdefault('headers', {}).setdefault(k, v) if self.global_request_id is not None: kwargs.setdefault('headers', {}).setdefault( - "X-OpenStack-Request-ID", self.global_request_id) + "X-OpenStack-Request-ID", self.global_request_id + ) if self.raise_exc is not None: kwargs.setdefault('raise_exc', self.raise_exc) @@ -309,10 +336,7 @@ def get_endpoint_data(self, auth=None): return self.session.get_endpoint_data(auth or self.auth, **kwargs) - def get_all_version_data( - self, - interface='public', - region_name=None): + def get_all_version_data(self, interface='public', region_name=None): """Get data about all versions of a service. :param interface: @@ -330,7 +354,8 @@ def get_all_version_data( return self.session.get_all_version_data( interface=interface, region_name=region_name, - service_type=self.service_type) + service_type=self.service_type, + ) def get_api_major_version(self, auth=None, **kwargs): """Get the major API version as provided by the auth plugin. @@ -419,43 +444,50 @@ def register_argparse_arguments(cls, parser, service_type=None): adapter_group = parser.add_argument_group( 'Service Options', 'Options controlling the specialization of the API' - ' Connection from information found in the catalog') + ' Connection from information found in the catalog', + ) adapter_group.add_argument( '--os-service-type', metavar='', default=os.environ.get('OS_SERVICE_TYPE', service_type), - help='Service type to request from the catalog') + help='Service type to request from the catalog', + ) adapter_group.add_argument( '--os-service-name', metavar='', default=os.environ.get('OS_SERVICE_NAME', None), - help='Service name to request from the catalog') + help='Service name to request from the catalog', + ) adapter_group.add_argument( '--os-interface', metavar='', default=os.environ.get('OS_INTERFACE', 'public'), - help='API Interface to use [public, internal, admin]') + help='API Interface to use [public, internal, admin]', + ) adapter_group.add_argument( '--os-region-name', metavar='', default=os.environ.get('OS_REGION_NAME', None), - help='Region of the cloud to use') + help='Region of the cloud to use', + ) adapter_group.add_argument( '--os-endpoint-override', metavar='', default=os.environ.get('OS_ENDPOINT_OVERRIDE', None), - help='Endpoint to use instead of the endpoint in the catalog') + help='Endpoint to use instead of the endpoint in the catalog', + ) adapter_group.add_argument( '--os-api-version', metavar='', default=os.environ.get('OS_API_VERSION', None), - help='Which version of the service API to use') + help='Which version of the service API to use', + ) # TODO(efried): Move this to loading.adapter.Adapter @classmethod @@ -469,66 +501,62 @@ def register_service_argparse_arguments(cls, parser, service_type): """ service_env = service_type.upper().replace('-', '_') adapter_group = parser.add_argument_group( - '{service_type} Service Options'.format( - service_type=service_type.title()), - 'Options controlling the specialization of the {service_type}' - ' API Connection from information found in the catalog'.format( - service_type=service_type.title())) + f'{service_type.title()} Service Options', + f'Options controlling the specialization of the {service_type.title()}' + ' API Connection from information found in the catalog', + ) adapter_group.add_argument( - '--os-{service_type}-service-type'.format( - service_type=service_type), + f'--os-{service_type}-service-type', metavar='', - default=os.environ.get( - 'OS_{service_type}_SERVICE_TYPE'.format( - service_type=service_env), None), - help=('Service type to request from the catalog for the' - ' {service_type} service'.format( - service_type=service_type))) + default=os.environ.get(f'OS_{service_env}_SERVICE_TYPE', None), + help=( + 'Service type to request from the catalog for the' + f' {service_type} service' + ), + ) adapter_group.add_argument( - '--os-{service_type}-service-name'.format( - service_type=service_type), + f'--os-{service_type}-service-name', metavar='', - default=os.environ.get( - 'OS_{service_type}_SERVICE_NAME'.format( - service_type=service_env), None), - help=('Service name to request from the catalog for the' - ' {service_type} service'.format( - service_type=service_type))) + default=os.environ.get(f'OS_{service_env}_SERVICE_NAME', None), + help=( + 'Service name to request from the catalog for the' + f' {service_type} service' + ), + ) adapter_group.add_argument( - '--os-{service_type}-interface'.format( - service_type=service_type), + f'--os-{service_type}-interface', metavar='', - default=os.environ.get( - 'OS_{service_type}_INTERFACE'.format( - service_type=service_env), None), - help=('API Interface to use for the {service_type} service' - ' [public, internal, admin]'.format( - service_type=service_type))) + default=os.environ.get(f'OS_{service_env}_INTERFACE', None), + help=( + f'API Interface to use for the {service_type} service' + ' [public, internal, admin]' + ), + ) adapter_group.add_argument( - '--os-{service_type}-api-version'.format( - service_type=service_type), + f'--os-{service_type}-api-version', metavar='', - default=os.environ.get( - 'OS_{service_type}_API_VERSION'.format( - service_type=service_env), None), - help=('Which version of the service API to use for' - ' the {service_type} service'.format( - service_type=service_type))) + default=os.environ.get(f'OS_{service_env}_API_VERSION', None), + help=( + 'Which version of the service API to use for' + f' the {service_type} service' + ), + ) adapter_group.add_argument( - '--os-{service_type}-endpoint-override'.format( - service_type=service_type), + f'--os-{service_type}-endpoint-override', metavar='', default=os.environ.get( - 'OS_{service_type}_ENDPOINT_OVERRIDE'.format( - service_type=service_env), None), - help=('Endpoint to use for the {service_type} service' - ' instead of the endpoint in the catalog'.format( - service_type=service_type))) + f'OS_{service_env}_ENDPOINT_OVERRIDE', None + ), + help=( + f'Endpoint to use for the {service_type} service' + ' instead of the endpoint in the catalog' + ), + ) class LegacyJsonAdapter(Adapter): @@ -549,7 +577,7 @@ def request(self, *args, **kwargs): except KeyError: pass - resp = super(LegacyJsonAdapter, self).request(*args, **kwargs) + resp = super().request(*args, **kwargs) try: body = resp.json() diff --git a/keystoneauth1/discover.py b/keystoneauth1/discover.py index 867a46b3..4c4d1225 100644 --- a/keystoneauth1/discover.py +++ b/keystoneauth1/discover.py @@ -62,23 +62,18 @@ def get_version_data(session, url, authenticated=None, version_header=None): The return is a list of dicts of the form:: - [{ - 'status': 'STABLE', - 'id': 'v2.3', - 'links': [ - { - 'href': 'http://network.example.com/v2.3', - 'rel': 'self', - }, - { - 'href': 'http://network.example.com/', - 'rel': 'collection', - }, - ], - 'min_version': '2.0', - 'max_version': '2.7', - }, - ..., + [ + { + 'status': 'STABLE', + 'id': 'v2.3', + 'links': [ + {'href': 'http://network.example.com/v2.3', 'rel': 'self'}, + {'href': 'http://network.example.com/', 'rel': 'collection'}, + ], + 'min_version': '2.0', + 'max_version': '2.7', + }, + ..., ] Note: @@ -117,7 +112,8 @@ def get_version_data(session, url, authenticated=None, version_header=None): # it's the only thing returning a [] here - and that's ok. if isinstance(body_resp, list): raise exceptions.DiscoveryFailure( - 'Invalid Response - List returned instead of dict') + 'Invalid Response - List returned instead of dict' + ) # In the event of querying a root URL we will get back a list of # available versions. @@ -163,8 +159,9 @@ def get_version_data(session, url, authenticated=None, version_header=None): return [body_resp] err_text = resp.text[:50] + '...' if len(resp.text) > 50 else resp.text - raise exceptions.DiscoveryFailure('Invalid Response - Bad version data ' - 'returned: %s' % err_text) + raise exceptions.DiscoveryFailure( + 'Invalid Response - Bad version data ' f'returned: {err_text}' + ) def normalize_version_number(version): @@ -253,11 +250,12 @@ def normalize_version_number(version): except (TypeError, ValueError): pass - raise TypeError('Invalid version specified: %s' % version) + raise TypeError(f'Invalid version specified: {version}') def _normalize_version_args( - version, min_version, max_version, service_type=None): + version, min_version, max_version, service_type=None +): # The sins of our fathers become the blood on our hands. # If a user requests an old-style service type such as volumev2, then they # are inherently requesting the major API version 2. It's not a good @@ -270,17 +268,20 @@ def _normalize_version_args( # as this, but in order to move forward without breaking people, we have # to just cry in the corner while striking ourselves with thorned branches. # That said, for sure only do this hack for officially known service_types. - if (service_type and - _SERVICE_TYPES.is_known(service_type) and - service_type[-1].isdigit() and - service_type[-2] == 'v'): + if ( + service_type + and _SERVICE_TYPES.is_known(service_type) + and service_type[-1].isdigit() + and service_type[-2] == 'v' + ): implied_version = normalize_version_number(service_type[-1]) else: implied_version = None if version and (min_version or max_version): raise ValueError( - "version is mutually exclusive with min_version and max_version") + "version is mutually exclusive with min_version and max_version" + ) if version: # Explode this into min_version and max_version @@ -291,15 +292,16 @@ def _normalize_version_args( raise exceptions.ImpliedVersionMismatch( service_type=service_type, implied=implied_version, - given=version_to_string(version)) + given=version_to_string(version), + ) return min_version, max_version if min_version == 'latest': if max_version not in (None, 'latest'): raise ValueError( - "min_version is 'latest' and max_version is {max_version}" - " but is only allowed to be 'latest' or None".format( - max_version=max_version)) + f"min_version is 'latest' and max_version is {max_version}" + " but is only allowed to be 'latest' or None" + ) max_version = 'latest' # Normalize e.g. empty string to None @@ -326,7 +328,8 @@ def _normalize_version_args( raise exceptions.ImpliedMinVersionMismatch( service_type=service_type, implied=implied_version, - given=version_to_string(min_version)) + given=version_to_string(min_version), + ) else: min_version = implied_version @@ -338,7 +341,8 @@ def _normalize_version_args( raise exceptions.ImpliedMaxVersionMismatch( service_type=service_type, implied=implied_version, - given=version_to_string(max_version)) + given=version_to_string(max_version), + ) else: max_version = (implied_version[0], LATEST) return min_version, max_version @@ -477,7 +481,8 @@ def _combine_relative_url(discovery_url, version_url): path, parsed_version_url.params, parsed_version_url.query, - parsed_version_url.fragment).geturl() + parsed_version_url.fragment, + ).geturl() def _version_from_url(url): @@ -499,7 +504,7 @@ def _version_from_url(url): return None -class Status(object): +class Status: CURRENT = 'CURRENT' SUPPORTED = 'SUPPORTED' DEPRECATED = 'DEPRECATED' @@ -528,19 +533,23 @@ def normalize(cls, raw_status): return status -class Discover(object): - +class Discover: CURRENT_STATUSES = ('stable', 'current', 'supported') DEPRECATED_STATUSES = ('deprecated',) EXPERIMENTAL_STATUSES = ('experimental',) def __init__(self, session, url, authenticated=None): self._url = url - self._data = get_version_data(session, url, - authenticated=authenticated) + self._data = get_version_data( + session, url, authenticated=authenticated + ) - def raw_version_data(self, allow_experimental=False, - allow_deprecated=True, allow_unknown=False): + def raw_version_data( + self, + allow_experimental=False, + allow_deprecated=True, + allow_unknown=False, + ): """Get raw version information from URL. Raw data indicates that only minimal validation processing is performed @@ -560,8 +569,10 @@ def raw_version_data(self, allow_experimental=False, try: status = v['status'] except KeyError: - _LOGGER.warning('Skipping over invalid version data. ' - 'No stability status in version.') + _LOGGER.warning( + 'Skipping over invalid version data. ' + 'No stability status in version.' + ) continue status = status.lower() @@ -633,8 +644,10 @@ def version_data(self, reverse=False, **kwargs): rel = link['rel'] url = _combine_relative_url(self._url, link['href']) except (KeyError, TypeError): - _LOGGER.info('Skipping invalid version link. ' - 'Missing link URL or relationship.') + _LOGGER.info( + 'Skipping invalid version link. ' + 'Missing link URL or relationship.' + ) continue if rel.lower() == 'self': @@ -642,20 +655,25 @@ def version_data(self, reverse=False, **kwargs): elif rel.lower() == 'collection': collection_url = url if not self_url: - _LOGGER.info('Skipping invalid version data. ' - 'Missing link to endpoint.') + _LOGGER.info( + 'Skipping invalid version data. ' + 'Missing link to endpoint.' + ) continue versions.append( - VersionData(version=version_number, - url=self_url, - collection=collection_url, - min_microversion=min_microversion, - max_microversion=max_microversion, - next_min_version=next_min_version, - not_before=not_before, - status=Status.normalize(v['status']), - raw_status=v['status'])) + VersionData( + version=version_number, + url=self_url, + collection=collection_url, + min_microversion=min_microversion, + max_microversion=max_microversion, + next_min_version=next_min_version, + not_before=not_before, + status=Status.normalize(v['status']), + raw_status=v['status'], + ) + ) versions.sort(key=lambda v: v['version'], reverse=reverse) return versions @@ -723,9 +741,9 @@ def url_for(self, version, **kwargs): data = self.data_for(version, **kwargs) return data['url'] if data else None - def versioned_data_for(self, url=None, - min_version=None, max_version=None, - **kwargs): + def versioned_data_for( + self, url=None, min_version=None, max_version=None, **kwargs + ): """Return endpoint data for the service at a url. min_version and max_version can be given either as strings or tuples. @@ -747,15 +765,17 @@ def versioned_data_for(self, url=None, :rtype: dict """ min_version, max_version = _normalize_version_args( - None, min_version, max_version) + None, min_version, max_version + ) no_version = not max_version and not min_version version_data = self.version_data(reverse=True, **kwargs) # If we don't have to check a min_version, we can short # circuit anything else - if (max_version == (LATEST, LATEST) and - (not min_version or min_version == (LATEST, LATEST))): + if max_version == (LATEST, LATEST) and ( + not min_version or min_version == (LATEST, LATEST) + ): # because we reverse we can just take the first entry return version_data[0] @@ -774,8 +794,11 @@ def versioned_data_for(self, url=None, if _latest_soft_match(min_version, data['version']): return data # Only validate version bounds if versions were specified - if min_version and max_version and version_between( - min_version, max_version, data['version']): + if ( + min_version + and max_version + and version_between(min_version, max_version, data['version']) + ): return data # If there is no version requested and we could not find a matching @@ -805,8 +828,9 @@ def versioned_url_for(self, min_version=None, max_version=None, **kwargs): :returns: The url for the specified version or None if no match. :rtype: str """ - data = self.versioned_data_for(min_version=min_version, - max_version=max_version, **kwargs) + data = self.versioned_data_for( + min_version=min_version, max_version=max_version, **kwargs + ) return data['url'] if data else None @@ -814,17 +838,18 @@ class VersionData(dict): """Normalized Version Data about an endpoint.""" def __init__( - self, - version, - url, - collection=None, - max_microversion=None, - min_microversion=None, - next_min_version=None, - not_before=None, - status='CURRENT', - raw_status=None): - super(VersionData, self).__init__() + self, + version, + url, + collection=None, + max_microversion=None, + min_microversion=None, + next_min_version=None, + not_before=None, + status='CURRENT', + raw_status=None, + ): + super().__init__() self['version'] = version self['url'] = url self['collection'] = collection @@ -883,7 +908,7 @@ def raw_status(self): return self.get('raw_status') -class EndpointData(object): +class EndpointData: """Normalized information about a discovered endpoint. Contains url, version, microversion, interface and region information. @@ -894,23 +919,25 @@ class EndpointData(object): possibilities. """ - def __init__(self, - catalog_url=None, - service_url=None, - service_type=None, - service_name=None, - service_id=None, - region_name=None, - interface=None, - endpoint_id=None, - raw_endpoint=None, - api_version=None, - major_version=None, - min_microversion=None, - max_microversion=None, - next_min_version=None, - not_before=None, - status=None): + def __init__( + self, + catalog_url=None, + service_url=None, + service_type=None, + service_name=None, + service_id=None, + region_name=None, + interface=None, + endpoint_id=None, + raw_endpoint=None, + api_version=None, + major_version=None, + min_microversion=None, + max_microversion=None, + next_min_version=None, + not_before=None, + status=None, + ): self.catalog_url = catalog_url self.service_url = service_url self.service_type = service_type @@ -962,19 +989,35 @@ def __copy__(self): def __str__(self): """Produce a string like EndpointData{key=val, ...}, for debugging.""" str_attrs = ( - 'api_version', 'catalog_url', 'endpoint_id', 'interface', - 'major_version', 'max_microversion', 'min_microversion', - 'next_min_version', 'not_before', 'raw_endpoint', 'region_name', - 'service_id', 'service_name', 'service_type', 'service_url', 'url') - return "%s{%s}" % (self.__class__.__name__, ', '.join( - ["%s=%s" % (attr, getattr(self, attr)) for attr in str_attrs])) + 'api_version', + 'catalog_url', + 'endpoint_id', + 'interface', + 'major_version', + 'max_microversion', + 'min_microversion', + 'next_min_version', + 'not_before', + 'raw_endpoint', + 'region_name', + 'service_id', + 'service_name', + 'service_type', + 'service_url', + 'url', + ) + return "{}{{{}}}".format( + self.__class__.__name__, + ', '.join([f"{attr}={getattr(self, attr)}" for attr in str_attrs]), + ) @property def url(self): return self.service_url or self.catalog_url - def get_current_versioned_data(self, session, allow=None, cache=None, - project_id=None): + def get_current_versioned_data( + self, session, allow=None, cache=None, project_id=None + ): """Run version discovery on the current endpoint. A simplified version of get_versioned_data, get_current_versioned_data @@ -1001,16 +1044,29 @@ def get_current_versioned_data(self, session, allow=None, cache=None, could not be discovered. """ min_version, max_version = _normalize_version_args( - self.api_version, None, None) + self.api_version, None, None + ) return self.get_versioned_data( - session=session, allow=allow, cache=cache, allow_version_hack=True, + session=session, + allow=allow, + cache=cache, + allow_version_hack=True, discover_versions=True, - min_version=min_version, max_version=max_version) + min_version=min_version, + max_version=max_version, + ) - def get_versioned_data(self, session, allow=None, cache=None, - allow_version_hack=True, project_id=None, - discover_versions=True, - min_version=None, max_version=None): + def get_versioned_data( + self, + session, + allow=None, + cache=None, + allow_version_hack=True, + project_id=None, + discover_versions=True, + min_version=None, + max_version=None, + ): """Run version discovery for the service described. Performs Version Discovery and returns a new EndpointData object with @@ -1050,7 +1106,8 @@ def get_versioned_data(self, session, allow=None, cache=None, could not be discovered. """ min_version, max_version = _normalize_version_args( - None, min_version, max_version) + None, min_version, max_version + ) if not allow: allow = {} @@ -1059,10 +1116,15 @@ def get_versioned_data(self, session, allow=None, cache=None, new_data = copy.copy(self) new_data._set_version_info( - session=session, allow=allow, cache=cache, - allow_version_hack=allow_version_hack, project_id=project_id, - discover_versions=discover_versions, min_version=min_version, - max_version=max_version) + session=session, + allow=allow, + cache=cache, + allow_version_hack=allow_version_hack, + project_id=project_id, + discover_versions=discover_versions, + min_version=min_version, + max_version=max_version, + ) return new_data def get_all_version_string_data(self, session, project_id=None): @@ -1082,7 +1144,8 @@ def get_all_version_string_data(self, session, project_id=None): # Ignore errors here - we're just searching for one of the # URLs that will give us data. _LOGGER.debug( - "Failed attempt at discovery on %s: %s", vers_url, str(e)) + "Failed attempt at discovery on %s: %s", vers_url, str(e) + ) continue for version in d.version_string_data(): versions.append(version) @@ -1109,10 +1172,17 @@ def _infer_version_data(self, project_id=None): return [VersionData(url=url, version=version)] - def _set_version_info(self, session, allow=None, cache=None, - allow_version_hack=True, project_id=None, - discover_versions=False, - min_version=None, max_version=None): + def _set_version_info( + self, + session, + allow=None, + cache=None, + allow_version_hack=True, + project_id=None, + discover_versions=False, + min_version=None, + max_version=None, + ): match_url = None no_version = not max_version and not min_version @@ -1134,38 +1204,48 @@ def _set_version_info(self, session, allow=None, cache=None, # satisfy the request without further work if self._disc: discovered_data = self._disc.versioned_data_for( - min_version=min_version, max_version=max_version, - url=match_url, **allow) + min_version=min_version, + max_version=max_version, + url=match_url, + **allow, + ) if not discovered_data: self._run_discovery( - session=session, cache=cache, - min_version=min_version, max_version=max_version, - project_id=project_id, allow_version_hack=allow_version_hack, - discover_versions=discover_versions) + session=session, + cache=cache, + min_version=min_version, + max_version=max_version, + project_id=project_id, + allow_version_hack=allow_version_hack, + discover_versions=discover_versions, + ) if not self._disc: return discovered_data = self._disc.versioned_data_for( - min_version=min_version, max_version=max_version, - url=match_url, **allow) + min_version=min_version, + max_version=max_version, + url=match_url, + **allow, + ) if not discovered_data: if min_version and not max_version: raise exceptions.DiscoveryFailure( - "Minimum version {min_version} was not found".format( - min_version=version_to_string(min_version))) + f"Minimum version {version_to_string(min_version)} was not found" + ) elif max_version and not min_version: raise exceptions.DiscoveryFailure( - "Maximum version {max_version} was not found".format( - max_version=version_to_string(max_version))) + f"Maximum version {version_to_string(max_version)} was not found" + ) elif min_version and max_version: raise exceptions.DiscoveryFailure( - "No version found between {min_version}" - " and {max_version}".format( - min_version=version_to_string(min_version), - max_version=version_to_string(max_version))) + f"No version found between {version_to_string(min_version)}" + f" and {version_to_string(max_version)}" + ) else: raise exceptions.DiscoveryFailure( - "No version data found remotely at all") + "No version data found remotely at all" + ) self.min_microversion = discovered_data['min_microversion'] self.max_microversion = discovered_data['max_microversion'] @@ -1184,25 +1264,35 @@ def _set_version_info(self, session, allow=None, cache=None, # for example a "v2" path from http://host/admin should resolve as # http://host/admin/v2 where it would otherwise be host/v2. # This has no effect on absolute urls returned from url_for. - url = urllib.parse.urljoin(self._disc._url.rstrip('/') + '/', - discovered_url) + url = urllib.parse.urljoin( + self._disc._url.rstrip('/') + '/', discovered_url + ) # If we had to pop a project_id from the catalog_url, put it back on if self._saved_project_id: - url = urllib.parse.urljoin(url.rstrip('/') + '/', - self._saved_project_id) + url = urllib.parse.urljoin( + url.rstrip('/') + '/', self._saved_project_id + ) self.service_url = url - def _run_discovery(self, session, cache, min_version, max_version, - project_id, allow_version_hack, discover_versions): + def _run_discovery( + self, + session, + cache, + min_version, + max_version, + project_id, + allow_version_hack, + discover_versions, + ): tried = set() for vers_url in self._get_discovery_url_choices( - project_id=project_id, - allow_version_hack=allow_version_hack, - min_version=min_version, - max_version=max_version): - + project_id=project_id, + allow_version_hack=allow_version_hack, + min_version=min_version, + max_version=max_version, + ): if self._catalog_matches_exactly and not discover_versions: # The version we started with is correct, and we don't want # new data @@ -1214,13 +1304,14 @@ def _run_discovery(self, session, cache, min_version, max_version, try: self._disc = get_discovery( - session, vers_url, - cache=cache, - authenticated=False) + session, vers_url, cache=cache, authenticated=False + ) break - except (exceptions.DiscoveryFailure, - exceptions.HttpError, - exceptions.ConnectionError) as exc: + except ( + exceptions.DiscoveryFailure, + exceptions.HttpError, + exceptions.ConnectionError, + ) as exc: _LOGGER.debug('No version document at %s: %s', vers_url, exc) continue if not self._disc: @@ -1242,7 +1333,9 @@ def _run_discovery(self, session, cache, min_version, max_version, _LOGGER.warning( 'Failed to contact the endpoint at %s for ' 'discovery. Fallback to using that endpoint as ' - 'the base url.', self.url) + 'the base url.', + self.url, + ) return else: @@ -1252,14 +1345,20 @@ def _run_discovery(self, session, cache, min_version, max_version, # date enough to properly specify a version and keystoneauth # can't deliver. raise exceptions.DiscoveryFailure( - "Unable to find a version discovery document at %s, " + "Unable to find a version discovery document at {}, " "the service is unavailable or misconfigured. " - "Required version range (%s - %s), version hack disabled." - % (self.url, min_version or "any", max_version or "any")) + "Required version range ({} - {}), version hack disabled.".format( + self.url, min_version or "any", max_version or "any" + ) + ) def _get_discovery_url_choices( - self, project_id=None, allow_version_hack=True, - min_version=None, max_version=None): + self, + project_id=None, + allow_version_hack=True, + min_version=None, + max_version=None, + ): """Find potential locations for version discovery URLs. min_version and max_version are already normalized, so will either be @@ -1295,19 +1394,27 @@ def _get_discovery_url_choices( '/'.join(url_parts), url.params, url.query, - url.fragment).geturl() + url.fragment, + ).geturl() except TypeError: pass else: # `is_between` means version bounds were specified *and* the URL # version is between them. - is_between = min_version and max_version and version_between( - min_version, max_version, url_version) - exact_match = (is_between and max_version and - max_version[0] == url_version[0]) - high_match = (is_between and max_version and - max_version[1] != LATEST and - version_match(max_version, url_version)) + is_between = ( + min_version + and max_version + and version_between(min_version, max_version, url_version) + ) + exact_match = ( + is_between and max_version and max_version[0] == url_version[0] + ) + high_match = ( + is_between + and max_version + and max_version[1] != LATEST + and version_match(max_version, url_version) + ) if exact_match or is_between: self._catalog_matches_version = True self._catalog_matches_exactly = exact_match @@ -1316,13 +1423,19 @@ def _get_discovery_url_choices( # return it just yet. It's a good option, but unless we # have an exact match or match the max requested, we want # to try for an unversioned endpoint first. - catalog_discovery = urllib.parse.ParseResult( - url.scheme, - url.netloc, - '/'.join(url_parts), - url.params, - url.query, - url.fragment).geturl().rstrip('/') + '/' + catalog_discovery = ( + urllib.parse.ParseResult( + url.scheme, + url.netloc, + '/'.join(url_parts), + url.params, + url.query, + url.fragment, + ) + .geturl() + .rstrip('/') + + '/' + ) # If we found a viable catalog endpoint and it's # an exact match or matches the max, go ahead and give @@ -1342,7 +1455,8 @@ def _get_discovery_url_choices( '/'.join(url_parts), url.params, url.query, - url.fragment).geturl() + url.fragment, + ).geturl() # Since this is potentially us constructing a base URL from the # versioned URL - we need to make sure it has a trailing /. But # we only want to do that if we have built a new URL - not if @@ -1448,7 +1562,8 @@ def get_discovery(session, url, cache=None, authenticated=False): '', parsed_url.params, parsed_url.query, - parsed_url.fragment).geturl() + parsed_url.fragment, + ).geturl() for cache in caches: disc = cache.get(url) @@ -1468,7 +1583,7 @@ def get_discovery(session, url, cache=None, authenticated=False): return disc -class _VersionHacks(object): +class _VersionHacks: """A container to abstract the list of version hacks. This could be done as simply a dictionary but is abstracted like this to diff --git a/keystoneauth1/exceptions/auth.py b/keystoneauth1/exceptions/auth.py index e8d89b61..16df296e 100644 --- a/keystoneauth1/exceptions/auth.py +++ b/keystoneauth1/exceptions/auth.py @@ -28,5 +28,5 @@ def __init__(self, response): self.methods = body['receipt']['methods'] self.required_auth_methods = body['required_auth_methods'] self.expires_at = utils.parse_isotime(body['receipt']['expires_at']) - message = "%s: %s" % (self.message, self.required_auth_methods) - super(MissingAuthMethods, self).__init__(message) + message = f"{self.message}: {self.required_auth_methods}" + super().__init__(message) diff --git a/keystoneauth1/exceptions/auth_plugins.py b/keystoneauth1/exceptions/auth_plugins.py index be3c8c19..77ac6856 100644 --- a/keystoneauth1/exceptions/auth_plugins.py +++ b/keystoneauth1/exceptions/auth_plugins.py @@ -13,12 +13,14 @@ from keystoneauth1.exceptions import base -__all__ = ('AuthPluginException', - 'MissingAuthPlugin', - 'NoMatchingPlugin', - 'UnsupportedParameters', - 'OptionError', - 'MissingRequiredOptions') +__all__ = ( + 'AuthPluginException', + 'MissingAuthPlugin', + 'NoMatchingPlugin', + 'UnsupportedParameters', + 'OptionError', + 'MissingRequiredOptions', +) class AuthPluginException(base.ClientException): @@ -41,8 +43,8 @@ class NoMatchingPlugin(AuthPluginException): def __init__(self, name): self.name = name - msg = 'The plugin %s could not be found' % name - super(NoMatchingPlugin, self).__init__(msg) + msg = f'The plugin {name} could not be found' + super().__init__(msg) class UnsupportedParameters(AuthPluginException): @@ -59,7 +61,7 @@ def __init__(self, names): self.names = names m = 'The following parameters were given that are unsupported: %s' - super(UnsupportedParameters, self).__init__(m % ', '.join(self.names)) + super().__init__(m % ', '.join(self.names)) class OptionError(AuthPluginException): @@ -90,4 +92,4 @@ def __init__(self, options): names = ", ".join(o.dest for o in options) m = 'Auth plugin requires parameters which were not given: %s' - super(MissingRequiredOptions, self).__init__(m % names) + super().__init__(m % names) diff --git a/keystoneauth1/exceptions/base.py b/keystoneauth1/exceptions/base.py index afb889bb..b8f56c4a 100644 --- a/keystoneauth1/exceptions/base.py +++ b/keystoneauth1/exceptions/base.py @@ -21,4 +21,4 @@ class ClientException(Exception): def __init__(self, message=None): self.message = message or self.message - super(ClientException, self).__init__(self.message) + super().__init__(self.message) diff --git a/keystoneauth1/exceptions/catalog.py b/keystoneauth1/exceptions/catalog.py index 25b6005c..a09fa78b 100644 --- a/keystoneauth1/exceptions/catalog.py +++ b/keystoneauth1/exceptions/catalog.py @@ -13,9 +13,7 @@ from keystoneauth1.exceptions import base -__all__ = ('CatalogException', - 'EmptyCatalog', - 'EndpointNotFound') +__all__ = ('CatalogException', 'EmptyCatalog', 'EndpointNotFound') class CatalogException(base.ClientException): diff --git a/keystoneauth1/exceptions/connection.py b/keystoneauth1/exceptions/connection.py index e5de679e..6e2710d2 100644 --- a/keystoneauth1/exceptions/connection.py +++ b/keystoneauth1/exceptions/connection.py @@ -13,12 +13,14 @@ from keystoneauth1.exceptions import base -__all__ = ('ConnectionError', - 'ConnectTimeout', - 'ConnectFailure', - 'SSLError', - 'RetriableConnectionFailure', - 'UnknownConnectionError') +__all__ = ( + 'ConnectionError', + 'ConnectTimeout', + 'ConnectFailure', + 'SSLError', + 'RetriableConnectionFailure', + 'UnknownConnectionError', +) class RetriableConnectionFailure(Exception): @@ -47,5 +49,5 @@ class UnknownConnectionError(ConnectionError): """An error was encountered but we don't know what it is.""" def __init__(self, msg, original): - super(UnknownConnectionError, self).__init__(msg) + super().__init__(msg) self.original = original diff --git a/keystoneauth1/exceptions/discovery.py b/keystoneauth1/exceptions/discovery.py index 5bc6b06a..0fa7708b 100644 --- a/keystoneauth1/exceptions/discovery.py +++ b/keystoneauth1/exceptions/discovery.py @@ -17,11 +17,13 @@ _SERVICE_TYPES = os_service_types.ServiceTypes() -__all__ = ('DiscoveryFailure', - 'ImpliedVersionMismatch', - 'ImpliedMinVersionMismatch', - 'ImpliedMaxVersionMismatch', - 'VersionNotAvailable') +__all__ = ( + 'DiscoveryFailure', + 'ImpliedVersionMismatch', + 'ImpliedMinVersionMismatch', + 'ImpliedMaxVersionMismatch', + 'VersionNotAvailable', +) class DiscoveryFailure(base.ClientException): @@ -36,17 +38,12 @@ class ImpliedVersionMismatch(ValueError): label = 'version' def __init__(self, service_type, implied, given): - super(ImpliedVersionMismatch, self).__init__( - "service_type {service_type} was given which implies" - " major API version {implied} but {label} of" - " {given} was also given. Please update your code" - " to use the official service_type {official_type}.".format( - service_type=service_type, - implied=str(implied[0]), - given=given, - label=self.label, - official_type=_SERVICE_TYPES.get_service_type(service_type), - )) + super().__init__( + f"service_type {service_type} was given which implies" + f" major API version {str(implied[0])} but {self.label} of" + f" {given} was also given. Please update your code" + f" to use the official service_type {_SERVICE_TYPES.get_service_type(service_type)}." + ) class ImpliedMinVersionMismatch(ImpliedVersionMismatch): diff --git a/keystoneauth1/exceptions/http.py b/keystoneauth1/exceptions/http.py index da79f0cf..3449a1db 100644 --- a/keystoneauth1/exceptions/http.py +++ b/keystoneauth1/exceptions/http.py @@ -25,38 +25,37 @@ from keystoneauth1.exceptions import base -__all__ = ('HttpError', - - 'HTTPClientError', - 'BadRequest', - 'Unauthorized', - 'PaymentRequired', - 'Forbidden', - 'NotFound', - 'MethodNotAllowed', - 'NotAcceptable', - 'ProxyAuthenticationRequired', - 'RequestTimeout', - 'Conflict', - 'Gone', - 'LengthRequired', - 'PreconditionFailed', - 'RequestEntityTooLarge', - 'RequestUriTooLong', - 'UnsupportedMediaType', - 'RequestedRangeNotSatisfiable', - 'ExpectationFailed', - 'UnprocessableEntity', - - 'HttpServerError', - 'InternalServerError', - 'HttpNotImplemented', - 'BadGateway', - 'ServiceUnavailable', - 'GatewayTimeout', - 'HttpVersionNotSupported', - - 'from_response') +__all__ = ( + 'HttpError', + 'HTTPClientError', + 'BadRequest', + 'Unauthorized', + 'PaymentRequired', + 'Forbidden', + 'NotFound', + 'MethodNotAllowed', + 'NotAcceptable', + 'ProxyAuthenticationRequired', + 'RequestTimeout', + 'Conflict', + 'Gone', + 'LengthRequired', + 'PreconditionFailed', + 'RequestEntityTooLarge', + 'RequestUriTooLong', + 'UnsupportedMediaType', + 'RequestedRangeNotSatisfiable', + 'ExpectationFailed', + 'UnprocessableEntity', + 'HttpServerError', + 'InternalServerError', + 'HttpNotImplemented', + 'BadGateway', + 'ServiceUnavailable', + 'GatewayTimeout', + 'HttpVersionNotSupported', + 'from_response', +) class HttpError(base.ClientException): @@ -65,10 +64,17 @@ class HttpError(base.ClientException): http_status = 0 message = "HTTP Error" - def __init__(self, message=None, details=None, - response=None, request_id=None, - url=None, method=None, http_status=None, - retry_after=0): + def __init__( + self, + message=None, + details=None, + response=None, + request_id=None, + url=None, + method=None, + http_status=None, + retry_after=0, + ): self.http_status = http_status or self.http_status self.message = message or self.message self.details = details @@ -76,11 +82,11 @@ def __init__(self, message=None, details=None, self.response = response self.url = url self.method = method - formatted_string = "%s (HTTP %s)" % (self.message, self.http_status) + formatted_string = f"{self.message} (HTTP {self.http_status})" self.retry_after = retry_after if request_id: - formatted_string += " (Request-ID: %s)" % request_id - super(HttpError, self).__init__(formatted_string) + formatted_string += f" (Request-ID: {request_id})" + super().__init__(formatted_string) class HTTPClientError(HttpError): @@ -256,7 +262,7 @@ def __init__(self, *args, **kwargs): except (KeyError, ValueError): self.retry_after = 0 - super(RequestEntityTooLarge, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) class RequestUriTooLong(HTTPClientError): @@ -377,11 +383,11 @@ class HttpVersionNotSupported(HttpServerError): # _code_map contains all the classes that have http_status attribute. -_code_map = dict( - (getattr(obj, 'http_status', None), obj) +_code_map = { + getattr(obj, 'http_status', None): obj for name, obj in vars(sys.modules[__name__]).items() if inspect.isclass(obj) and getattr(obj, 'http_status', False) -) +} def from_response(response, method, url): @@ -414,8 +420,9 @@ def from_response(response, method, url): error = body["error"] kwargs["message"] = error.get("message") kwargs["details"] = error.get("details") - elif (isinstance(body, dict) and - isinstance(body.get("errors"), list)): + elif isinstance(body, dict) and isinstance( + body.get("errors"), list + ): # if the error response follows the API SIG guidelines, it # will return a list of errors. in this case, only the first # error is shown, but if there are multiple the user will be @@ -429,13 +436,15 @@ def from_response(response, method, url): if len(errors) > 1: # if there is more than one error, let the user know # that multiple were seen. - msg_hdr = ("Multiple error responses, " - "showing first only: ") + msg_hdr = ( + "Multiple error responses, showing first only: " + ) else: msg_hdr = "" - kwargs["message"] = "{}{}".format(msg_hdr, - errors[0].get("title")) + kwargs["message"] = "{}{}".format( + msg_hdr, errors[0].get("title") + ) kwargs["details"] = errors[0].get("detail") else: kwargs["message"] = "Unrecognized schema in response body." @@ -444,8 +453,10 @@ def from_response(response, method, url): kwargs["details"] = response.text # we check explicity for 401 in case of auth receipts - if (response.status_code == 401 - and "Openstack-Auth-Receipt" in response.headers): + if ( + response.status_code == 401 + and "Openstack-Auth-Receipt" in response.headers + ): return auth.MissingAuthMethods(response) try: diff --git a/keystoneauth1/exceptions/oidc.py b/keystoneauth1/exceptions/oidc.py index e8af5875..048cfd0a 100644 --- a/keystoneauth1/exceptions/oidc.py +++ b/keystoneauth1/exceptions/oidc.py @@ -14,18 +14,21 @@ from keystoneauth1.exceptions import auth_plugins __all__ = ( - 'InvalidDiscoveryEndpoint', 'InvalidOidcDiscoveryDocument', - 'OidcAccessTokenEndpointNotFound', 'OidcAuthorizationEndpointNotFound', - 'OidcGrantTypeMissmatch', 'OidcPluginNotSupported', + 'InvalidDiscoveryEndpoint', + 'InvalidOidcDiscoveryDocument', + 'OidcAccessTokenEndpointNotFound', + 'OidcAuthorizationEndpointNotFound', + 'OidcGrantTypeMissmatch', + 'OidcPluginNotSupported', ) class InvalidDiscoveryEndpoint(auth_plugins.AuthPluginException): - message = "OpenID Connect Discovery Document endpoint not set.""" + message = "OpenID Connect Discovery Document endpoint not set." class InvalidOidcDiscoveryDocument(auth_plugins.AuthPluginException): - message = "OpenID Connect Discovery Document is not valid JSON.""" + message = "OpenID Connect Discovery Document is not valid JSON." class OidcAccessTokenEndpointNotFound(auth_plugins.AuthPluginException): @@ -37,7 +40,8 @@ class OidcAuthorizationEndpointNotFound(auth_plugins.AuthPluginException): class OidcDeviceAuthorizationEndpointNotFound( - auth_plugins.AuthPluginException): + auth_plugins.AuthPluginException +): message = "OpenID Connect device authorization endpoint not provided." diff --git a/keystoneauth1/exceptions/response.py b/keystoneauth1/exceptions/response.py index 0707eda1..71ab6197 100644 --- a/keystoneauth1/exceptions/response.py +++ b/keystoneauth1/exceptions/response.py @@ -21,5 +21,5 @@ class InvalidResponse(base.ClientException): message = "Invalid response from server." def __init__(self, response): - super(InvalidResponse, self).__init__() + super().__init__() self.response = response diff --git a/keystoneauth1/exceptions/service_providers.py b/keystoneauth1/exceptions/service_providers.py index 959d6eb7..ce06de52 100644 --- a/keystoneauth1/exceptions/service_providers.py +++ b/keystoneauth1/exceptions/service_providers.py @@ -20,5 +20,5 @@ class ServiceProviderNotFound(base.ClientException): def __init__(self, sp_id): self.sp_id = sp_id - msg = 'The Service Provider %(sp)s could not be found' % {'sp': sp_id} - super(ServiceProviderNotFound, self).__init__(msg) + msg = f'The Service Provider {sp_id} could not be found' + super().__init__(msg) diff --git a/keystoneauth1/extras/_saml2/_loading.py b/keystoneauth1/extras/_saml2/_loading.py index 01da48fe..04a4c0b7 100644 --- a/keystoneauth1/extras/_saml2/_loading.py +++ b/keystoneauth1/extras/_saml2/_loading.py @@ -15,7 +15,6 @@ class Saml2Password(loading.BaseFederationLoader): - @property def plugin_class(self): return _saml2.V3Saml2Password @@ -25,25 +24,29 @@ def available(self): return _saml2._V3_SAML2_AVAILABLE def get_options(self): - options = super(Saml2Password, self).get_options() + options = super().get_options() - options.extend([ - loading.Opt('identity-provider-url', - required=True, - help=('An Identity Provider URL, where the SAML2 ' - 'authentication request will be sent.')), - loading.Opt('username', help='Username', required=True), - loading.Opt('password', - secret=True, - help='Password', - required=True) - ]) + options.extend( + [ + loading.Opt( + 'identity-provider-url', + required=True, + help=( + 'An Identity Provider URL, where the SAML2 ' + 'authentication request will be sent.' + ), + ), + loading.Opt('username', help='Username', required=True), + loading.Opt( + 'password', secret=True, help='Password', required=True + ), + ] + ) return options class ADFSPassword(loading.BaseFederationLoader): - @property def plugin_class(self): return _saml2.V3ADFSPassword @@ -53,24 +56,33 @@ def available(self): return _saml2._V3_ADFS_AVAILABLE def get_options(self): - options = super(ADFSPassword, self).get_options() + options = super().get_options() - options.extend([ - loading.Opt('identity-provider-url', - required=True, - help=('An Identity Provider URL, where the SAML ' - 'authentication request will be sent.')), - loading.Opt('service-provider-endpoint', - required=True, - help="Service Provider's Endpoint"), - loading.Opt('service-provider-entity-id', - required=True, - help="Service Provider's SAML Entity ID"), - loading.Opt('username', help='Username', required=True), - loading.Opt('password', - secret=True, - required=True, - help='Password') - ]) + options.extend( + [ + loading.Opt( + 'identity-provider-url', + required=True, + help=( + 'An Identity Provider URL, where the SAML ' + 'authentication request will be sent.' + ), + ), + loading.Opt( + 'service-provider-endpoint', + required=True, + help="Service Provider's Endpoint", + ), + loading.Opt( + 'service-provider-entity-id', + required=True, + help="Service Provider's SAML Entity ID", + ), + loading.Opt('username', help='Username', required=True), + loading.Opt( + 'password', secret=True, required=True, help='Password' + ), + ] + ) return options diff --git a/keystoneauth1/extras/_saml2/v3/adfs.py b/keystoneauth1/extras/_saml2/v3/adfs.py index edf71902..c89ff312 100644 --- a/keystoneauth1/extras/_saml2/v3/adfs.py +++ b/keystoneauth1/extras/_saml2/v3/adfs.py @@ -35,21 +35,34 @@ class Password(base.BaseSAMLPlugin): NAMESPACES = { 's': 'http://www.w3.org/2003/05/soap-envelope', 'a': 'http://www.w3.org/2005/08/addressing', - 'u': ('http://docs.oasis-open.org/wss/2004/01/oasis-200401-' - 'wss-wssecurity-utility-1.0.xsd') + 'u': ( + 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-' + 'wss-wssecurity-utility-1.0.xsd' + ), } ADFS_TOKEN_NAMESPACES = { 's': 'http://www.w3.org/2003/05/soap-envelope', - 't': 'http://docs.oasis-open.org/ws-sx/ws-trust/200512' + 't': 'http://docs.oasis-open.org/ws-sx/ws-trust/200512', } - ADFS_ASSERTION_XPATH = ('/s:Envelope/s:Body' - '/t:RequestSecurityTokenResponseCollection' - '/t:RequestSecurityTokenResponse') - - def __init__(self, auth_url, identity_provider, identity_provider_url, - service_provider_endpoint, username, password, - protocol, service_provider_entity_id=None, **kwargs): + ADFS_ASSERTION_XPATH = ( + '/s:Envelope/s:Body' + '/t:RequestSecurityTokenResponseCollection' + '/t:RequestSecurityTokenResponse' + ) + + def __init__( + self, + auth_url, + identity_provider, + identity_provider_url, + service_provider_endpoint, + username, + password, + protocol, + service_provider_entity_id=None, + **kwargs, + ): """Constructor for ``ADFSPassword``. :param auth_url: URL of the Identity Service @@ -78,10 +91,15 @@ def __init__(self, auth_url, identity_provider, identity_provider_url, :type password: string """ - super(Password, self).__init__( - auth_url=auth_url, identity_provider=identity_provider, + super().__init__( + auth_url=auth_url, + identity_provider=identity_provider, identity_provider_url=identity_provider_url, - username=username, password=password, protocol=protocol, **kwargs) + username=username, + password=password, + protocol=protocol, + **kwargs, + ) self.service_provider_endpoint = service_provider_endpoint self.service_provider_entity_id = service_provider_entity_id @@ -123,9 +141,11 @@ def _token_dates(self, fmt='%Y-%m-%dT%H:%M:%S.%fZ'): """ date_created = datetime.datetime.now(datetime.timezone.utc).replace( - tzinfo=None) + tzinfo=None + ) date_expires = date_created + datetime.timedelta( - seconds=self.DEFAULT_ADFS_TOKEN_EXPIRATION) + seconds=self.DEFAULT_ADFS_TOKEN_EXPIRATION + ) return [_time.strftime(fmt) for _time in (date_created, date_expires)] def _prepare_adfs_request(self): @@ -135,132 +155,188 @@ def _prepare_adfs_request(self): """ WSS_SECURITY_NAMESPACE = { - 'o': ('http://docs.oasis-open.org/wss/2004/01/oasis-200401-' - 'wss-wssecurity-secext-1.0.xsd') + 'o': ( + 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-' + 'wss-wssecurity-secext-1.0.xsd' + ) } TRUST_NAMESPACE = { 'trust': 'http://docs.oasis-open.org/ws-sx/ws-trust/200512' } - WSP_NAMESPACE = { - 'wsp': 'http://schemas.xmlsoap.org/ws/2004/09/policy' - } + WSP_NAMESPACE = {'wsp': 'http://schemas.xmlsoap.org/ws/2004/09/policy'} - WSA_NAMESPACE = { - 'wsa': 'http://www.w3.org/2005/08/addressing' - } + WSA_NAMESPACE = {'wsa': 'http://www.w3.org/2005/08/addressing'} root = etree.Element( '{http://www.w3.org/2003/05/soap-envelope}Envelope', - nsmap=self.NAMESPACES) + nsmap=self.NAMESPACES, + ) header = etree.SubElement( - root, '{http://www.w3.org/2003/05/soap-envelope}Header') + root, '{http://www.w3.org/2003/05/soap-envelope}Header' + ) action = etree.SubElement( - header, "{http://www.w3.org/2005/08/addressing}Action") + header, "{http://www.w3.org/2005/08/addressing}Action" + ) action.set( - "{http://www.w3.org/2003/05/soap-envelope}mustUnderstand", "1") - action.text = ('http://docs.oasis-open.org/ws-sx/ws-trust/200512' - '/RST/Issue') + "{http://www.w3.org/2003/05/soap-envelope}mustUnderstand", "1" + ) + action.text = ( + 'http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue' + ) messageID = etree.SubElement( - header, '{http://www.w3.org/2005/08/addressing}MessageID') + header, '{http://www.w3.org/2005/08/addressing}MessageID' + ) messageID.text = 'urn:uuid:' + uuid.uuid4().hex replyID = etree.SubElement( - header, '{http://www.w3.org/2005/08/addressing}ReplyTo') + header, '{http://www.w3.org/2005/08/addressing}ReplyTo' + ) address = etree.SubElement( - replyID, '{http://www.w3.org/2005/08/addressing}Address') + replyID, '{http://www.w3.org/2005/08/addressing}Address' + ) address.text = 'http://www.w3.org/2005/08/addressing/anonymous' to = etree.SubElement( - header, '{http://www.w3.org/2005/08/addressing}To') + header, '{http://www.w3.org/2005/08/addressing}To' + ) to.set("{http://www.w3.org/2003/05/soap-envelope}mustUnderstand", "1") security = etree.SubElement( - header, '{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' + header, + '{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' 'wss-wssecurity-secext-1.0.xsd}Security', - nsmap=WSS_SECURITY_NAMESPACE) + nsmap=WSS_SECURITY_NAMESPACE, + ) security.set( - "{http://www.w3.org/2003/05/soap-envelope}mustUnderstand", "1") + "{http://www.w3.org/2003/05/soap-envelope}mustUnderstand", "1" + ) timestamp = etree.SubElement( - security, ('{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' - 'wss-wssecurity-utility-1.0.xsd}Timestamp')) + security, + ( + '{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' + 'wss-wssecurity-utility-1.0.xsd}Timestamp' + ), + ) timestamp.set( - ('{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' - 'wss-wssecurity-utility-1.0.xsd}Id'), '_0') + ( + '{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' + 'wss-wssecurity-utility-1.0.xsd}Id' + ), + '_0', + ) created = etree.SubElement( - timestamp, ('{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' - 'wss-wssecurity-utility-1.0.xsd}Created')) + timestamp, + ( + '{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' + 'wss-wssecurity-utility-1.0.xsd}Created' + ), + ) expires = etree.SubElement( - timestamp, ('{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' - 'wss-wssecurity-utility-1.0.xsd}Expires')) + timestamp, + ( + '{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' + 'wss-wssecurity-utility-1.0.xsd}Expires' + ), + ) created.text, expires.text = self._token_dates() usernametoken = etree.SubElement( - security, '{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' - 'wss-wssecurity-secext-1.0.xsd}UsernameToken') + security, + '{http://docs.oasis-open.org/wss/2004/01/oasis-200401-' + 'wss-wssecurity-secext-1.0.xsd}UsernameToken', + ) usernametoken.set( - ('{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-' - 'wssecurity-utility-1.0.xsd}u'), "uuid-%s-1" % uuid.uuid4().hex) + ( + '{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-' + 'wssecurity-utility-1.0.xsd}u' + ), + f"uuid-{uuid.uuid4().hex}-1", + ) username = etree.SubElement( - usernametoken, ('{http://docs.oasis-open.org/wss/2004/01/oasis-' - '200401-wss-wssecurity-secext-1.0.xsd}Username')) + usernametoken, + ( + '{http://docs.oasis-open.org/wss/2004/01/oasis-' + '200401-wss-wssecurity-secext-1.0.xsd}Username' + ), + ) password = etree.SubElement( - usernametoken, ('{http://docs.oasis-open.org/wss/2004/01/oasis-' - '200401-wss-wssecurity-secext-1.0.xsd}Password'), - Type=('http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-' - 'username-token-profile-1.0#PasswordText')) + usernametoken, + ( + '{http://docs.oasis-open.org/wss/2004/01/oasis-' + '200401-wss-wssecurity-secext-1.0.xsd}Password' + ), + Type=( + 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-' + 'username-token-profile-1.0#PasswordText' + ), + ) body = etree.SubElement( - root, "{http://www.w3.org/2003/05/soap-envelope}Body") + root, "{http://www.w3.org/2003/05/soap-envelope}Body" + ) request_security_token = etree.SubElement( - body, ('{http://docs.oasis-open.org/ws-sx/ws-trust/200512}' - 'RequestSecurityToken'), nsmap=TRUST_NAMESPACE) + body, + ( + '{http://docs.oasis-open.org/ws-sx/ws-trust/200512}' + 'RequestSecurityToken' + ), + nsmap=TRUST_NAMESPACE, + ) applies_to = etree.SubElement( request_security_token, '{http://schemas.xmlsoap.org/ws/2004/09/policy}AppliesTo', - nsmap=WSP_NAMESPACE) + nsmap=WSP_NAMESPACE, + ) endpoint_reference = etree.SubElement( applies_to, '{http://www.w3.org/2005/08/addressing}EndpointReference', - nsmap=WSA_NAMESPACE) + nsmap=WSA_NAMESPACE, + ) wsa_address = etree.SubElement( - endpoint_reference, - '{http://www.w3.org/2005/08/addressing}Address') + endpoint_reference, '{http://www.w3.org/2005/08/addressing}Address' + ) keytype = etree.SubElement( request_security_token, - '{http://docs.oasis-open.org/ws-sx/ws-trust/200512}KeyType') - keytype.text = ('http://docs.oasis-open.org/ws-sx/' - 'ws-trust/200512/Bearer') + '{http://docs.oasis-open.org/ws-sx/ws-trust/200512}KeyType', + ) + keytype.text = ( + 'http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer' + ) request_type = etree.SubElement( request_security_token, - '{http://docs.oasis-open.org/ws-sx/ws-trust/200512}RequestType') - request_type.text = ('http://docs.oasis-open.org/ws-sx/' - 'ws-trust/200512/Issue') + '{http://docs.oasis-open.org/ws-sx/ws-trust/200512}RequestType', + ) + request_type.text = ( + 'http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue' + ) token_type = etree.SubElement( request_security_token, - '{http://docs.oasis-open.org/ws-sx/ws-trust/200512}TokenType') + '{http://docs.oasis-open.org/ws-sx/ws-trust/200512}TokenType', + ) token_type.text = 'urn:oasis:names:tc:SAML:1.0:assertion' # After constructing the request, let's plug in some values username.text = self.username password.text = self.password to.text = self.identity_provider_url - wsa_address.text = (self.service_provider_entity_id or - self.service_provider_endpoint) + wsa_address.text = ( + self.service_provider_entity_id or self.service_provider_endpoint + ) self.prepared_request = root @@ -289,12 +365,14 @@ def _get_adfs_security_token(self, session): recognized. """ + def _get_failure(e): xpath = '/s:Envelope/s:Body/s:Fault/s:Code/s:Subcode/s:Value' content = e.response.content try: obj = self.str_to_xml(content).xpath( - xpath, namespaces=self.NAMESPACES) + xpath, namespaces=self.NAMESPACES + ) obj = self._first(obj) return obj.text # NOTE(marek-denis): etree.Element.xpath() doesn't raise an @@ -309,13 +387,18 @@ def _get_failure(e): request_security_token = self.xml_to_str(self.prepared_request) try: response = session.post( - url=self.identity_provider_url, headers=self.HEADER_SOAP, - data=request_security_token, authenticated=False) + url=self.identity_provider_url, + headers=self.HEADER_SOAP, + data=request_security_token, + authenticated=False, + ) except exceptions.InternalServerError as e: reason = _get_failure(e) raise exceptions.AuthorizationFailure(reason) - msg = ('Error parsing XML returned from ' - 'the ADFS Identity Provider, reason: %s') + msg = ( + 'Error parsing XML returned from ' + 'the ADFS Identity Provider, reason: %s' + ) self.adfs_token = self.str_to_xml(response.content, msg) def _prepare_sp_request(self): @@ -329,7 +412,8 @@ def _prepare_sp_request(self): """ assertion = self.adfs_token.xpath( - self.ADFS_ASSERTION_XPATH, namespaces=self.ADFS_TOKEN_NAMESPACES) + self.ADFS_ASSERTION_XPATH, namespaces=self.ADFS_TOKEN_NAMESPACES + ) assertion = self._first(assertion) assertion = self.xml_to_str(assertion) # TODO(marek-denis): Ideally no string replacement should occur. @@ -338,7 +422,8 @@ def _prepare_sp_request(self): # from scratch and reuse values from the adfs security token. assertion = assertion.replace( b'http://docs.oasis-open.org/ws-sx/ws-trust/200512', - b'http://schemas.xmlsoap.org/ws/2005/02/trust') + b'http://schemas.xmlsoap.org/ws/2005/02/trust', + ) encoded_assertion = urllib.parse.quote(assertion) self.encoded_assertion = 'wa=wsignin1.0&wresult=' + encoded_assertion @@ -358,8 +443,12 @@ def _send_assertion_to_service_provider(self, session): """ session.post( - url=self.service_provider_endpoint, data=self.encoded_assertion, - headers=self.HEADER_X_FORM, redirect=False, authenticated=False) + url=self.service_provider_endpoint, + data=self.encoded_assertion, + headers=self.HEADER_X_FORM, + redirect=False, + authenticated=False, + ) def _access_service_provider(self, session): """Access protected endpoint and fetch unscoped token. @@ -382,9 +471,11 @@ def _access_service_provider(self, session): if self._cookies(session) is False: raise exceptions.AuthorizationFailure( "Session object doesn't contain a cookie, therefore you are " - "not allowed to enter the Identity Provider's protected area.") - self.authenticated_response = session.get(self.federated_token_url, - authenticated=False) + "not allowed to enter the Identity Provider's protected area." + ) + self.authenticated_response = session.get( + self.federated_token_url, authenticated=False + ) def get_unscoped_auth_ref(self, session, *kwargs): """Retrieve unscoped token after authentcation with ADFS server. diff --git a/keystoneauth1/extras/_saml2/v3/base.py b/keystoneauth1/extras/_saml2/v3/base.py index d221d158..eb02c4a9 100644 --- a/keystoneauth1/extras/_saml2/v3/base.py +++ b/keystoneauth1/extras/_saml2/v3/base.py @@ -23,21 +23,27 @@ class _Saml2TokenAuthMethod(v3.AuthMethod): _method_parameters = [] def get_auth_data(self, session, auth, headers, **kwargs): - raise exceptions.MethodNotImplemented('This method should never ' - 'be called') + raise exceptions.MethodNotImplemented( + 'This method should never be called' + ) class BaseSAMLPlugin(v3.FederationBaseAuth): - HTTP_MOVED_TEMPORARILY = 302 HTTP_SEE_OTHER = 303 _auth_method_class = _Saml2TokenAuthMethod - def __init__(self, auth_url, - identity_provider, identity_provider_url, - username, password, protocol, - **kwargs): + def __init__( + self, + auth_url, + identity_provider, + identity_provider_url, + username, + password, + protocol, + **kwargs, + ): """Class constructor accepting following parameters. :param auth_url: URL of the Identity Service @@ -68,10 +74,12 @@ def __init__(self, auth_url, :type protocol: string """ - super(BaseSAMLPlugin, self).__init__( - auth_url=auth_url, identity_provider=identity_provider, + super().__init__( + auth_url=auth_url, + identity_provider=identity_provider, protocol=protocol, - **kwargs) + **kwargs, + ) self.identity_provider_url = identity_provider_url self.username = username self.password = password diff --git a/keystoneauth1/extras/_saml2/v3/saml2.py b/keystoneauth1/extras/_saml2/v3/saml2.py index ab3ab933..e7ca43b4 100644 --- a/keystoneauth1/extras/_saml2/v3/saml2.py +++ b/keystoneauth1/extras/_saml2/v3/saml2.py @@ -28,7 +28,7 @@ _ECP_NAMESPACE = 'urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp' _PAOS_HEADER = 'application/vnd.paos+xml' -_PAOS_VER = 'ver="%s";"%s"' % (_PAOS_NAMESPACE, _ECP_NAMESPACE) +_PAOS_VER = f'ver="{_PAOS_NAMESPACE}";"{_ECP_NAMESPACE}"' _XML_NAMESPACES = { 'ecp': _ECP_NAMESPACE, @@ -72,14 +72,14 @@ def _response_xml(response, name): try: return etree.XML(response.content) except etree.XMLSyntaxError as e: - msg = 'SAML2: Error parsing XML returned from %s: %s' % (name, e) + msg = f'SAML2: Error parsing XML returned from {name}: {e}' raise InvalidResponse(msg) def _str_from_xml(xml, path): li = xml.xpath(path, namespaces=_XML_NAMESPACES) if len(li) != 1: - raise IndexError('%s should provide a single element list' % path) + raise IndexError(f'{path} should provide a single element list') return li[0] @@ -115,7 +115,7 @@ class _SamlAuth(requests.auth.AuthBase): """ def __init__(self, identity_provider_url, requests_auth): - super(_SamlAuth, self).__init__() + super().__init__() self.identity_provider_url = identity_provider_url self.requests_auth = requests_auth @@ -132,8 +132,10 @@ def __call__(self, request): return request def _handle_response(self, response, **kwargs): - if (response.status_code == 200 and - response.headers.get('Content-Type') == _PAOS_HEADER): + if ( + response.status_code == 200 + and response.headers.get('Content-Type') == _PAOS_HEADER + ): response = self._ecp_retry(response, **kwargs) return response @@ -151,33 +153,40 @@ def send(*send_args, **send_kwargs): authn_request.remove(authn_request[0]) - idp_response = send('POST', - self.identity_provider_url, - headers={'Content-type': 'text/xml'}, - data=etree.tostring(authn_request), - auth=self.requests_auth) + idp_response = send( + 'POST', + self.identity_provider_url, + headers={'Content-type': 'text/xml'}, + data=etree.tostring(authn_request), + auth=self.requests_auth, + ) history.append(idp_response) authn_response = _response_xml(idp_response, 'Identity Provider') - idp_consumer_url = _str_from_xml(authn_response, - _XPATH_IDP_CONSUMER_URL) + idp_consumer_url = _str_from_xml( + authn_response, _XPATH_IDP_CONSUMER_URL + ) if sp_consumer_url != idp_consumer_url: # send fault message to the SP, discard the response - send('POST', - sp_consumer_url, - data=_SOAP_FAULT, - headers={'Content-Type': _PAOS_HEADER}) + send( + 'POST', + sp_consumer_url, + data=_SOAP_FAULT, + headers={'Content-Type': _PAOS_HEADER}, + ) # prepare error message and raise an exception. - msg = ('Consumer URLs from Service Provider %(service_provider)s ' - '%(sp_consumer_url)s and Identity Provider ' - '%(identity_provider)s %(idp_consumer_url)s are not equal') + msg = ( + 'Consumer URLs from Service Provider %(service_provider)s ' + '%(sp_consumer_url)s and Identity Provider ' + '%(identity_provider)s %(idp_consumer_url)s are not equal' + ) msg = msg % { 'service_provider': sp_response.request.url, 'sp_consumer_url': sp_consumer_url, 'identity_provider': self.identity_provider_url, - 'idp_consumer_url': idp_consumer_url + 'idp_consumer_url': idp_consumer_url, } raise ConsumerMismatch(msg) @@ -186,19 +195,22 @@ def send(*send_args, **send_kwargs): # idp_consumer_url is the URL on the SP that handles the ECP body # returned and creates an authenticated session. - final_resp = send('POST', - idp_consumer_url, - headers={'Content-Type': _PAOS_HEADER}, - cookies=idp_response.cookies, - data=etree.tostring(authn_response)) + final_resp = send( + 'POST', + idp_consumer_url, + headers={'Content-Type': _PAOS_HEADER}, + cookies=idp_response.cookies, + data=etree.tostring(authn_response), + ) history.append(final_resp) # the SP should then redirect us back to the original URL to retry the # original request. - if final_resp.status_code in (requests.codes.found, - requests.codes.other): - + if final_resp.status_code in ( + requests.codes.found, + requests.codes.other, + ): # Consume content and release the original connection # to allow our new request to reuse the same one. sp_response.content @@ -216,13 +228,15 @@ def send(*send_args, **send_kwargs): class _FederatedSaml(v3.FederationBaseAuth): - - def __init__(self, auth_url, identity_provider, protocol, - identity_provider_url, **kwargs): - super(_FederatedSaml, self).__init__(auth_url, - identity_provider, - protocol, - **kwargs) + def __init__( + self, + auth_url, + identity_provider, + protocol, + identity_provider_url, + **kwargs, + ): + super().__init__(auth_url, identity_provider, protocol, **kwargs) self.identity_provider_url = identity_provider_url @abc.abstractmethod @@ -234,9 +248,11 @@ def get_unscoped_auth_ref(self, session, **kwargs): auth = _SamlAuth(self.identity_provider_url, method) try: - resp = session.get(self.federated_token_url, - requests_auth=auth, - authenticated=False) + resp = session.get( + self.federated_token_url, + requests_auth=auth, + authenticated=False, + ) except SamlException as e: raise exceptions.AuthorizationFailure(str(e)) @@ -287,13 +303,23 @@ class Password(_FederatedSaml): """ - def __init__(self, auth_url, identity_provider, protocol, - identity_provider_url, username, password, **kwargs): - super(Password, self).__init__(auth_url, - identity_provider, - protocol, - identity_provider_url, - **kwargs) + def __init__( + self, + auth_url, + identity_provider, + protocol, + identity_provider_url, + username, + password, + **kwargs, + ): + super().__init__( + auth_url, + identity_provider, + protocol, + identity_provider_url, + **kwargs, + ) self.username = username self.password = password diff --git a/keystoneauth1/extras/kerberos/__init__.py b/keystoneauth1/extras/kerberos/__init__.py index 493b897b..21abbbe3 100644 --- a/keystoneauth1/extras/kerberos/__init__.py +++ b/keystoneauth1/extras/kerberos/__init__.py @@ -43,7 +43,8 @@ def _mutual_auth(value): def _requests_auth(mutual_authentication): return requests_kerberos.HTTPKerberosAuth( - mutual_authentication=_mutual_auth(mutual_authentication)) + mutual_authentication=_mutual_auth(mutual_authentication) + ) def _dependency_check(): @@ -57,12 +58,11 @@ def _dependency_check(): class KerberosMethod(v3.AuthMethod): - _method_parameters = ['mutual_auth'] def __init__(self, *args, **kwargs): _dependency_check() - super(KerberosMethod, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def get_auth_data(self, session, auth, headers, request_kwargs, **kwargs): # NOTE(jamielennox): request_kwargs is passed as a kwarg however it is @@ -82,16 +82,18 @@ class MappedKerberos(federation.FederationBaseAuth): use the standard keystone auth process to scope that to any given project. """ - def __init__(self, auth_url, identity_provider, protocol, - mutual_auth=None, **kwargs): + def __init__( + self, auth_url, identity_provider, protocol, mutual_auth=None, **kwargs + ): _dependency_check() self.mutual_auth = mutual_auth - super(MappedKerberos, self).__init__(auth_url, identity_provider, - protocol, **kwargs) + super().__init__(auth_url, identity_provider, protocol, **kwargs) def get_unscoped_auth_ref(self, session, **kwargs): - resp = session.get(self.federated_token_url, - requests_auth=_requests_auth(self.mutual_auth), - authenticated=False) + resp = session.get( + self.federated_token_url, + requests_auth=_requests_auth(self.mutual_auth), + authenticated=False, + ) return access.create(body=resp.json(), resp=resp) diff --git a/keystoneauth1/extras/kerberos/_loading.py b/keystoneauth1/extras/kerberos/_loading.py index e1c94067..e77b05f5 100644 --- a/keystoneauth1/extras/kerberos/_loading.py +++ b/keystoneauth1/extras/kerberos/_loading.py @@ -16,7 +16,6 @@ class Kerberos(loading.BaseV3Loader): - @property def plugin_class(self): return kerberos.Kerberos @@ -26,14 +25,18 @@ def available(self): return kerberos.requests_kerberos is not None def get_options(self): - options = super(Kerberos, self).get_options() - - options.extend([ - loading.Opt('mutual-auth', - required=False, - default='optional', - help='Configures Kerberos Mutual Authentication'), - ]) + options = super().get_options() + + options.extend( + [ + loading.Opt( + 'mutual-auth', + required=False, + default='optional', + help='Configures Kerberos Mutual Authentication', + ) + ] + ) return options @@ -41,16 +44,17 @@ def load_from_options(self, **kwargs): if kwargs.get('mutual_auth'): value = kwargs.get('mutual_auth') if not (value.lower() in ['required', 'optional', 'disabled']): - m = ('You need to provide a valid value for kerberos mutual ' - 'authentication. It can be one of the following: ' - '(required, optional, disabled)') + m = ( + 'You need to provide a valid value for kerberos mutual ' + 'authentication. It can be one of the following: ' + '(required, optional, disabled)' + ) raise exceptions.OptionError(m) - return super(Kerberos, self).load_from_options(**kwargs) + return super().load_from_options(**kwargs) class MappedKerberos(loading.BaseFederationLoader): - @property def plugin_class(self): return kerberos.MappedKerberos @@ -60,14 +64,18 @@ def available(self): return kerberos.requests_kerberos is not None def get_options(self): - options = super(MappedKerberos, self).get_options() - - options.extend([ - loading.Opt('mutual-auth', - required=False, - default='optional', - help='Configures Kerberos Mutual Authentication'), - ]) + options = super().get_options() + + options.extend( + [ + loading.Opt( + 'mutual-auth', + required=False, + default='optional', + help='Configures Kerberos Mutual Authentication', + ) + ] + ) return options @@ -75,9 +83,11 @@ def load_from_options(self, **kwargs): if kwargs.get('mutual_auth'): value = kwargs.get('mutual_auth') if not (value.lower() in ['required', 'optional', 'disabled']): - m = ('You need to provide a valid value for kerberos mutual ' - 'authentication. It can be one of the following: ' - '(required, optional, disabled)') + m = ( + 'You need to provide a valid value for kerberos mutual ' + 'authentication. It can be one of the following: ' + '(required, optional, disabled)' + ) raise exceptions.OptionError(m) - return super(MappedKerberos, self).load_from_options(**kwargs) + return super().load_from_options(**kwargs) diff --git a/keystoneauth1/extras/oauth1/_loading.py b/keystoneauth1/extras/oauth1/_loading.py index fa43232e..677d2ba9 100644 --- a/keystoneauth1/extras/oauth1/_loading.py +++ b/keystoneauth1/extras/oauth1/_loading.py @@ -17,7 +17,6 @@ # NOTE(jamielennox): This is not a BaseV3Loader because we don't want to # include the scoping options like project-id in the option list class V3OAuth1(loading.BaseIdentityLoader): - @property def plugin_class(self): return v3.OAuth1 @@ -27,21 +26,25 @@ def available(self): return v3.oauth1 is not None def get_options(self): - options = super(V3OAuth1, self).get_options() - - options.extend([ - loading.Opt('consumer-key', - required=True, - help='OAuth Consumer ID/Key'), - loading.Opt('consumer-secret', - required=True, - help='OAuth Consumer Secret'), - loading.Opt('access-key', - required=True, - help='OAuth Access Key'), - loading.Opt('access-secret', - required=True, - help='OAuth Access Secret'), - ]) + options = super().get_options() + + options.extend( + [ + loading.Opt( + 'consumer-key', required=True, help='OAuth Consumer ID/Key' + ), + loading.Opt( + 'consumer-secret', + required=True, + help='OAuth Consumer Secret', + ), + loading.Opt( + 'access-key', required=True, help='OAuth Access Key' + ), + loading.Opt( + 'access-secret', required=True, help='OAuth Access Secret' + ), + ] + ) return options diff --git a/keystoneauth1/extras/oauth1/v3.py b/keystoneauth1/extras/oauth1/v3.py index 98c768db..ec8c54fa 100644 --- a/keystoneauth1/extras/oauth1/v3.py +++ b/keystoneauth1/extras/oauth1/v3.py @@ -44,37 +44,46 @@ class OAuth1Method(v3.AuthMethod): :param string access_secret: Access token secret. """ - _method_parameters = ['consumer_key', 'consumer_secret', - 'access_key', 'access_secret'] + _method_parameters = [ + 'consumer_key', + 'consumer_secret', + 'access_key', + 'access_secret', + ] def get_auth_data(self, session, auth, headers, **kwargs): # Add the oauth specific content into the headers - oauth_client = oauth1.Client(self.consumer_key, - client_secret=self.consumer_secret, - resource_owner_key=self.access_key, - resource_owner_secret=self.access_secret, - signature_method=oauth1.SIGNATURE_HMAC) - - o_url, o_headers, o_body = oauth_client.sign(auth.token_url, - http_method='POST') + oauth_client = oauth1.Client( + self.consumer_key, + client_secret=self.consumer_secret, + resource_owner_key=self.access_key, + resource_owner_secret=self.access_secret, + signature_method=oauth1.SIGNATURE_HMAC, + ) + + o_url, o_headers, o_body = oauth_client.sign( + auth.token_url, http_method='POST' + ) headers.update(o_headers) return 'oauth1', {} def get_cache_id_elements(self): - return dict(('oauth1_%s' % p, getattr(self, p)) - for p in self._method_parameters) + return { + f'oauth1_{p}': getattr(self, p) for p in self._method_parameters + } class OAuth1(v3.AuthConstructor): - _auth_method_class = OAuth1Method def __init__(self, *args, **kwargs): - super(OAuth1, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if self.has_scope_parameters: - LOG.warning('Scoping parameters such as a project were provided ' - 'to the OAuth1 plugin. Because OAuth1 access is ' - 'always scoped to a project these will be ignored by ' - 'the identity server') + LOG.warning( + 'Scoping parameters such as a project were provided ' + 'to the OAuth1 plugin. Because OAuth1 access is ' + 'always scoped to a project these will be ignored by ' + 'the identity server' + ) diff --git a/keystoneauth1/fixture/__init__.py b/keystoneauth1/fixture/__init__.py index f5d17069..03e26310 100644 --- a/keystoneauth1/fixture/__init__.py +++ b/keystoneauth1/fixture/__init__.py @@ -33,14 +33,15 @@ V3Token = v3.Token V3FederationToken = v3.V3FederationToken -__all__ = ('DiscoveryList', - 'FixtureValidationError', - 'LoadingFixture', - 'TestPlugin', - 'V2Discovery', - 'V3Discovery', - 'V2Token', - 'V3Token', - 'V3FederationToken', - 'VersionDiscovery', - ) +__all__ = ( + 'DiscoveryList', + 'FixtureValidationError', + 'LoadingFixture', + 'TestPlugin', + 'V2Discovery', + 'V3Discovery', + 'V2Token', + 'V3Token', + 'V3FederationToken', + 'VersionDiscovery', +) diff --git a/keystoneauth1/fixture/discovery.py b/keystoneauth1/fixture/discovery.py index 6a50f827..82bb77f5 100644 --- a/keystoneauth1/fixture/discovery.py +++ b/keystoneauth1/fixture/discovery.py @@ -12,11 +12,7 @@ from keystoneauth1 import _utils as utils -__all__ = ('DiscoveryList', - 'V2Discovery', - 'V3Discovery', - 'VersionDiscovery', - ) +__all__ = ('DiscoveryList', 'V2Discovery', 'V3Discovery', 'VersionDiscovery') _DEFAULT_DAYS_AGO = 30 @@ -32,7 +28,7 @@ class DiscoveryBase(dict): """ def __init__(self, id, status=None, updated=None): - super(DiscoveryBase, self).__init__() + super().__init__() self.id = id self.status = status or 'stable' @@ -103,7 +99,7 @@ class VersionDiscovery(DiscoveryBase): """ def __init__(self, href, id, **kwargs): - super(VersionDiscovery, self).__init__(id, **kwargs) + super().__init__(id, **kwargs) self.add_link(href) @@ -122,7 +118,7 @@ class MicroversionDiscovery(DiscoveryBase): """ def __init__(self, href, id, min_version='', max_version='', **kwargs): - super(MicroversionDiscovery, self).__init__(id, **kwargs) + super().__init__(id, **kwargs) self.add_link(href) @@ -160,7 +156,7 @@ class NovaMicroversionDiscovery(DiscoveryBase): """ def __init__(self, href, id, min_version=None, version=None, **kwargs): - super(NovaMicroversionDiscovery, self).__init__(id, **kwargs) + super().__init__(id, **kwargs) self.add_link(href) @@ -204,7 +200,7 @@ class V2Discovery(DiscoveryBase): _DESC_URL = 'https://developer.openstack.org/api-ref/identity/v2/' def __init__(self, href, id=None, html=True, pdf=True, **kwargs): - super(V2Discovery, self).__init__(id or 'v2.0', **kwargs) + super().__init__(id or 'v2.0', **kwargs) self.add_link(href) @@ -219,9 +215,11 @@ def add_html_description(self): The standard structure includes a link to a HTML document with the API specification. Add it to this entry. """ - self.add_link(href=self._DESC_URL + 'content', - rel='describedby', - type='text/html') + self.add_link( + href=self._DESC_URL + 'content', + rel='describedby', + type='text/html', + ) def add_pdf_description(self): """Add the PDF described by links. @@ -229,9 +227,11 @@ def add_pdf_description(self): The standard structure includes a link to a PDF document with the API specification. Add it to this entry. """ - self.add_link(href=self._DESC_URL + 'identity-dev-guide-2.0.pdf', - rel='describedby', - type='application/pdf') + self.add_link( + href=self._DESC_URL + 'identity-dev-guide-2.0.pdf', + rel='describedby', + type='application/pdf', + ) class V3Discovery(DiscoveryBase): @@ -249,7 +249,7 @@ class V3Discovery(DiscoveryBase): """ def __init__(self, href, id=None, json=True, xml=True, **kwargs): - super(V3Discovery, self).__init__(id or 'v3.0', **kwargs) + super().__init__(id or 'v3.0', **kwargs) self.add_link(href) @@ -264,8 +264,10 @@ def add_json_media_type(self): The standard structure includes a list of media-types that the endpoint supports. Add JSON to the list. """ - self.add_media_type(base='application/json', - type='application/vnd.openstack.identity-v3+json') + self.add_media_type( + base='application/json', + type='application/vnd.openstack.identity-v3+json', + ) def add_xml_media_type(self): """Add the XML media-type links. @@ -273,8 +275,10 @@ def add_xml_media_type(self): The standard structure includes a list of media-types that the endpoint supports. Add XML to the list. """ - self.add_media_type(base='application/xml', - type='application/vnd.openstack.identity-v3+xml') + self.add_media_type( + base='application/xml', + type='application/vnd.openstack.identity-v3+xml', + ) class DiscoveryList(dict): @@ -298,22 +302,47 @@ class DiscoveryList(dict): TEST_URL = 'http://keystone.host:5000/' - def __init__(self, href=None, v2=True, v3=True, v2_id=None, v3_id=None, - v2_status=None, v2_updated=None, v2_html=True, v2_pdf=True, - v3_status=None, v3_updated=None, v3_json=True, v3_xml=True): - super(DiscoveryList, self).__init__(versions={'values': []}) + def __init__( + self, + href=None, + v2=True, + v3=True, + v2_id=None, + v3_id=None, + v2_status=None, + v2_updated=None, + v2_html=True, + v2_pdf=True, + v3_status=None, + v3_updated=None, + v3_json=True, + v3_xml=True, + ): + super().__init__(versions={'values': []}) href = href or self.TEST_URL if v2: v2_href = href.rstrip('/') + '/v2.0' - self.add_v2(v2_href, id=v2_id, status=v2_status, - updated=v2_updated, html=v2_html, pdf=v2_pdf) + self.add_v2( + v2_href, + id=v2_id, + status=v2_status, + updated=v2_updated, + html=v2_html, + pdf=v2_pdf, + ) if v3: v3_href = href.rstrip('/') + '/v3' - self.add_v3(v3_href, id=v3_id, status=v3_status, - updated=v3_updated, json=v3_json, xml=v3_xml) + self.add_v3( + v3_href, + id=v3_id, + status=v3_status, + updated=v3_updated, + json=v3_json, + xml=v3_xml, + ) @property def versions(self): diff --git a/keystoneauth1/fixture/keystoneauth_betamax.py b/keystoneauth1/fixture/keystoneauth_betamax.py index 3a05d965..c7ed62d3 100644 --- a/keystoneauth1/fixture/keystoneauth_betamax.py +++ b/keystoneauth1/fixture/keystoneauth_betamax.py @@ -25,11 +25,16 @@ class BetamaxFixture(fixtures.Fixture): - - def __init__(self, cassette_name, cassette_library_dir=None, - serializer=None, record=False, - pre_record_hook=hooks.pre_record_hook, - serializer_name=None, request_matchers=None): + def __init__( + self, + cassette_name, + cassette_library_dir=None, + serializer=None, + record=False, + pre_record_hook=hooks.pre_record_hook, + serializer_name=None, + request_matchers=None, + ): """Configure Betamax for the test suite. :param str cassette_name: @@ -93,10 +98,12 @@ def serializer_name(self): return self._serializer_name def setUp(self): - super(BetamaxFixture, self).setUp() + super().setUp() self.mockpatch = mock.patch.object( - session, '_construct_session', - partial(_construct_session_with_betamax, self)) + session, + '_construct_session', + partial(_construct_session_with_betamax, self), + ) self.mockpatch.start() # Unpatch during cleanup self.addCleanup(self.mockpatch.stop) @@ -116,7 +123,8 @@ def _construct_session_with_betamax(fixture, session_obj=None): with betamax.Betamax.configure() as config: config.before_record(callback=fixture.pre_record_hook) fixture.recorder = betamax.Betamax( - session_obj, cassette_library_dir=fixture.cassette_library_dir) + session_obj, cassette_library_dir=fixture.cassette_library_dir + ) record = 'none' serializer = None @@ -126,10 +134,12 @@ def _construct_session_with_betamax(fixture, session_obj=None): serializer = fixture.serializer_name - fixture.recorder.use_cassette(fixture.cassette_name, - serialize_with=serializer, - record=record, - **fixture.use_cassette_kwargs) + fixture.recorder.use_cassette( + fixture.cassette_name, + serialize_with=serializer, + record=record, + **fixture.use_cassette_kwargs, + ) fixture.recorder.start() fixture.addCleanup(fixture.recorder.stop) diff --git a/keystoneauth1/fixture/plugin.py b/keystoneauth1/fixture/plugin.py index f9e908fe..cee7aa23 100644 --- a/keystoneauth1/fixture/plugin.py +++ b/keystoneauth1/fixture/plugin.py @@ -18,10 +18,7 @@ from keystoneauth1 import loading from keystoneauth1 import plugin -__all__ = ( - 'LoadingFixture', - 'TestPlugin', -) +__all__ = ('LoadingFixture', 'TestPlugin') DEFAULT_TEST_ENDPOINT = 'https://openstack.example.com/%(service_type)s' @@ -62,12 +59,10 @@ class TestPlugin(plugin.BaseAuthPlugin): auth_type = 'test_plugin' - def __init__(self, - token=None, - endpoint=None, - user_id=None, - project_id=None): - super(TestPlugin, self).__init__() + def __init__( + self, token=None, endpoint=None, user_id=None, project_id=None + ): + super().__init__() self.token = token or uuid.uuid4().hex self.endpoint = endpoint or DEFAULT_TEST_ENDPOINT @@ -98,9 +93,8 @@ def invalidate(self): class _TestPluginLoader(loading.BaseLoader): - def __init__(self, plugin): - super(_TestPluginLoader, self).__init__() + super().__init__() self._plugin = plugin def create_plugin(self, **kwargs): @@ -129,12 +123,10 @@ class LoadingFixture(fixtures.Fixture): MOCK_POINT = 'keystoneauth1.loading.base.get_plugin_loader' - def __init__(self, - token=None, - endpoint=None, - user_id=None, - project_id=None): - super(LoadingFixture, self).__init__() + def __init__( + self, token=None, endpoint=None, user_id=None, project_id=None + ): + super().__init__() # these are created and saved here so that a test could use them self.token = token or uuid.uuid4().hex @@ -143,16 +135,19 @@ def __init__(self, self.project_id = project_id or uuid.uuid4().hex def setUp(self): - super(LoadingFixture, self).setUp() + super().setUp() - self.useFixture(fixtures.MonkeyPatch(self.MOCK_POINT, - self.get_plugin_loader)) + self.useFixture( + fixtures.MonkeyPatch(self.MOCK_POINT, self.get_plugin_loader) + ) def create_plugin(self): - return TestPlugin(token=self.token, - endpoint=self.endpoint, - user_id=self.user_id, - project_id=self.project_id) + return TestPlugin( + token=self.token, + endpoint=self.endpoint, + user_id=self.user_id, + project_id=self.project_id, + ) def get_plugin_loader(self, auth_type): plugin = self.create_plugin() @@ -171,6 +166,6 @@ def get_endpoint(self, path=None, **kwargs): endpoint = _format_endpoint(self.endpoint, **kwargs) if path: - endpoint = "%s/%s" % (endpoint.rstrip('/'), path.lstrip('/')) + endpoint = "{}/{}".format(endpoint.rstrip('/'), path.lstrip('/')) return endpoint diff --git a/keystoneauth1/fixture/serializer.py b/keystoneauth1/fixture/serializer.py index 53905559..3798b6a2 100644 --- a/keystoneauth1/fixture/serializer.py +++ b/keystoneauth1/fixture/serializer.py @@ -20,7 +20,7 @@ def _should_use_block(value): - for c in u"\u000a\u000d\u001c\u001d\u001e\u0085\u2028\u2029": + for c in "\u000a\u000d\u001c\u001d\u001e\u0085\u2028\u2029": if c in value: return True return False @@ -40,7 +40,7 @@ def _represent_scalar(self, tag, value, style=None): def _unicode_representer(dumper, uni): - node = yaml.ScalarNode(tag=u'tag:yaml.org,2002:str', value=uni) + node = yaml.ScalarNode(tag='tag:yaml.org,2002:str', value=uni) return node @@ -49,9 +49,12 @@ def _indent_json(val): return '' return json.dumps( - json.loads(val), indent=2, - separators=(',', ': '), sort_keys=False, - default=str) + json.loads(val), + indent=2, + separators=(',', ': '), + sort_keys=False, + default=str, + ) def _is_json_body(interaction): @@ -60,13 +63,11 @@ def _is_json_body(interaction): class YamlJsonSerializer(betamax.serializers.base.BaseSerializer): - name = "yamljson" @staticmethod def generate_cassette_name(cassette_library_dir, cassette_name): - return os.path.join( - cassette_library_dir, "{name}.yaml".format(name=cassette_name)) + return os.path.join(cassette_library_dir, f"{cassette_name}.yaml") def serialize(self, cassette_data): # Reserialize internal json with indentation @@ -74,7 +75,8 @@ def serialize(self, cassette_data): for key in ('request', 'response'): if _is_json_body(interaction[key]): interaction[key]['body']['string'] = _indent_json( - interaction[key]['body']['string']) + interaction[key]['body']['string'] + ) class MyDumper(yaml.Dumper): """Specialized Dumper which does nice blocks and unicode.""" @@ -84,7 +86,8 @@ class MyDumper(yaml.Dumper): MyDumper.add_representer(str, _unicode_representer) return yaml.dump( - cassette_data, Dumper=MyDumper, default_flow_style=False) + cassette_data, Dumper=MyDumper, default_flow_style=False + ) def deserialize(self, cassette_data): try: diff --git a/keystoneauth1/fixture/v2.py b/keystoneauth1/fixture/v2.py index 0f88552e..78f56071 100644 --- a/keystoneauth1/fixture/v2.py +++ b/keystoneauth1/fixture/v2.py @@ -18,15 +18,23 @@ class _Service(dict): - - def add_endpoint(self, public, admin=None, internal=None, - tenant_id=None, region=None, id=None): - data = {'tenantId': tenant_id or uuid.uuid4().hex, - 'publicURL': public, - 'adminURL': admin or public, - 'internalURL': internal or public, - 'region': region, - 'id': id or uuid.uuid4().hex} + def add_endpoint( + self, + public, + admin=None, + internal=None, + tenant_id=None, + region=None, + id=None, + ): + data = { + 'tenantId': tenant_id or uuid.uuid4().hex, + 'publicURL': public, + 'adminURL': admin or public, + 'internalURL': internal or public, + 'region': region, + 'id': id or uuid.uuid4().hex, + } self.setdefault('endpoints', []).append(data) return data @@ -41,11 +49,21 @@ class Token(dict): that matter to them and not copy and paste sample. """ - def __init__(self, token_id=None, expires=None, issued=None, - tenant_id=None, tenant_name=None, user_id=None, - user_name=None, trust_id=None, trustee_user_id=None, - audit_id=None, audit_chain_id=None): - super(Token, self).__init__() + def __init__( + self, + token_id=None, + expires=None, + issued=None, + tenant_id=None, + tenant_name=None, + user_id=None, + user_name=None, + trust_id=None, + trustee_user_id=None, + audit_id=None, + audit_chain_id=None, + ): + super().__init__() self.token_id = token_id or uuid.uuid4().hex self.user_id = user_id or uuid.uuid4().hex @@ -75,8 +93,9 @@ def __init__(self, token_id=None, expires=None, issued=None, if trust_id or trustee_user_id: # the trustee_user_id will generally be the same as the user_id as # the token is being issued to the trustee - self.set_trust(id=trust_id, - trustee_user_id=trustee_user_id or user_id) + self.set_trust( + id=trust_id, trustee_user_id=trustee_user_id or user_id + ) if audit_chain_id: self.audit_chain_id = audit_chain_id @@ -237,8 +256,10 @@ def add_service(self, type, name=None): def remove_service(self, type): self.root['serviceCatalog'] = [ - f for f in self.root.setdefault('serviceCatalog', []) - if f['type'] != type] + f + for f in self.root.setdefault('serviceCatalog', []) + if f['type'] != type + ] def set_scope(self, id=None, name=None): self.tenant_id = id or uuid.uuid4().hex diff --git a/keystoneauth1/fixture/v3.py b/keystoneauth1/fixture/v3.py index a831792c..447ac774 100644 --- a/keystoneauth1/fixture/v3.py +++ b/keystoneauth1/fixture/v3.py @@ -25,16 +25,19 @@ class _Service(dict): """ def add_endpoint(self, interface, url, region=None, id=None): - data = {'id': id or uuid.uuid4().hex, - 'interface': interface, - 'url': url, - 'region': region, - 'region_id': region} + data = { + 'id': id or uuid.uuid4().hex, + 'interface': interface, + 'url': url, + 'region': region, + 'region_id': region, + } self.setdefault('endpoints', []).append(data) return data - def add_standard_endpoints(self, public=None, admin=None, internal=None, - region=None): + def add_standard_endpoints( + self, public=None, admin=None, internal=None, region=None + ): ret = [] if public: @@ -56,18 +59,36 @@ class Token(dict): that matter to them and not copy and paste sample. """ - def __init__(self, expires=None, issued=None, user_id=None, user_name=None, - user_domain_id=None, user_domain_name=None, methods=None, - project_id=None, project_name=None, project_domain_id=None, - project_domain_name=None, domain_id=None, domain_name=None, - trust_id=None, trust_impersonation=None, trustee_user_id=None, - trustor_user_id=None, application_credential_id=None, - application_credential_access_rules=None, - oauth_access_token_id=None, oauth_consumer_id=None, - audit_id=None, audit_chain_id=None, - is_admin_project=None, project_is_domain=None, - oauth2_thumbprint=None): - super(Token, self).__init__() + def __init__( + self, + expires=None, + issued=None, + user_id=None, + user_name=None, + user_domain_id=None, + user_domain_name=None, + methods=None, + project_id=None, + project_name=None, + project_domain_id=None, + project_domain_name=None, + domain_id=None, + domain_name=None, + trust_id=None, + trust_impersonation=None, + trustee_user_id=None, + trustor_user_id=None, + application_credential_id=None, + application_credential_access_rules=None, + oauth_access_token_id=None, + oauth_consumer_id=None, + audit_id=None, + audit_chain_id=None, + is_admin_project=None, + project_is_domain=None, + oauth2_thumbprint=None, + ): + super().__init__() self.user_id = user_id or uuid.uuid4().hex self.user_name = user_name or uuid.uuid4().hex @@ -97,32 +118,47 @@ def __init__(self, expires=None, issued=None, user_id=None, user_name=None, # expires should be able to be passed as a string so ignore self.expires_str = expires - if (project_id or project_name or - project_domain_id or project_domain_name): - self.set_project_scope(id=project_id, - name=project_name, - domain_id=project_domain_id, - domain_name=project_domain_name, - is_domain=project_is_domain) + if ( + project_id + or project_name + or project_domain_id + or project_domain_name + ): + self.set_project_scope( + id=project_id, + name=project_name, + domain_id=project_domain_id, + domain_name=project_domain_name, + is_domain=project_is_domain, + ) if domain_id or domain_name: self.set_domain_scope(id=domain_id, name=domain_name) - if (trust_id or (trust_impersonation is not None) or - trustee_user_id or trustor_user_id): - self.set_trust_scope(id=trust_id, - impersonation=trust_impersonation, - trustee_user_id=trustee_user_id, - trustor_user_id=trustor_user_id) + if ( + trust_id + or (trust_impersonation is not None) + or trustee_user_id + or trustor_user_id + ): + self.set_trust_scope( + id=trust_id, + impersonation=trust_impersonation, + trustee_user_id=trustee_user_id, + trustor_user_id=trustor_user_id, + ) if application_credential_id: self.set_application_credential( application_credential_id, - access_rules=application_credential_access_rules) + access_rules=application_credential_access_rules, + ) if oauth_access_token_id or oauth_consumer_id: - self.set_oauth(access_token_id=oauth_access_token_id, - consumer_id=oauth_consumer_id) + self.set_oauth( + access_token_id=oauth_access_token_id, + consumer_id=oauth_consumer_id, + ) if audit_chain_id: self.audit_chain_id = audit_chain_id @@ -326,7 +362,8 @@ def application_credential_id(self): @application_credential_id.setter def application_credential_id(self, value): application_credential = self.root.setdefault( - 'application_credential', {}) + 'application_credential', {} + ) application_credential.setdefault('id', value) @property @@ -336,7 +373,8 @@ def application_credential_access_rules(self): @application_credential_access_rules.setter def application_credential_access_rules(self, value): application_credential = self.root.setdefault( - 'application_credential', {}) + 'application_credential', {} + ) application_credential.setdefault('access_rules', value) @property @@ -438,8 +476,7 @@ def validate(self): def add_role(self, name=None, id=None): roles = self.root.setdefault('roles', []) - data = {'id': id or uuid.uuid4().hex, - 'name': name or uuid.uuid4().hex} + data = {'id': id or uuid.uuid4().hex, 'name': name or uuid.uuid4().hex} roles.append(data) return data @@ -453,11 +490,17 @@ def add_service(self, type, name=None, id=None): def remove_service(self, type): self.root.setdefault('catalog', []) self.root['catalog'] = [ - f for f in self.root.setdefault('catalog', []) - if f['type'] != type] - - def set_project_scope(self, id=None, name=None, domain_id=None, - domain_name=None, is_domain=None): + f for f in self.root.setdefault('catalog', []) if f['type'] != type + ] + + def set_project_scope( + self, + id=None, + name=None, + domain_id=None, + domain_name=None, + is_domain=None, + ): self.project_id = id or uuid.uuid4().hex self.project_name = name or uuid.uuid4().hex self.project_domain_id = domain_id or uuid.uuid4().hex @@ -477,8 +520,13 @@ def set_system_scope(self): # entire system. self.system = {'all': True} - def set_trust_scope(self, id=None, impersonation=False, - trustee_user_id=None, trustor_user_id=None): + def set_trust_scope( + self, + id=None, + impersonation=False, + trustee_user_id=None, + trustor_user_id=None, + ): self.trust_id = id or uuid.uuid4().hex self.trust_impersonation = impersonation self.trustee_user_id = trustee_user_id or uuid.uuid4().hex @@ -488,8 +536,9 @@ def set_oauth(self, access_token_id=None, consumer_id=None): self.oauth_access_token_id = access_token_id or uuid.uuid4().hex self.oauth_consumer_id = consumer_id or uuid.uuid4().hex - def set_application_credential(self, application_credential_id, - access_rules=None): + def set_application_credential( + self, application_credential_id, access_rules=None + ): self.application_credential_id = application_credential_id if access_rules is not None: self.application_credential_access_rules = access_rules @@ -517,20 +566,22 @@ class V3FederationToken(Token): FEDERATED_DOMAIN_ID = 'Federated' - def __init__(self, methods=None, identity_provider=None, protocol=None, - groups=None): + def __init__( + self, methods=None, identity_provider=None, protocol=None, groups=None + ): methods = methods or ['saml2'] - super(V3FederationToken, self).__init__(methods=methods) + super().__init__(methods=methods) self._user_domain = {'id': V3FederationToken.FEDERATED_DOMAIN_ID} self.add_federation_info_to_user(identity_provider, protocol, groups) - def add_federation_info_to_user(self, identity_provider=None, - protocol=None, groups=None): + def add_federation_info_to_user( + self, identity_provider=None, protocol=None, groups=None + ): data = { "OS-FEDERATION": { "identity_provider": identity_provider or uuid.uuid4().hex, "protocol": protocol or uuid.uuid4().hex, - "groups": groups or [{"id": uuid.uuid4().hex}] + "groups": groups or [{"id": uuid.uuid4().hex}], } } self._user.update(data) diff --git a/keystoneauth1/hacking/checks.py b/keystoneauth1/hacking/checks.py index 1d92e71c..5fda04c8 100644 --- a/keystoneauth1/hacking/checks.py +++ b/keystoneauth1/hacking/checks.py @@ -18,7 +18,6 @@ """ - import re from hacking import core @@ -27,10 +26,11 @@ @core.flake8ext def check_oslo_namespace_imports(logical_line, blank_before, filename): oslo_namespace_imports = re.compile( - r"(((from)|(import))\s+oslo\.)|(from\s+oslo\s+import\s+)") + r"(((from)|(import))\s+oslo\.)|(from\s+oslo\s+import\s+)" + ) if re.match(oslo_namespace_imports, logical_line): - msg = ("K333: '%s' must be used instead of '%s'.") % ( - logical_line.replace('oslo.', 'oslo_'), - logical_line) + msg = ("K333: '{}' must be used instead of '{}'.").format( + logical_line.replace('oslo.', 'oslo_'), logical_line + ) yield (0, msg) diff --git a/keystoneauth1/http_basic.py b/keystoneauth1/http_basic.py index 63f97cbf..e4c8eed0 100644 --- a/keystoneauth1/http_basic.py +++ b/keystoneauth1/http_basic.py @@ -25,15 +25,14 @@ class HTTPBasicAuth(plugin.FixedEndpointPlugin): """ def __init__(self, endpoint=None, username=None, password=None): - super(HTTPBasicAuth, self).__init__(endpoint) + super().__init__(endpoint) self.username = username self.password = password def get_token(self, session, **kwargs): if self.username is None or self.password is None: return None - token = bytes('%s:%s' % (self.username, self.password), - encoding='utf-8') + token = bytes(f'{self.username}:{self.password}', encoding='utf-8') encoded = base64.b64encode(token) return str(encoded, encoding='utf-8') @@ -41,5 +40,5 @@ def get_headers(self, session, **kwargs): token = self.get_token(session) if not token: return None - auth = 'Basic %s' % token + auth = f'Basic {token}' return {AUTH_HEADER_NAME: auth} diff --git a/keystoneauth1/identity/__init__.py b/keystoneauth1/identity/__init__.py index 6625a597..caa6ef3f 100644 --- a/keystoneauth1/identity/__init__.py +++ b/keystoneauth1/identity/__init__.py @@ -70,20 +70,22 @@ V3OAuth2mTlsClientCredential = v3.OAuth2mTlsClientCredential """See :class:`keystoneauth1.identity.v3.OAuth2mTlsClientCredential`""" -__all__ = ('BaseIdentityPlugin', - 'Password', - 'Token', - 'V2Password', - 'V2Token', - 'V3Password', - 'V3Token', - 'V3OidcPassword', - 'V3OidcAuthorizationCode', - 'V3OidcAccessToken', - 'V3OidcDeviceAuthorization', - 'V3TOTP', - 'V3TokenlessAuth', - 'V3ApplicationCredential', - 'V3MultiFactor', - 'V3OAuth2ClientCredential', - 'V3OAuth2mTlsClientCredential') +__all__ = ( + 'BaseIdentityPlugin', + 'Password', + 'Token', + 'V2Password', + 'V2Token', + 'V3Password', + 'V3Token', + 'V3OidcPassword', + 'V3OidcAuthorizationCode', + 'V3OidcAccessToken', + 'V3OidcDeviceAuthorization', + 'V3TOTP', + 'V3TokenlessAuth', + 'V3ApplicationCredential', + 'V3MultiFactor', + 'V3OAuth2ClientCredential', + 'V3OAuth2mTlsClientCredential', +) diff --git a/keystoneauth1/identity/access.py b/keystoneauth1/identity/access.py index bad476e7..842e7814 100644 --- a/keystoneauth1/identity/access.py +++ b/keystoneauth1/identity/access.py @@ -31,8 +31,7 @@ class AccessInfoPlugin(base.BaseIdentityPlugin): """ def __init__(self, auth_ref, auth_url=None): - super(AccessInfoPlugin, self).__init__(auth_url=auth_url, - reauthenticate=False) + super().__init__(auth_url=auth_url, reauthenticate=False) self.auth_ref = auth_ref def get_auth_ref(self, session, **kwargs): diff --git a/keystoneauth1/identity/base.py b/keystoneauth1/identity/base.py index b6d1ca7d..7b0808a5 100644 --- a/keystoneauth1/identity/base.py +++ b/keystoneauth1/identity/base.py @@ -27,14 +27,12 @@ class BaseIdentityPlugin(plugin.BaseAuthPlugin, metaclass=abc.ABCMeta): - # we count a token as valid (not needing refreshing) if it is valid for at # least this many seconds before the token expiry time MIN_TOKEN_LIFE_SECONDS = 120 def __init__(self, auth_url=None, reauthenticate=True): - - super(BaseIdentityPlugin, self).__init__() + super().__init__() self.auth_url = auth_url self.auth_ref = None @@ -152,11 +150,22 @@ def invalidate(self): return False - def get_endpoint_data(self, session, service_type=None, interface=None, - region_name=None, service_name=None, allow=None, - allow_version_hack=True, discover_versions=True, - skip_discovery=False, min_version=None, - max_version=None, endpoint_override=None, **kwargs): + def get_endpoint_data( + self, + session, + service_type=None, + interface=None, + region_name=None, + service_name=None, + allow=None, + allow_version_hack=True, + discover_versions=True, + skip_discovery=False, + min_version=None, + max_version=None, + endpoint_override=None, + **kwargs, + ): """Return a valid endpoint data for a service. If a valid token is not present then a new one will be fetched using @@ -223,7 +232,8 @@ def get_endpoint_data(self, session, service_type=None, interface=None, allow = allow or {} min_version, max_version = discover._normalize_version_args( - None, min_version, max_version, service_type=service_type) + None, min_version, max_version, service_type=service_type + ) # NOTE(jamielennox): if you specifically ask for requests to be sent to # the auth url then we can ignore many of the checks. Typically if you @@ -233,7 +243,8 @@ def get_endpoint_data(self, session, service_type=None, interface=None, if interface is plugin.AUTH_INTERFACE: endpoint_data = discover.EndpointData( service_url=self.auth_url, - service_type=service_type or 'identity') + service_type=service_type or 'identity', + ) project_id = None elif endpoint_override: # TODO(mordred) Make a code path that will look for a @@ -246,7 +257,8 @@ def get_endpoint_data(self, session, service_type=None, interface=None, catalog_url=endpoint_override, interface=interface, region_name=region_name, - service_name=service_name) + service_name=service_name, + ) # Setting an endpoint_override then calling get_endpoint_data means # you absolutely want the discovery info for the URL in question. # There are no code flows where this will happen for any other @@ -255,9 +267,11 @@ def get_endpoint_data(self, session, service_type=None, interface=None, project_id = self.get_project_id(session) else: if not service_type: - LOG.warning('Plugin cannot return an endpoint without ' - 'knowing the service type that is required. Add ' - 'service_type to endpoint filtering data.') + LOG.warning( + 'Plugin cannot return an endpoint without ' + 'knowing the service type that is required. Add ' + 'service_type to endpoint filtering data.' + ) return None # It's possible for things higher in the stack, because of @@ -273,7 +287,8 @@ def get_endpoint_data(self, session, service_type=None, interface=None, service_type=service_type, interface=interface, region_name=region_name, - service_name=service_name) + service_name=service_name, + ) if not endpoint_data: return None @@ -288,10 +303,14 @@ def get_endpoint_data(self, session, service_type=None, interface=None, max_version=max_version, cache=self._discovery_cache, discover_versions=discover_versions, - allow_version_hack=allow_version_hack, allow=allow) - except (exceptions.DiscoveryFailure, - exceptions.HttpError, - exceptions.ConnectionError): + allow_version_hack=allow_version_hack, + allow=allow, + ) + except ( + exceptions.DiscoveryFailure, + exceptions.HttpError, + exceptions.ConnectionError, + ): # If a version was requested, we didn't find it, return # None. if max_version or min_version: @@ -300,12 +319,21 @@ def get_endpoint_data(self, session, service_type=None, interface=None, # should be fine return endpoint_data - def get_endpoint(self, session, service_type=None, interface=None, - region_name=None, service_name=None, version=None, - allow=None, allow_version_hack=True, - skip_discovery=False, - min_version=None, max_version=None, - **kwargs): + def get_endpoint( + self, + session, + service_type=None, + interface=None, + region_name=None, + service_name=None, + version=None, + allow=None, + allow_version_hack=True, + skip_discovery=False, + min_version=None, + max_version=None, + **kwargs, + ): """Return a valid endpoint for a service. If a valid token is not present then a new one will be fetched using @@ -363,26 +391,45 @@ def get_endpoint(self, session, service_type=None, interface=None, # Explode `version` into min_version and max_version - everything below # here uses the latter rather than the former. min_version, max_version = discover._normalize_version_args( - version, min_version, max_version, service_type=service_type) + version, min_version, max_version, service_type=service_type + ) # Set discover_versions to False since we're only going to return # a URL. Fetching the microversion data would be needlessly # expensive in the common case. However, discover_versions=False # will still run discovery if the version requested is not the # version in the catalog. endpoint_data = self.get_endpoint_data( - session, service_type=service_type, interface=interface, - region_name=region_name, service_name=service_name, - allow=allow, min_version=min_version, max_version=max_version, - discover_versions=False, skip_discovery=skip_discovery, - allow_version_hack=allow_version_hack, **kwargs) + session, + service_type=service_type, + interface=interface, + region_name=region_name, + service_name=service_name, + allow=allow, + min_version=min_version, + max_version=max_version, + discover_versions=False, + skip_discovery=skip_discovery, + allow_version_hack=allow_version_hack, + **kwargs, + ) return endpoint_data.url if endpoint_data else None - def get_api_major_version(self, session, service_type=None, interface=None, - region_name=None, service_name=None, - version=None, allow=None, - allow_version_hack=True, skip_discovery=False, - discover_versions=False, min_version=None, - max_version=None, **kwargs): + def get_api_major_version( + self, + session, + service_type=None, + interface=None, + region_name=None, + service_name=None, + version=None, + allow=None, + allow_version_hack=True, + skip_discovery=False, + discover_versions=False, + min_version=None, + max_version=None, + **kwargs, + ): """Return the major API version for a service. If a valid token is not present then a new one will be fetched using @@ -456,8 +503,8 @@ def get_api_major_version(self, session, service_type=None, interface=None, ``block-storage`` service and they do:: client = adapter.Adapter( - session, service_type='block-storage', min_version=2, - max_version=3) + session, service_type='block-storage', min_version=2, max_version=3 + ) volume_version = client.get_api_major_version() The version actually be returned with no api calls other than getting @@ -485,15 +532,23 @@ def get_api_major_version(self, session, service_type=None, interface=None, # Explode `version` into min_version and max_version - everything below # here uses the latter rather than the former. min_version, max_version = discover._normalize_version_args( - version, min_version, max_version, service_type=service_type) + version, min_version, max_version, service_type=service_type + ) # Using functools.partial here just to reduce copy-pasta of params get_endpoint_data = functools.partial( self.get_endpoint_data, - session, service_type=service_type, interface=interface, - region_name=region_name, service_name=service_name, - allow=allow, min_version=min_version, max_version=max_version, + session, + service_type=service_type, + interface=interface, + region_name=region_name, + service_name=service_name, + allow=allow, + min_version=min_version, + max_version=max_version, skip_discovery=skip_discovery, - allow_version_hack=allow_version_hack, **kwargs) + allow_version_hack=allow_version_hack, + **kwargs, + ) data = get_endpoint_data(discover_versions=discover_versions) if (not data or not data.api_version) and not discover_versions: # It's possible that no version was requested and the endpoint @@ -505,9 +560,14 @@ def get_api_major_version(self, session, service_type=None, interface=None, return None return data.api_version - def get_all_version_data(self, session, interface='public', - region_name=None, service_type=None, - **kwargs): + def get_all_version_data( + self, + session, + interface='public', + region_name=None, + service_type=None, + **kwargs, + ): """Get version data for all services in the catalog. :param session: A session object that can be used for communication. @@ -539,12 +599,12 @@ def get_all_version_data(self, session, interface='public', for endpoint_service_type, services in endpoints_data.items(): if service_types.is_known(endpoint_service_type): endpoint_service_type = service_types.get_service_type( - endpoint_service_type) + endpoint_service_type + ) for service in services: versions = service.get_all_version_string_data( - session=session, - project_id=self.get_project_id(session), + session=session, project_id=self.get_project_id(session) ) if service.region_name not in version_data: @@ -566,15 +626,15 @@ def get_project_id(self, session, **kwargs): def get_sp_auth_url(self, session, sp_id, **kwargs): try: - return self.get_access( - session).service_providers.get_auth_url(sp_id) + return self.get_access(session).service_providers.get_auth_url( + sp_id + ) except exceptions.ServiceProviderNotFound: return None def get_sp_url(self, session, sp_id, **kwargs): try: - return self.get_access( - session).service_providers.get_sp_url(sp_id) + return self.get_access(session).service_providers.get_sp_url(sp_id) except exceptions.ServiceProviderNotFound: return None @@ -602,9 +662,12 @@ def get_discovery(self, session, url, authenticated=None): :returns: A discovery object with the results of looking up that URL. """ - return discover.get_discovery(session=session, url=url, - cache=self._discovery_cache, - authenticated=authenticated) + return discover.get_discovery( + session=session, + url=url, + cache=self._discovery_cache, + authenticated=authenticated, + ) def get_cache_id_elements(self): """Get the elements for this auth plugin that make it unique. @@ -667,8 +730,10 @@ def get_auth_state(self): :rtype: str or None if no auth present. """ if self.auth_ref: - data = {'auth_token': self.auth_ref.auth_token, - 'body': self.auth_ref._data} + data = { + 'auth_token': self.auth_ref.auth_token, + 'body': self.auth_ref._data, + } return json.dumps(data) @@ -680,7 +745,8 @@ def set_auth_state(self, data): """ if data: auth_data = json.loads(data) - self.auth_ref = access.create(body=auth_data['body'], - auth_token=auth_data['auth_token']) + self.auth_ref = access.create( + body=auth_data['body'], auth_token=auth_data['auth_token'] + ) else: self.auth_ref = None diff --git a/keystoneauth1/identity/generic/__init__.py b/keystoneauth1/identity/generic/__init__.py index df1831e3..e4115adc 100644 --- a/keystoneauth1/identity/generic/__init__.py +++ b/keystoneauth1/identity/generic/__init__.py @@ -15,7 +15,4 @@ from keystoneauth1.identity.generic.token import Token # noqa -__all__ = ('BaseGenericPlugin', - 'Password', - 'Token', - ) +__all__ = ('BaseGenericPlugin', 'Password', 'Token') diff --git a/keystoneauth1/identity/generic/base.py b/keystoneauth1/identity/generic/base.py index 22fb6540..00e36230 100644 --- a/keystoneauth1/identity/generic/base.py +++ b/keystoneauth1/identity/generic/base.py @@ -29,22 +29,24 @@ class BaseGenericPlugin(base.BaseIdentityPlugin, metaclass=abc.ABCMeta): URL and then proxy all calls from the base plugin to the versioned one. """ - def __init__(self, auth_url, - tenant_id=None, - tenant_name=None, - project_id=None, - project_name=None, - project_domain_id=None, - project_domain_name=None, - domain_id=None, - domain_name=None, - system_scope=None, - trust_id=None, - default_domain_id=None, - default_domain_name=None, - reauthenticate=True): - super(BaseGenericPlugin, self).__init__(auth_url=auth_url, - reauthenticate=reauthenticate) + def __init__( + self, + auth_url, + tenant_id=None, + tenant_name=None, + project_id=None, + project_name=None, + project_domain_id=None, + project_domain_name=None, + domain_id=None, + domain_name=None, + system_scope=None, + trust_id=None, + default_domain_id=None, + default_domain_name=None, + reauthenticate=True, + ): + super().__init__(auth_url=auth_url, reauthenticate=reauthenticate) self._project_id = project_id or tenant_id self._project_name = project_name or tenant_name @@ -86,29 +88,39 @@ def _has_domain_scope(self): :returns: True if a domain parameter is set, false otherwise. """ - return any([self._domain_id, self._domain_name, - self._project_domain_id, self._project_domain_name]) + return any( + [ + self._domain_id, + self._domain_name, + self._project_domain_id, + self._project_domain_name, + ] + ) @property def _v2_params(self): """Return the parameters that are common to v2 plugins.""" - return {'trust_id': self._trust_id, - 'tenant_id': self._project_id, - 'tenant_name': self._project_name, - 'reauthenticate': self.reauthenticate} + return { + 'trust_id': self._trust_id, + 'tenant_id': self._project_id, + 'tenant_name': self._project_name, + 'reauthenticate': self.reauthenticate, + } @property def _v3_params(self): """Return the parameters that are common to v3 plugins.""" - return {'trust_id': self._trust_id, - 'system_scope': self._system_scope, - 'project_id': self._project_id, - 'project_name': self._project_name, - 'project_domain_id': self.project_domain_id, - 'project_domain_name': self.project_domain_name, - 'domain_id': self._domain_id, - 'domain_name': self._domain_name, - 'reauthenticate': self.reauthenticate} + return { + 'trust_id': self._trust_id, + 'system_scope': self._system_scope, + 'project_id': self._project_id, + 'project_name': self._project_name, + 'project_domain_id': self.project_domain_id, + 'project_domain_name': self.project_domain_name, + 'domain_id': self._domain_id, + 'domain_name': self._domain_name, + 'reauthenticate': self.reauthenticate, + } @property def project_domain_id(self): @@ -130,16 +142,20 @@ def _do_create_plugin(self, session): plugin = None try: - disc = self.get_discovery(session, - self.auth_url, - authenticated=False) - except (exceptions.DiscoveryFailure, - exceptions.HttpError, - exceptions.SSLError, - exceptions.ConnectionError) as e: - LOG.warning('Failed to discover available identity versions when ' - 'contacting %s. Attempting to parse version from URL.', - self.auth_url) + disc = self.get_discovery( + session, self.auth_url, authenticated=False + ) + except ( + exceptions.DiscoveryFailure, + exceptions.HttpError, + exceptions.SSLError, + exceptions.ConnectionError, + ) as e: + LOG.warning( + 'Failed to discover available identity versions when ' + 'contacting %s. Attempting to parse version from URL.', + self.auth_url, + ) url_parts = urllib.parse.urlparse(self.auth_url) path = url_parts.path.lower() @@ -147,7 +163,8 @@ def _do_create_plugin(self, session): if path.startswith('/v2.0'): if self._has_domain_scope: raise exceptions.DiscoveryFailure( - 'Cannot use v2 authentication with domain scope') + 'Cannot use v2 authentication with domain scope' + ) plugin = self.create_plugin(session, (2, 0), self.auth_url) elif path.startswith('/v3'): plugin = self.create_plugin(session, (3, 0), self.auth_url) @@ -155,7 +172,8 @@ def _do_create_plugin(self, session): raise exceptions.DiscoveryFailure( 'Could not find versioned identity endpoints when ' 'attempting to authenticate. Please check that your ' - 'auth_url is correct. %s' % e) + f'auth_url is correct. {e}' + ) else: # NOTE(jamielennox): version_data is always in oldest to newest @@ -172,23 +190,28 @@ def _do_create_plugin(self, session): for data in disc_data: version = data['version'] - if (discover.version_match((2,), version) and - self._has_domain_scope): + if ( + discover.version_match((2,), version) + and self._has_domain_scope + ): # NOTE(jamielennox): if there are domain parameters there # is no point even trying against v2 APIs. v2_with_domain_scope = True continue - plugin = self.create_plugin(session, - version, - data['url'], - raw_status=data['raw_status']) + plugin = self.create_plugin( + session, + version, + data['url'], + raw_status=data['raw_status'], + ) if plugin: break if not plugin and v2_with_domain_scope: raise exceptions.DiscoveryFailure( - 'Cannot use v2 authentication with domain scope') + 'Cannot use v2 authentication with domain scope' + ) if plugin: return plugin @@ -196,7 +219,8 @@ def _do_create_plugin(self, session): # so there were no URLs that i could use for auth of any version. raise exceptions.DiscoveryFailure( 'Could not find versioned identity endpoints when attempting ' - 'to authenticate. Please check that your auth_url is correct.') + 'to authenticate. Please check that your auth_url is correct.' + ) def get_auth_ref(self, session, **kwargs): if not self._plugin: @@ -212,11 +236,13 @@ def get_cache_id_elements(self, _implemented=False): if not _implemented: raise NotImplementedError() - return {'auth_url': self.auth_url, - 'project_id': self._project_id, - 'project_name': self._project_name, - 'project_domain_id': self.project_domain_id, - 'project_domain_name': self.project_domain_name, - 'domain_id': self._domain_id, - 'domain_name': self._domain_name, - 'trust_id': self._trust_id} + return { + 'auth_url': self.auth_url, + 'project_id': self._project_id, + 'project_name': self._project_name, + 'project_domain_id': self.project_domain_id, + 'project_domain_name': self.project_domain_name, + 'domain_id': self._domain_id, + 'domain_name': self._domain_name, + 'trust_id': self._trust_id, + } diff --git a/keystoneauth1/identity/generic/password.py b/keystoneauth1/identity/generic/password.py index c62c1b27..b9d1ffc9 100644 --- a/keystoneauth1/identity/generic/password.py +++ b/keystoneauth1/identity/generic/password.py @@ -27,9 +27,17 @@ class Password(base.BaseGenericPlugin): """ - def __init__(self, auth_url, username=None, user_id=None, password=None, - user_domain_id=None, user_domain_name=None, **kwargs): - super(Password, self).__init__(auth_url=auth_url, **kwargs) + def __init__( + self, + auth_url, + username=None, + user_id=None, + password=None, + user_domain_id=None, + user_domain_name=None, + **kwargs, + ): + super().__init__(auth_url=auth_url, **kwargs) self._username = username self._user_id = user_id @@ -42,23 +50,27 @@ def create_plugin(self, session, version, url, raw_status=None): if self._user_domain_id or self._user_domain_name: return None - return v2.Password(auth_url=url, - user_id=self._user_id, - username=self._username, - password=self._password, - **self._v2_params) + return v2.Password( + auth_url=url, + user_id=self._user_id, + username=self._username, + password=self._password, + **self._v2_params, + ) elif discover.version_match((3,), version): u_domain_id = self._user_domain_id or self._default_domain_id u_domain_name = self._user_domain_name or self._default_domain_name - return v3.Password(auth_url=url, - user_id=self._user_id, - username=self._username, - user_domain_id=u_domain_id, - user_domain_name=u_domain_name, - password=self._password, - **self._v3_params) + return v3.Password( + auth_url=url, + user_id=self._user_id, + username=self._username, + user_domain_id=u_domain_id, + user_domain_name=u_domain_name, + password=self._password, + **self._v3_params, + ) @property def user_domain_id(self): @@ -77,8 +89,7 @@ def user_domain_name(self, value): self._user_domain_name = value def get_cache_id_elements(self): - elements = super(Password, self).get_cache_id_elements( - _implemented=True) + elements = super().get_cache_id_elements(_implemented=True) elements['username'] = self._username elements['user_id'] = self._user_id elements['password'] = self._password diff --git a/keystoneauth1/identity/generic/token.py b/keystoneauth1/identity/generic/token.py index 00239b61..9b32821a 100644 --- a/keystoneauth1/identity/generic/token.py +++ b/keystoneauth1/identity/generic/token.py @@ -23,7 +23,7 @@ class Token(base.BaseGenericPlugin): """ def __init__(self, auth_url, token=None, **kwargs): - super(Token, self).__init__(auth_url, **kwargs) + super().__init__(auth_url, **kwargs) self._token = token def create_plugin(self, session, version, url, raw_status=None): @@ -34,6 +34,6 @@ def create_plugin(self, session, version, url, raw_status=None): return v3.Token(url, self._token, **self._v3_params) def get_cache_id_elements(self): - elements = super(Token, self).get_cache_id_elements(_implemented=True) + elements = super().get_cache_id_elements(_implemented=True) elements['token'] = self._token return elements diff --git a/keystoneauth1/identity/v2.py b/keystoneauth1/identity/v2.py index 44b33a75..864ab1b6 100644 --- a/keystoneauth1/identity/v2.py +++ b/keystoneauth1/identity/v2.py @@ -31,13 +31,15 @@ class Auth(base.BaseIdentityPlugin, metaclass=abc.ABCMeta): is going to expire. (optional) default True """ - def __init__(self, auth_url, - trust_id=None, - tenant_id=None, - tenant_name=None, - reauthenticate=True): - super(Auth, self).__init__(auth_url=auth_url, - reauthenticate=reauthenticate) + def __init__( + self, + auth_url, + trust_id=None, + tenant_id=None, + tenant_name=None, + reauthenticate=True, + ): + super().__init__(auth_url=auth_url, reauthenticate=reauthenticate) self.trust_id = trust_id self.tenant_id = tenant_id @@ -56,8 +58,9 @@ def get_auth_ref(self, session, **kwargs): params['auth']['trust_id'] = self.trust_id _logger.debug('Making authentication request to %s', url) - resp = session.post(url, json=params, headers=headers, - authenticated=False, log=False) + resp = session.post( + url, json=params, headers=headers, authenticated=False, log=False + ) try: resp_data = resp.json() @@ -106,9 +109,15 @@ class Password(Auth): :raises TypeError: if a user_id or username is not provided. """ - def __init__(self, auth_url, username=_NOT_PASSED, password=None, - user_id=_NOT_PASSED, **kwargs): - super(Password, self).__init__(auth_url, **kwargs) + def __init__( + self, + auth_url, + username=_NOT_PASSED, + password=None, + user_id=_NOT_PASSED, + **kwargs, + ): + super().__init__(auth_url, **kwargs) if username is _NOT_PASSED and user_id is _NOT_PASSED: msg = 'You need to specify either a username or user_id' @@ -134,13 +143,15 @@ def get_auth_data(self, headers=None): return {'passwordCredentials': auth} def get_cache_id_elements(self): - return {'username': self.username, - 'user_id': self.user_id, - 'password': self.password, - 'auth_url': self.auth_url, - 'tenant_id': self.tenant_id, - 'tenant_name': self.tenant_name, - 'trust_id': self.trust_id} + return { + 'username': self.username, + 'user_id': self.user_id, + 'password': self.password, + 'auth_url': self.auth_url, + 'tenant_id': self.tenant_id, + 'tenant_name': self.tenant_name, + 'trust_id': self.trust_id, + } class Token(Auth): @@ -156,7 +167,7 @@ class Token(Auth): """ def __init__(self, auth_url, token, **kwargs): - super(Token, self).__init__(auth_url, **kwargs) + super().__init__(auth_url, **kwargs) self.token = token def get_auth_data(self, headers=None): @@ -165,8 +176,10 @@ def get_auth_data(self, headers=None): return {'token': {'id': self.token}} def get_cache_id_elements(self): - return {'token': self.token, - 'auth_url': self.auth_url, - 'tenant_id': self.tenant_id, - 'tenant_name': self.tenant_name, - 'trust_id': self.trust_id} + return { + 'token': self.token, + 'auth_url': self.auth_url, + 'tenant_id': self.tenant_id, + 'tenant_name': self.tenant_name, + 'trust_id': self.trust_id, + } diff --git a/keystoneauth1/identity/v3/__init__.py b/keystoneauth1/identity/v3/__init__.py index b10c390a..6beb0dfe 100644 --- a/keystoneauth1/identity/v3/__init__.py +++ b/keystoneauth1/identity/v3/__init__.py @@ -27,40 +27,29 @@ from keystoneauth1.identity.v3.oauth2_mtls_client_credential import * # noqa -__all__ = ('ApplicationCredential', - 'ApplicationCredentialMethod', - - 'Auth', - 'AuthConstructor', - 'AuthMethod', - 'BaseAuth', - - 'FederationBaseAuth', - - 'Keystone2Keystone', - - 'Password', - 'PasswordMethod', - - 'Token', - 'TokenMethod', - - 'OidcAccessToken', - 'OidcAuthorizationCode', - 'OidcClientCredentials', - 'OidcPassword', - - 'TOTPMethod', - 'TOTP', - - 'TokenlessAuth', - - 'ReceiptMethod', - - 'MultiFactor', - - 'OAuth2ClientCredential', - 'OAuth2ClientCredentialMethod', - - 'OAuth2mTlsClientCredential', - ) +__all__ = ( + 'ApplicationCredential', + 'ApplicationCredentialMethod', + 'Auth', + 'AuthConstructor', + 'AuthMethod', + 'BaseAuth', + 'FederationBaseAuth', + 'Keystone2Keystone', + 'Password', + 'PasswordMethod', + 'Token', + 'TokenMethod', + 'OidcAccessToken', + 'OidcAuthorizationCode', + 'OidcClientCredentials', + 'OidcPassword', + 'TOTPMethod', + 'TOTP', + 'TokenlessAuth', + 'ReceiptMethod', + 'MultiFactor', + 'OAuth2ClientCredential', + 'OAuth2ClientCredentialMethod', + 'OAuth2mTlsClientCredential', +) diff --git a/keystoneauth1/identity/v3/application_credential.py b/keystoneauth1/identity/v3/application_credential.py index 8dc2e570..848cd174 100644 --- a/keystoneauth1/identity/v3/application_credential.py +++ b/keystoneauth1/identity/v3/application_credential.py @@ -37,13 +37,15 @@ class ApplicationCredentialMethod(base.AuthMethod): provided. """ - _method_parameters = ['application_credential_secret', - 'application_credential_id', - 'application_credential_name', - 'user_id', - 'username', - 'user_domain_id', - 'user_domain_name'] + _method_parameters = [ + 'application_credential_secret', + 'application_credential_id', + 'application_credential_name', + 'user_id', + 'username', + 'user_domain_id', + 'user_domain_name', + ] def get_auth_data(self, session, auth, headers, **kwargs): auth_data = {'secret': self.application_credential_secret} @@ -62,13 +64,16 @@ def get_auth_data(self, session, auth, headers, **kwargs): auth_data['user']['domain'] = {'id': self.user_domain_id} elif self.user_domain_name: auth_data['user']['domain'] = { - 'name': self.user_domain_name} + 'name': self.user_domain_name + } return 'application_credential', auth_data def get_cache_id_elements(self): - return dict(('application_credential_%s' % p, getattr(self, p)) - for p in self._method_parameters) + return { + f'application_credential_{p}': getattr(self, p) + for p in self._method_parameters + } class ApplicationCredential(base.AuthConstructor): diff --git a/keystoneauth1/identity/v3/base.py b/keystoneauth1/identity/v3/base.py index 7fe0bd6b..80f22092 100644 --- a/keystoneauth1/identity/v3/base.py +++ b/keystoneauth1/identity/v3/base.py @@ -41,19 +41,21 @@ class BaseAuth(base.BaseIdentityPlugin, metaclass=abc.ABCMeta): token. (optional) default True. """ - def __init__(self, auth_url, - trust_id=None, - system_scope=None, - domain_id=None, - domain_name=None, - project_id=None, - project_name=None, - project_domain_id=None, - project_domain_name=None, - reauthenticate=True, - include_catalog=True): - super(BaseAuth, self).__init__(auth_url=auth_url, - reauthenticate=reauthenticate) + def __init__( + self, + auth_url, + trust_id=None, + system_scope=None, + domain_id=None, + domain_name=None, + project_id=None, + project_name=None, + project_domain_id=None, + project_domain_name=None, + reauthenticate=True, + include_catalog=True, + ): + super().__init__(auth_url=auth_url, reauthenticate=reauthenticate) self.trust_id = trust_id self.system_scope = system_scope self.domain_id = domain_id @@ -67,7 +69,7 @@ def __init__(self, auth_url, @property def token_url(self): """The full URL where we will send authentication data.""" - return '%s/auth/tokens' % self.auth_url.rstrip('/') + return '{}/auth/tokens'.format(self.auth_url.rstrip('/')) @abc.abstractmethod def get_auth_ref(self, session, **kwargs): @@ -76,9 +78,14 @@ def get_auth_ref(self, session, **kwargs): @property def has_scope_parameters(self): """Return true if parameters can be used to create a scoped token.""" - return (self.domain_id or self.domain_name or - self.project_id or self.project_name or - self.trust_id or self.system_scope) + return ( + self.domain_id + or self.domain_name + or self.project_id + or self.project_name + or self.trust_id + or self.system_scope + ) class Auth(BaseAuth): @@ -104,7 +111,7 @@ class Auth(BaseAuth): def __init__(self, auth_url, auth_methods, **kwargs): self.unscoped = kwargs.pop('unscoped', False) - super(Auth, self).__init__(auth_url=auth_url, **kwargs) + super().__init__(auth_url=auth_url, **kwargs) self.auth_methods = auth_methods def add_method(self, method): @@ -119,7 +126,8 @@ def get_auth_ref(self, session, **kwargs): for method in self.auth_methods: name, auth_data = method.get_auth_data( - session, self, headers, request_kwargs=rkwargs) + session, self, headers, request_kwargs=rkwargs + ) # NOTE(adriant): Methods like ReceiptMethod don't # want anything added to the request data, so they # explicitly return None, which we check for. @@ -129,19 +137,23 @@ def get_auth_ref(self, session, **kwargs): if not ident: raise exceptions.AuthorizationFailure( - 'Authentication method required (e.g. password)') + 'Authentication method required (e.g. password)' + ) - mutual_exclusion = [bool(self.domain_id or self.domain_name), - bool(self.project_id or self.project_name), - bool(self.trust_id), - bool(self.system_scope), - bool(self.unscoped)] + mutual_exclusion = [ + bool(self.domain_id or self.domain_name), + bool(self.project_id or self.project_name), + bool(self.trust_id), + bool(self.system_scope), + bool(self.unscoped), + ] if sum(mutual_exclusion) > 1: raise exceptions.AuthorizationFailure( message='Authentication cannot be scoped to multiple' - ' targets. Pick one of: project, domain, ' - 'trust, system or unscoped') + ' targets. Pick one of: project, domain, ' + 'trust, system or unscoped' + ) if self.domain_id: body['auth']['scope'] = {'domain': {'id': self.domain_id}} @@ -174,7 +186,7 @@ def get_auth_ref(self, session, **kwargs): token_url = self.token_url if not self.auth_url.rstrip('/').endswith('v3'): - token_url = '%s/v3/auth/tokens' % self.auth_url.rstrip('/') + token_url = '{}/v3/auth/tokens'.format(self.auth_url.rstrip('/')) # NOTE(jamielennox): we add nocatalog here rather than in token_url # directly as some federation plugins require the base token_url @@ -182,8 +194,14 @@ def get_auth_ref(self, session, **kwargs): token_url += '?nocatalog' _logger.debug('Making authentication request to %s', token_url) - resp = session.post(token_url, json=body, headers=headers, - authenticated=False, log=False, **rkwargs) + resp = session.post( + token_url, + json=body, + headers=headers, + authenticated=False, + log=False, + **rkwargs, + ) try: _logger.debug(json.dumps(resp.json())) @@ -194,21 +212,24 @@ def get_auth_ref(self, session, **kwargs): if 'token' not in resp_data: raise exceptions.InvalidResponse(response=resp) - return access.AccessInfoV3(auth_token=resp.headers['X-Subject-Token'], - body=resp_data) + return access.AccessInfoV3( + auth_token=resp.headers['X-Subject-Token'], body=resp_data + ) def get_cache_id_elements(self): if not self.auth_methods: return None - params = {'auth_url': self.auth_url, - 'domain_id': self.domain_id, - 'domain_name': self.domain_name, - 'project_id': self.project_id, - 'project_name': self.project_name, - 'project_domain_id': self.project_domain_id, - 'project_domain_name': self.project_domain_name, - 'trust_id': self.trust_id} + params = { + 'auth_url': self.auth_url, + 'domain_id': self.domain_id, + 'domain_name': self.domain_name, + 'project_id': self.project_id, + 'project_name': self.project_name, + 'project_domain_id': self.project_domain_id, + 'project_domain_name': self.project_domain_name, + 'trust_id': self.trust_id, + } for method in self.auth_methods: try: @@ -240,14 +261,13 @@ def __init__(self, **kwargs): setattr(self, param, kwargs.pop(param, None)) if kwargs: - msg = "Unexpected Attributes: %s" % ", ".join(kwargs.keys()) + msg = "Unexpected Attributes: {}".format(", ".join(kwargs.keys())) raise AttributeError(msg) @classmethod def _extract_kwargs(cls, kwargs): """Remove parameters related to this method from other kwargs.""" - return dict([(p, kwargs.pop(p, None)) - for p in cls._method_parameters]) + return {p: kwargs.pop(p, None) for p in cls._method_parameters} @abc.abstractmethod def get_auth_data(self, session, auth, headers, **kwargs): @@ -296,4 +316,4 @@ class AuthConstructor(Auth, metaclass=abc.ABCMeta): def __init__(self, auth_url, *args, **kwargs): method_kwargs = self._auth_method_class._extract_kwargs(kwargs) method = self._auth_method_class(*args, **method_kwargs) - super(AuthConstructor, self).__init__(auth_url, [method], **kwargs) + super().__init__(auth_url, [method], **kwargs) diff --git a/keystoneauth1/identity/v3/federation.py b/keystoneauth1/identity/v3/federation.py index b8c4faf6..65b7d415 100644 --- a/keystoneauth1/identity/v3/federation.py +++ b/keystoneauth1/identity/v3/federation.py @@ -35,13 +35,15 @@ class _Rescoped(base.BaseAuth, metaclass=abc.ABCMeta): rescoping_plugin = token.Token def _get_scoping_data(self): - return {'trust_id': self.trust_id, - 'domain_id': self.domain_id, - 'domain_name': self.domain_name, - 'project_id': self.project_id, - 'project_name': self.project_name, - 'project_domain_id': self.project_domain_id, - 'project_domain_name': self.project_domain_name} + return { + 'trust_id': self.trust_id, + 'domain_id': self.domain_id, + 'domain_name': self.domain_name, + 'project_id': self.project_id, + 'project_name': self.project_name, + 'project_domain_id': self.project_domain_id, + 'project_domain_name': self.project_domain_name, + } def get_auth_ref(self, session, **kwargs): """Authenticate retrieve token information. @@ -63,9 +65,9 @@ def get_auth_ref(self, session, **kwargs): scoping = self._get_scoping_data() if any(scoping.values()): - token_plugin = self.rescoping_plugin(self.auth_url, - token=auth_ref.auth_token, - **scoping) + token_plugin = self.rescoping_plugin( + self.auth_url, token=auth_ref.auth_token, **scoping + ) auth_ref = token_plugin.get_auth_ref(session) @@ -93,7 +95,7 @@ class FederationBaseAuth(_Rescoped): """ def __init__(self, auth_url, identity_provider, protocol, **kwargs): - super(FederationBaseAuth, self).__init__(auth_url=auth_url, **kwargs) + super().__init__(auth_url=auth_url, **kwargs) self.identity_provider = identity_provider self.protocol = protocol @@ -106,10 +108,12 @@ def federated_token_url(self): values = { 'host': host, 'identity_provider': self.identity_provider, - 'protocol': self.protocol + 'protocol': self.protocol, } - url = ("%(host)s/OS-FEDERATION/identity_providers/" - "%(identity_provider)s/protocols/%(protocol)s/auth") + url = ( + "%(host)s/OS-FEDERATION/identity_providers/" + "%(identity_provider)s/protocols/%(protocol)s/auth" + ) url = url % values return url diff --git a/keystoneauth1/identity/v3/k2k.py b/keystoneauth1/identity/v3/k2k.py index 2d96e502..1f225aa5 100644 --- a/keystoneauth1/identity/v3/k2k.py +++ b/keystoneauth1/identity/v3/k2k.py @@ -43,7 +43,7 @@ class Keystone2Keystone(federation._Rescoped): HTTP_SEE_OTHER = 303 def __init__(self, base_plugin, service_provider, **kwargs): - super(Keystone2Keystone, self).__init__(auth_url=None, **kwargs) + super().__init__(auth_url=None, **kwargs) self._local_cloud_plugin = base_plugin self._sp_id = service_provider @@ -81,36 +81,38 @@ def _get_ecp_assertion(self, session): 'methods': ['token'], 'token': { 'id': self._local_cloud_plugin.get_token(session) - } + }, }, - 'scope': { - 'service_provider': { - 'id': self._sp_id - } - } + 'scope': {'service_provider': {'id': self._sp_id}}, } } - endpoint_filter = {'version': (3, 0), - 'interface': plugin.AUTH_INTERFACE} + endpoint_filter = { + 'version': (3, 0), + 'interface': plugin.AUTH_INTERFACE, + } headers = {'Accept': 'application/json'} - resp = session.post(self.REQUEST_ECP_URL, - json=body, - auth=self._local_cloud_plugin, - endpoint_filter=endpoint_filter, - headers=headers, - authenticated=False, - raise_exc=False) + resp = session.post( + self.REQUEST_ECP_URL, + json=body, + auth=self._local_cloud_plugin, + endpoint_filter=endpoint_filter, + headers=headers, + authenticated=False, + raise_exc=False, + ) # NOTE(marek-denis): I am not sure whether disabling exceptions in the # Session object and testing if resp.ok is sufficient. An alternative # would be catching locally all exceptions and reraising with custom # warning. if not resp.ok: - msg = ("Error while requesting ECP wrapped assertion: response " - "exit code: %(status_code)d, reason: %(err)s") + msg = ( + "Error while requesting ECP wrapped assertion: response " + "exit code: %(status_code)d, reason: %(err)s" + ) msg = msg % {'status_code': resp.status_code, 'err': resp.reason} raise exceptions.AuthorizationFailure(msg) @@ -119,8 +121,9 @@ def _get_ecp_assertion(self, session): return str(resp.text) - def _send_service_provider_ecp_authn_response(self, session, sp_url, - sp_auth_url): + def _send_service_provider_ecp_authn_response( + self, session, sp_url, sp_auth_url + ): """Present ECP wrapped SAML assertion to the keystone SP. The assertion is issued by the keystone IdP and it is targeted to the @@ -145,27 +148,33 @@ def _send_service_provider_ecp_authn_response(self, session, sp_url, headers={'Content-Type': 'application/vnd.paos+xml'}, data=self._get_ecp_assertion(session), authenticated=False, - redirect=False) + redirect=False, + ) # Don't follow HTTP specs - after the HTTP 302/303 response don't # repeat the call directed to the Location URL. In this case, this is # an indication that SAML2 session is now active and protected resource # can be accessed. - if response.status_code in (self.HTTP_MOVED_TEMPORARILY, - self.HTTP_SEE_OTHER): + if response.status_code in ( + self.HTTP_MOVED_TEMPORARILY, + self.HTTP_SEE_OTHER, + ): response = session.get( sp_auth_url, headers={'Content-Type': 'application/vnd.paos+xml'}, - authenticated=False) + authenticated=False, + ) return response def get_unscoped_auth_ref(self, session, **kwargs): sp_auth_url = self._local_cloud_plugin.get_sp_auth_url( - session, self._sp_id) + session, self._sp_id + ) sp_url = self._local_cloud_plugin.get_sp_url(session, self._sp_id) self.auth_url = self._remote_auth_url(sp_auth_url) response = self._send_service_provider_ecp_authn_response( - session, sp_url, sp_auth_url) + session, sp_url, sp_auth_url + ) return access.create(resp=response) diff --git a/keystoneauth1/identity/v3/multi_factor.py b/keystoneauth1/identity/v3/multi_factor.py index de47473b..26ce8341 100644 --- a/keystoneauth1/identity/v3/multi_factor.py +++ b/keystoneauth1/identity/v3/multi_factor.py @@ -14,7 +14,7 @@ from keystoneauth1 import loading -__all__ = ('MultiFactor', ) +__all__ = ('MultiFactor',) class MultiFactor(base.Auth): @@ -42,7 +42,8 @@ def __init__(self, auth_url, auth_methods, **kwargs): for method in auth_methods: # Using the loaders we pull the related auth method class method_class = loading.get_plugin_loader( - method).plugin_class._auth_method_class + method + ).plugin_class._auth_method_class # We build some new kwargs for the method from required parameters method_kwargs = {} for key in method_class._method_parameters: @@ -56,4 +57,4 @@ def __init__(self, auth_url, auth_methods, **kwargs): # to the super class and throw errors for key in method_keys: kwargs.pop(key, None) - super(MultiFactor, self).__init__(auth_url, method_instances, **kwargs) + super().__init__(auth_url, method_instances, **kwargs) diff --git a/keystoneauth1/identity/v3/oauth2_client_credential.py b/keystoneauth1/identity/v3/oauth2_client_credential.py index dac91df5..6adec4de 100644 --- a/keystoneauth1/identity/v3/oauth2_client_credential.py +++ b/keystoneauth1/identity/v3/oauth2_client_credential.py @@ -31,7 +31,7 @@ class OAuth2ClientCredentialMethod(base.AuthMethod): _method_parameters = [ 'oauth2_endpoint', 'oauth2_client_id', - 'oauth2_client_secret' + 'oauth2_client_secret', ] def get_auth_data(self, session, auth, headers, **kwargs): @@ -48,7 +48,7 @@ def get_auth_data(self, session, auth, headers, **kwargs): """ auth_data = { 'id': self.oauth2_client_id, - 'secret': self.oauth2_client_secret + 'secret': self.oauth2_client_secret, } return 'application_credential', auth_data @@ -66,8 +66,10 @@ def get_cache_id_elements(self): should be prefixed with the plugin identifier. For example the password plugin returns its username value as 'password_username'. """ - return dict(('oauth2_client_credential_%s' % p, getattr(self, p)) - for p in self._method_parameters) + return { + f'oauth2_client_credential_{p}': getattr(self, p) + for p in self._method_parameters + } class OAuth2ClientCredential(base.AuthConstructor): @@ -82,7 +84,7 @@ class OAuth2ClientCredential(base.AuthConstructor): _auth_method_class = OAuth2ClientCredentialMethod def __init__(self, auth_url, *args, **kwargs): - super(OAuth2ClientCredential, self).__init__(auth_url, *args, **kwargs) + super().__init__(auth_url, *args, **kwargs) self._oauth2_endpoint = kwargs['oauth2_endpoint'] self._oauth2_client_id = kwargs['oauth2_client_id'] self._oauth2_client_secret = kwargs['oauth2_client_secret'] @@ -99,19 +101,21 @@ def get_headers(self, session, **kwargs): :rtype: dict """ # get headers for X-Auth-Token - headers = super(OAuth2ClientCredential, self).get_headers( - session, **kwargs) + headers = super().get_headers(session, **kwargs) # Get OAuth2.0 access token and add the field 'Authorization' data = {"grant_type": "client_credentials"} - auth = requests.auth.HTTPBasicAuth(self._oauth2_client_id, - self._oauth2_client_secret) - resp = session.request(self._oauth2_endpoint, - "POST", - authenticated=False, - raise_exc=False, - data=data, - requests_auth=auth) + auth = requests.auth.HTTPBasicAuth( + self._oauth2_client_id, self._oauth2_client_secret + ) + resp = session.request( + self._oauth2_endpoint, + "POST", + authenticated=False, + raise_exc=False, + data=data, + requests_auth=auth, + ) if resp.status_code == 200: oauth2 = resp.json() oauth2_token = oauth2["access_token"] diff --git a/keystoneauth1/identity/v3/oauth2_mtls_client_credential.py b/keystoneauth1/identity/v3/oauth2_mtls_client_credential.py index 3965deb8..69d08a08 100644 --- a/keystoneauth1/identity/v3/oauth2_mtls_client_credential.py +++ b/keystoneauth1/identity/v3/oauth2_mtls_client_credential.py @@ -27,10 +27,10 @@ class OAuth2mTlsClientCredential(base.BaseAuth, metaclass=abc.ABCMeta): :param string oauth2_client_id: OAuth2.0 client credential id. """ - def __init__(self, auth_url, oauth2_endpoint, oauth2_client_id, - *args, **kwargs): - super(OAuth2mTlsClientCredential, self).__init__( - auth_url, *args, **kwargs) + def __init__( + self, auth_url, oauth2_endpoint, oauth2_client_id, *args, **kwargs + ): + super().__init__(auth_url, *args, **kwargs) self.auth_url = auth_url self.oauth2_endpoint = oauth2_endpoint self.oauth2_client_id = oauth2_client_id @@ -64,12 +64,16 @@ def get_auth_ref(self, session, **kwargs): """ # Get OAuth2.0 access token and add the field 'Authorization' when # using the HTTPS protocol. - data = {'grant_type': 'client_credentials', - 'client_id': self.oauth2_client_id} - resp = session.post(url=self.oauth2_endpoint, - authenticated=False, - raise_exc=False, - data=data) + data = { + 'grant_type': 'client_credentials', + 'client_id': self.oauth2_client_id, + } + resp = session.post( + url=self.oauth2_endpoint, + authenticated=False, + raise_exc=False, + data=data, + ) if resp.status_code == 200: oauth2 = resp.json() self.oauth2_access_token = oauth2.get('access_token') @@ -78,17 +82,18 @@ def get_auth_ref(self, session, **kwargs): msg = error.get('error_description') raise exceptions.ClientException(msg) - headers = {'Accept': 'application/json', - 'X-Auth-Token': self.oauth2_access_token, - 'X-Subject-Token': self.oauth2_access_token} + headers = { + 'Accept': 'application/json', + 'X-Auth-Token': self.oauth2_access_token, + 'X-Subject-Token': self.oauth2_access_token, + } - token_url = '%s/auth/tokens' % self.auth_url.rstrip('/') + token_url = '{}/auth/tokens'.format(self.auth_url.rstrip('/')) if not self.auth_url.rstrip('/').endswith('v3'): - token_url = '%s/v3/auth/tokens' % self.auth_url.rstrip('/') - resp = session.get(url=token_url, - authenticated=False, - headers=headers, - log=False) + token_url = '{}/v3/auth/tokens'.format(self.auth_url.rstrip('/')) + resp = session.get( + url=token_url, authenticated=False, headers=headers, log=False + ) try: resp_data = resp.json() except ValueError: @@ -96,8 +101,9 @@ def get_auth_ref(self, session, **kwargs): if 'token' not in resp_data: raise exceptions.InvalidResponse(response=resp) - return access.AccessInfoV3(auth_token=self.oauth2_access_token, - body=resp_data) + return access.AccessInfoV3( + auth_token=self.oauth2_access_token, body=resp_data + ) def get_headers(self, session, **kwargs): """Fetch authentication headers for message. @@ -111,8 +117,7 @@ def get_headers(self, session, **kwargs): :rtype: dict """ # get headers for X-Auth-Token - headers = super(OAuth2mTlsClientCredential, self).get_headers( - session, **kwargs) + headers = super().get_headers(session, **kwargs) # add OAuth2.0 access token to the headers if headers: diff --git a/keystoneauth1/identity/v3/oidc.py b/keystoneauth1/identity/v3/oidc.py index 826bbf34..38ccc7fd 100644 --- a/keystoneauth1/identity/v3/oidc.py +++ b/keystoneauth1/identity/v3/oidc.py @@ -27,10 +27,12 @@ _logger = utils.get_logger(__name__) -__all__ = ('OidcAuthorizationCode', - 'OidcClientCredentials', - 'OidcPassword', - 'OidcAccessToken') +__all__ = ( + 'OidcAuthorizationCode', + 'OidcClientCredentials', + 'OidcPassword', + 'OidcAccessToken', +) SENSITIVE_KEYS = ("password", "code", "token", "secret") @@ -44,14 +46,20 @@ class _OidcBase(federation.FederationBaseAuth, metaclass=abc.ABCMeta): grant_type = None - def __init__(self, auth_url, identity_provider, protocol, - client_id, client_secret, - access_token_type, - scope="openid profile", - access_token_endpoint=None, - discovery_endpoint=None, - grant_type=None, - **kwargs): + def __init__( + self, + auth_url, + identity_provider, + protocol, + client_id, + client_secret, + access_token_type, + scope="openid profile", + access_token_endpoint=None, + discovery_endpoint=None, + grant_type=None, + **kwargs, + ): """The OpenID Connect plugin expects the following. :param auth_url: URL of the Identity Service @@ -96,8 +104,7 @@ def __init__(self, auth_url, identity_provider, protocol, states that "openid" must be always specified. :type scope: string """ - super(_OidcBase, self).__init__(auth_url, identity_provider, protocol, - **kwargs) + super().__init__(auth_url, identity_provider, protocol, **kwargs) self.client_id = client_id self.client_secret = client_secret @@ -111,15 +118,17 @@ def __init__(self, auth_url, identity_provider, protocol, if grant_type is not None: if grant_type != self.grant_type: raise exceptions.OidcGrantTypeMissmatch() - warnings.warn("Passing grant_type as an argument has been " - "deprecated as it is now defined in the plugin " - "itself. You should stop passing this argument " - "to the plugin, as it will be ignored, since you " - "cannot pass a free text string as a grant_type. " - "This argument will be dropped from the plugin in " - "July 2017 or with the next major release of " - "keystoneauth (3.0.0)", - DeprecationWarning) + warnings.warn( + "Passing grant_type as an argument has been " + "deprecated as it is now defined in the plugin " + "itself. You should stop passing this argument " + "to the plugin, as it will be ignored, since you " + "cannot pass a free text string as a grant_type. " + "This argument will be dropped from the plugin in " + "July 2017 or with the next major release of " + "keystoneauth (3.0.0)", + DeprecationWarning, + ) def _get_discovery_document(self, session): """Get the contents of the OpenID Connect Discovery Document. @@ -137,14 +146,18 @@ def _get_discovery_document(self, session): otherwise it will return an empty dict. :rtype: dict """ - if (self.discovery_endpoint is not None - and not self._discovery_document): + if ( + self.discovery_endpoint is not None + and not self._discovery_document + ): try: - resp = session.get(self.discovery_endpoint, - authenticated=False) + resp = session.get( + self.discovery_endpoint, authenticated=False + ) except exceptions.HttpError: - _logger.error("Cannot fetch discovery document %(discovery)s" % - {"discovery": self.discovery_endpoint}) + _logger.error( + f"Cannot fetch discovery document {self.discovery_endpoint}" + ) raise try: @@ -211,20 +224,25 @@ def _get_access_token(self, session, payload): sanitized_payload = self._sanitize(payload) _logger.debug( "Making OpenID-Connect authentication request to %s with " - "data %s", access_token_endpoint, sanitized_payload + "data %s", + access_token_endpoint, + sanitized_payload, ) - op_response = session.post(access_token_endpoint, - requests_auth=client_auth, - data=payload, - log=False, - authenticated=False) + op_response = session.post( + access_token_endpoint, + requests_auth=client_auth, + data=payload, + log=False, + authenticated=False, + ) response = op_response.json() if _logger.isEnabledFor(logging.DEBUG): sanitized_response = self._sanitize(response) _logger.debug( "OpenID-Connect authentication response from %s is %s", - access_token_endpoint, sanitized_response + access_token_endpoint, + sanitized_response, ) return response[self.access_token_type] @@ -247,9 +265,9 @@ def _get_keystone_token(self, session, access_token): """ # use access token against protected URL headers = {'Authorization': 'Bearer ' + access_token} - auth_response = session.post(self.federated_token_url, - headers=headers, - authenticated=False) + auth_response = session.post( + self.federated_token_url, headers=headers, authenticated=False + ) return auth_response def get_unscoped_auth_ref(self, session): @@ -278,8 +296,11 @@ def get_unscoped_auth_ref(self, session): # First of all, check if the grant type is supported discovery = self._get_discovery_document(session) grant_types = discovery.get("grant_types_supported") - if (grant_types and self.grant_type is not None - and self.grant_type not in grant_types): + if ( + grant_types + and self.grant_type is not None + and self.grant_type not in grant_types + ): raise exceptions.OidcPluginNotSupported() # Get the payload @@ -317,13 +338,21 @@ class OidcPassword(_OidcBase): grant_type = "password" - def __init__(self, auth_url, identity_provider, protocol, # nosec - client_id, client_secret, - access_token_endpoint=None, - discovery_endpoint=None, - access_token_type='access_token', - username=None, password=None, idp_otp_key=None, - **kwargs): + def __init__( + self, + auth_url, + identity_provider, + protocol, # nosec + client_id, + client_secret, + access_token_endpoint=None, + discovery_endpoint=None, + access_token_type='access_token', + username=None, + password=None, + idp_otp_key=None, + **kwargs, + ): """The OpenID Password plugin expects the following. :param username: Username used to authenticate @@ -332,7 +361,7 @@ def __init__(self, auth_url, identity_provider, protocol, # nosec :param password: Password used to authenticate :type password: string """ - super(OidcPassword, self).__init__( + super().__init__( auth_url=auth_url, identity_provider=identity_provider, protocol=protocol, @@ -341,7 +370,8 @@ def __init__(self, auth_url, identity_provider, protocol, # nosec access_token_endpoint=access_token_endpoint, discovery_endpoint=discovery_endpoint, access_token_type=access_token_type, - **kwargs) + **kwargs, + ) self.username = username self.password = password self.idp_otp_key = idp_otp_key @@ -355,10 +385,12 @@ def get_payload(self, session): :returns: a python dictionary containing the payload to be exchanged :rtype: dict """ - payload = {'username': self.username, - 'password': self.password, - 'scope': self.scope, - 'client_id': self.client_id} + payload = { + 'username': self.username, + 'password': self.password, + 'scope': self.scope, + 'client_id': self.client_id, + } self.manage_otp_from_session_or_request_to_the_user(payload, session) @@ -391,7 +423,8 @@ def manage_otp_from_session_or_request_to_the_user(self, payload, session): payload[self.idp_otp_key] = otp_from_session else: payload[self.idp_otp_key] = input( - "Please, enter the generated OTP code: ") + "Please, enter the generated OTP code: " + ) setattr(session, 'otp', payload[self.idp_otp_key]) @@ -400,12 +433,18 @@ class OidcClientCredentials(_OidcBase): grant_type = 'client_credentials' - def __init__(self, auth_url, identity_provider, protocol, # nosec - client_id, client_secret, - access_token_endpoint=None, - discovery_endpoint=None, - access_token_type='access_token', - **kwargs): + def __init__( + self, + auth_url, + identity_provider, + protocol, # nosec + client_id, + client_secret, + access_token_endpoint=None, + discovery_endpoint=None, + access_token_type='access_token', + **kwargs, + ): """The OpenID Client Credentials expects the following. :param client_id: Client ID used to authenticate @@ -414,7 +453,7 @@ def __init__(self, auth_url, identity_provider, protocol, # nosec :param client_secret: Client Secret used to authenticate :type password: string """ - super(OidcClientCredentials, self).__init__( + super().__init__( auth_url=auth_url, identity_provider=identity_provider, protocol=protocol, @@ -423,7 +462,8 @@ def __init__(self, auth_url, identity_provider, protocol, # nosec access_token_endpoint=access_token_endpoint, discovery_endpoint=discovery_endpoint, access_token_type=access_token_type, - **kwargs) + **kwargs, + ) def get_payload(self, session): """Get an authorization grant for the client credentials grant type. @@ -443,12 +483,20 @@ class OidcAuthorizationCode(_OidcBase): grant_type = 'authorization_code' - def __init__(self, auth_url, identity_provider, protocol, # nosec - client_id, client_secret, - access_token_endpoint=None, - discovery_endpoint=None, - access_token_type='access_token', - redirect_uri=None, code=None, **kwargs): + def __init__( + self, + auth_url, + identity_provider, + protocol, # nosec + client_id, + client_secret, + access_token_endpoint=None, + discovery_endpoint=None, + access_token_type='access_token', + redirect_uri=None, + code=None, + **kwargs, + ): """The OpenID Authorization Code plugin expects the following. :param redirect_uri: OpenID Connect Client Redirect URL @@ -458,7 +506,7 @@ def __init__(self, auth_url, identity_provider, protocol, # nosec :type code: string """ - super(OidcAuthorizationCode, self).__init__( + super().__init__( auth_url=auth_url, identity_provider=identity_provider, protocol=protocol, @@ -467,7 +515,8 @@ def __init__(self, auth_url, identity_provider, protocol, # nosec access_token_endpoint=access_token_endpoint, discovery_endpoint=discovery_endpoint, access_token_type=access_token_type, - **kwargs) + **kwargs, + ) self.redirect_uri = redirect_uri self.code = code @@ -488,8 +537,9 @@ def get_payload(self, session): class OidcAccessToken(_OidcBase): """Implementation for OpenID Connect access token reuse.""" - def __init__(self, auth_url, identity_provider, protocol, - access_token, **kwargs): + def __init__( + self, auth_url, identity_provider, protocol, access_token, **kwargs + ): """The OpenID Connect plugin based on the Access Token. It expects the following: @@ -507,13 +557,16 @@ def __init__(self, auth_url, identity_provider, protocol, :param access_token: OpenID Connect Access token :type access_token: string """ - super(OidcAccessToken, self).__init__(auth_url, identity_provider, - protocol, - client_id=None, - client_secret=None, - access_token_endpoint=None, - access_token_type=None, - **kwargs) + super().__init__( + auth_url, + identity_provider, + protocol, + client_id=None, + client_secret=None, + access_token_endpoint=None, + access_token_type=None, + **kwargs, + ) self.access_token = access_token def get_payload(self, session): @@ -546,13 +599,20 @@ class OidcDeviceAuthorization(_OidcBase): grant_type = "urn:ietf:params:oauth:grant-type:device_code" HEADER_X_FORM = {"Content-Type": "application/x-www-form-urlencoded"} - def __init__(self, auth_url, identity_provider, protocol, # nosec - client_id, client_secret=None, - access_token_endpoint=None, - device_authorization_endpoint=None, - discovery_endpoint=None, - code_challenge=None, code_challenge_method=None, - **kwargs): + def __init__( + self, + auth_url, + identity_provider, + protocol, # nosec + client_id, + client_secret=None, + access_token_endpoint=None, + device_authorization_endpoint=None, + discovery_endpoint=None, + code_challenge=None, + code_challenge_method=None, + **kwargs, + ): """The OAuth 2.0 Device Authorization plugin expects the following. :param device_authorization_endpoint: OAuth 2.0 Device Authorization @@ -571,7 +631,7 @@ def __init__(self, auth_url, identity_provider, protocol, # nosec self.device_authorization_endpoint = device_authorization_endpoint self.code_challenge_method = code_challenge_method - super(OidcDeviceAuthorization, self).__init__( + super().__init__( auth_url=auth_url, identity_provider=identity_provider, protocol=protocol, @@ -580,7 +640,8 @@ def __init__(self, auth_url, identity_provider, protocol, # nosec access_token_endpoint=access_token_endpoint, discovery_endpoint=discovery_endpoint, access_token_type=self.access_token_type, - **kwargs) + **kwargs, + ) def _get_device_authorization_endpoint(self, session): """Get the endpoint for the OAuth 2.0 Device Authorization flow. @@ -639,8 +700,9 @@ def get_payload(self, session): :returns: a python dictionary containing the payload to be exchanged :rtype: dict """ - device_authz_endpoint = \ - self._get_device_authorization_endpoint(session) + device_authz_endpoint = self._get_device_authorization_endpoint( + session + ) if self.client_secret: client_auth = (self.client_id, self.client_secret) @@ -651,8 +713,9 @@ def get_payload(self, session): if self.code_challenge_method: self.code_challenge = self._generate_pkce_challenge() - payload.setdefault('code_challenge_method', - self.code_challenge_method) + payload.setdefault( + 'code_challenge_method', self.code_challenge_method + ) payload.setdefault('code_challenge', self.code_challenge) encoded_payload = urlparse.urlencode(payload) @@ -660,19 +723,24 @@ def get_payload(self, session): sanitized_payload = self._sanitize(payload) _logger.debug( "Making OpenID-Connect authentication request to %s with " - "data %s", device_authz_endpoint, sanitized_payload + "data %s", + device_authz_endpoint, + sanitized_payload, ) - op_response = session.post(device_authz_endpoint, - requests_auth=client_auth, - headers=self.HEADER_X_FORM, - data=encoded_payload, - log=False, - authenticated=False) + op_response = session.post( + device_authz_endpoint, + requests_auth=client_auth, + headers=self.HEADER_X_FORM, + data=encoded_payload, + log=False, + authenticated=False, + ) if _logger.isEnabledFor(logging.DEBUG): sanitized_response = self._sanitize(op_response.json()) _logger.debug( "OpenID-Connect authentication response from %s is %s", - device_authz_endpoint, sanitized_response + device_authz_endpoint, + sanitized_response, ) self.expires_in = int(op_response.json()["expires_in"]) @@ -681,8 +749,9 @@ def get_payload(self, session): self.interval = int(op_response.json()["interval"]) self.user_code = op_response.json()["user_code"] self.verification_uri = op_response.json()["verification_uri"] - self.verification_uri_complete = \ - op_response.json()["verification_uri_complete"] + self.verification_uri_complete = op_response.json()[ + "verification_uri_complete" + ] payload = {'device_code': self.device_code} if self.code_challenge_method: @@ -701,8 +770,10 @@ def _get_access_token(self, session, payload): 'device_code': self.device_code} :type payload: dict """ - _logger.warning(f"To authenticate please go to: " - f"{self.verification_uri_complete}") + _logger.warning( + f"To authenticate please go to: " + f"{self.verification_uri_complete}" + ) if self.client_secret: client_auth = (self.client_id, self.client_secret) @@ -720,19 +791,23 @@ def _get_access_token(self, session, payload): _logger.debug( "Making OpenID-Connect authentication request to %s " "with data %s", - access_token_endpoint, sanitized_payload + access_token_endpoint, + sanitized_payload, ) - op_response = session.post(access_token_endpoint, - requests_auth=client_auth, - data=encoded_payload, - headers=self.HEADER_X_FORM, - log=False, - authenticated=False) + op_response = session.post( + access_token_endpoint, + requests_auth=client_auth, + data=encoded_payload, + headers=self.HEADER_X_FORM, + log=False, + authenticated=False, + ) if _logger.isEnabledFor(logging.DEBUG): sanitized_response = self._sanitize(op_response.json()) _logger.debug( "OpenID-Connect authentication response from %s is %s", - access_token_endpoint, sanitized_response + access_token_endpoint, + sanitized_response, ) except exceptions.http.BadRequest as exc: error = exc.response.json().get("error") diff --git a/keystoneauth1/identity/v3/password.py b/keystoneauth1/identity/v3/password.py index c83f629a..c11fd705 100644 --- a/keystoneauth1/identity/v3/password.py +++ b/keystoneauth1/identity/v3/password.py @@ -26,11 +26,13 @@ class PasswordMethod(base.AuthMethod): :param string user_domain_name: User's domain name for authentication. """ - _method_parameters = ['user_id', - 'username', - 'user_domain_id', - 'user_domain_name', - 'password'] + _method_parameters = [ + 'user_id', + 'username', + 'user_domain_id', + 'user_domain_name', + 'password', + ] def get_auth_data(self, session, auth, headers, **kwargs): user = {'password': self.password} @@ -48,8 +50,9 @@ def get_auth_data(self, session, auth, headers, **kwargs): return 'password', {'user': user} def get_cache_id_elements(self): - return dict(('password_%s' % p, getattr(self, p)) - for p in self._method_parameters) + return { + f'password_{p}': getattr(self, p) for p in self._method_parameters + } class Password(base.AuthConstructor): diff --git a/keystoneauth1/identity/v3/receipt.py b/keystoneauth1/identity/v3/receipt.py index 4ddc8b6e..dfec4b0d 100644 --- a/keystoneauth1/identity/v3/receipt.py +++ b/keystoneauth1/identity/v3/receipt.py @@ -13,7 +13,7 @@ from keystoneauth1.identity.v3 import base -__all__ = ('ReceiptMethod', ) +__all__ = ('ReceiptMethod',) class ReceiptMethod(base.AuthMethod): diff --git a/keystoneauth1/identity/v3/token.py b/keystoneauth1/identity/v3/token.py index c959d116..b4f33ad7 100644 --- a/keystoneauth1/identity/v3/token.py +++ b/keystoneauth1/identity/v3/token.py @@ -51,4 +51,4 @@ class Token(base.AuthConstructor): _auth_method_class = TokenMethod def __init__(self, auth_url, token, **kwargs): - super(Token, self).__init__(auth_url, token=token, **kwargs) + super().__init__(auth_url, token=token, **kwargs) diff --git a/keystoneauth1/identity/v3/tokenless_auth.py b/keystoneauth1/identity/v3/tokenless_auth.py index a31984cb..9c3faad8 100644 --- a/keystoneauth1/identity/v3/tokenless_auth.py +++ b/keystoneauth1/identity/v3/tokenless_auth.py @@ -27,13 +27,16 @@ class TokenlessAuth(plugin.BaseAuthPlugin, metaclass=abc.ABCMeta): the provided HTTPS certificate along with the scope information. """ - def __init__(self, auth_url, - domain_id=None, - domain_name=None, - project_id=None, - project_name=None, - project_domain_id=None, - project_domain_name=None): + def __init__( + self, + auth_url, + domain_id=None, + domain_name=None, + project_id=None, + project_name=None, + project_domain_id=None, + project_domain_name=None, + ): """A init method for TokenlessAuth. :param string auth_url: Identity service endpoint for authentication. @@ -75,23 +78,23 @@ def get_headers(self, session, **kwargs): elif self.project_name: scope_headers['X-Project-Name'] = self.project_name if self.project_domain_id: - scope_headers['X-Project-Domain-Id'] = ( - self.project_domain_id) + scope_headers['X-Project-Domain-Id'] = self.project_domain_id elif self.project_domain_name: scope_headers['X-Project-Domain-Name'] = ( - self.project_domain_name) + self.project_domain_name + ) else: LOG.warning( 'Neither Project Domain ID nor Project Domain Name was ' - 'provided.') + 'provided.' + ) return None elif self.domain_id: scope_headers['X-Domain-Id'] = self.domain_id elif self.domain_name: scope_headers['X-Domain-Name'] = self.domain_name else: - LOG.warning( - 'Neither Project nor Domain scope was provided.') + LOG.warning('Neither Project nor Domain scope was provided.') return None return scope_headers @@ -106,8 +109,10 @@ def get_endpoint(self, session, service_type=None, **kwargs): :return: A valid endpoint URL or None if not available. :rtype: string or None """ - if (service_type is plugin.AUTH_INTERFACE or - service_type.lower() == 'identity'): + if ( + service_type is plugin.AUTH_INTERFACE + or service_type.lower() == 'identity' + ): return self.auth_url return None diff --git a/keystoneauth1/identity/v3/totp.py b/keystoneauth1/identity/v3/totp.py index ac0a7540..55291c53 100644 --- a/keystoneauth1/identity/v3/totp.py +++ b/keystoneauth1/identity/v3/totp.py @@ -28,11 +28,13 @@ class TOTPMethod(base.AuthMethod): :param string user_domain_name: User's domain name for authentication. """ - _method_parameters = ['user_id', - 'username', - 'user_domain_id', - 'user_domain_name', - 'passcode'] + _method_parameters = [ + 'user_id', + 'username', + 'user_domain_id', + 'user_domain_name', + 'passcode', + ] def get_auth_data(self, session, auth, headers, **kwargs): user = {'passcode': self.passcode} @@ -54,8 +56,7 @@ def get_cache_id_elements(self): # the key in caching. params = copy.copy(self._method_parameters) params.remove('passcode') - return dict(('totp_%s' % p, getattr(self, p)) - for p in self._method_parameters) + return {f'totp_{p}': getattr(self, p) for p in self._method_parameters} class TOTP(base.AuthConstructor): diff --git a/keystoneauth1/loading/__init__.py b/keystoneauth1/loading/__init__.py index 371c18c0..609b8ed6 100644 --- a/keystoneauth1/loading/__init__.py +++ b/keystoneauth1/loading/__init__.py @@ -37,7 +37,8 @@ register_adapter_argparse_arguments = adapter.register_argparse_arguments register_service_adapter_argparse_arguments = ( - adapter.register_service_argparse_arguments) + adapter.register_service_argparse_arguments +) register_adapter_conf_options = adapter.register_conf_options load_adapter_from_conf_options = adapter.load_from_conf_options get_adapter_conf_options = adapter.get_conf_options @@ -50,38 +51,32 @@ 'get_available_plugin_loaders', 'get_plugin_loader', 'PLUGIN_NAMESPACE', - # loading.identity 'BaseIdentityLoader', 'BaseV2Loader', 'BaseV3Loader', 'BaseFederationLoader', 'BaseGenericLoader', - # auth cli 'register_auth_argparse_arguments', 'load_auth_from_argparse_arguments', - # auth conf 'get_auth_common_conf_options', 'get_auth_plugin_conf_options', 'register_auth_conf_options', 'load_auth_from_conf_options', - # session 'register_session_argparse_arguments', 'load_session_from_argparse_arguments', 'register_session_conf_options', 'load_session_from_conf_options', 'get_session_conf_options', - # adapter 'register_adapter_argparse_arguments', 'register_service_adapter_argparse_arguments', 'register_adapter_conf_options', 'load_adapter_from_conf_options', 'get_adapter_conf_options', - # loading.opts 'Opt', ) diff --git a/keystoneauth1/loading/_plugins/admin_token.py b/keystoneauth1/loading/_plugins/admin_token.py index 3aba63d3..87c4445d 100644 --- a/keystoneauth1/loading/_plugins/admin_token.py +++ b/keystoneauth1/loading/_plugins/admin_token.py @@ -32,15 +32,21 @@ def plugin_class(self): return token_endpoint.Token def get_options(self): - options = super(AdminToken, self).get_options() - - options.extend([ - loading.Opt('endpoint', - deprecated=[loading.Opt('url')], - help='The endpoint that will always be used'), - loading.Opt('token', - secret=True, - help='The token that will always be used'), - ]) + options = super().get_options() + + options.extend( + [ + loading.Opt( + 'endpoint', + deprecated=[loading.Opt('url')], + help='The endpoint that will always be used', + ), + loading.Opt( + 'token', + secret=True, + help='The token that will always be used', + ), + ] + ) return options diff --git a/keystoneauth1/loading/_plugins/http_basic.py b/keystoneauth1/loading/_plugins/http_basic.py index b38c686e..6448a8ea 100644 --- a/keystoneauth1/loading/_plugins/http_basic.py +++ b/keystoneauth1/loading/_plugins/http_basic.py @@ -31,18 +31,25 @@ def plugin_class(self): return http_basic.HTTPBasicAuth def get_options(self): - options = super(HTTPBasicAuth, self).get_options() - - options.extend([ - loading.Opt('username', - help='Username', - deprecated=[loading.Opt('user-name')]), - loading.Opt('password', - secret=True, - prompt='Password: ', - help="User's password"), - loading.Opt('endpoint', - help='The endpoint that will always be used'), - ]) + options = super().get_options() + + options.extend( + [ + loading.Opt( + 'username', + help='Username', + deprecated=[loading.Opt('user-name')], + ), + loading.Opt( + 'password', + secret=True, + prompt='Password: ', + help="User's password", + ), + loading.Opt( + 'endpoint', help='The endpoint that will always be used' + ), + ] + ) return options diff --git a/keystoneauth1/loading/_plugins/identity/generic.py b/keystoneauth1/loading/_plugins/identity/generic.py index b6c139c7..b0353733 100644 --- a/keystoneauth1/loading/_plugins/identity/generic.py +++ b/keystoneauth1/loading/_plugins/identity/generic.py @@ -33,12 +33,15 @@ def plugin_class(self): return identity.Token def get_options(self): - options = super(Token, self).get_options() + options = super().get_options() - options.extend([ - loading.Opt('token', secret=True, - help='Token to authenticate with'), - ]) + options.extend( + [ + loading.Opt( + 'token', secret=True, help='Token to authenticate with' + ) + ] + ) return options @@ -59,17 +62,23 @@ def plugin_class(self): return identity.Password def get_options(cls): - options = super(Password, cls).get_options() - options.extend([ - loading.Opt('user-id', help='User id'), - loading.Opt('username', - help='Username', - deprecated=[loading.Opt('user-name')]), - loading.Opt('user-domain-id', help="User's domain id"), - loading.Opt('user-domain-name', help="User's domain name"), - loading.Opt('password', - secret=True, - prompt='Password: ', - help="User's password"), - ]) + options = super().get_options() + options.extend( + [ + loading.Opt('user-id', help='User id'), + loading.Opt( + 'username', + help='Username', + deprecated=[loading.Opt('user-name')], + ), + loading.Opt('user-domain-id', help="User's domain id"), + loading.Opt('user-domain-name', help="User's domain name"), + loading.Opt( + 'password', + secret=True, + prompt='Password: ', + help="User's password", + ), + ] + ) return options diff --git a/keystoneauth1/loading/_plugins/identity/v2.py b/keystoneauth1/loading/_plugins/identity/v2.py index aaacd153..42d66ed2 100644 --- a/keystoneauth1/loading/_plugins/identity/v2.py +++ b/keystoneauth1/loading/_plugins/identity/v2.py @@ -15,39 +15,41 @@ class Token(loading.BaseV2Loader): - @property def plugin_class(self): return identity.V2Token def get_options(self): - options = super(Token, self).get_options() + options = super().get_options() - options.extend([ - loading.Opt('token', secret=True, help='Token'), - ]) + options.extend([loading.Opt('token', secret=True, help='Token')]) return options class Password(loading.BaseV2Loader): - @property def plugin_class(self): return identity.V2Password def get_options(self): - options = super(Password, self).get_options() - - options.extend([ - loading.Opt('username', - deprecated=[loading.Opt('user-name')], - help='Username to login with'), - loading.Opt('user-id', help='User ID to login with'), - loading.Opt('password', - secret=True, - prompt='Password: ', - help='Password to use'), - ]) + options = super().get_options() + + options.extend( + [ + loading.Opt( + 'username', + deprecated=[loading.Opt('user-name')], + help='Username to login with', + ), + loading.Opt('user-id', help='User ID to login with'), + loading.Opt( + 'password', + secret=True, + prompt='Password: ', + help='Password to use', + ), + ] + ) return options diff --git a/keystoneauth1/loading/_plugins/identity/v3.py b/keystoneauth1/loading/_plugins/identity/v3.py index 4c24a0a0..1b3132d1 100644 --- a/keystoneauth1/loading/_plugins/identity/v3.py +++ b/keystoneauth1/loading/_plugins/identity/v3.py @@ -16,334 +16,409 @@ def _add_common_identity_options(options): - options.extend([ - loading.Opt('user-id', help='User ID'), - loading.Opt('username', - help='Username', - deprecated=[loading.Opt('user-name')]), - loading.Opt('user-domain-id', help="User's domain id"), - loading.Opt('user-domain-name', help="User's domain name"), - ]) + options.extend( + [ + loading.Opt('user-id', help='User ID'), + loading.Opt( + 'username', + help='Username', + deprecated=[loading.Opt('user-name')], + ), + loading.Opt('user-domain-id', help="User's domain id"), + loading.Opt('user-domain-name', help="User's domain name"), + ] + ) def _assert_identity_options(options): - if (options.get('username') and - not (options.get('user_domain_name') or - options.get('user_domain_id'))): - m = "You have provided a username. In the V3 identity API a " \ - "username is only unique within a domain so you must " \ + if options.get('username') and not ( + options.get('user_domain_name') or options.get('user_domain_id') + ): + m = ( + "You have provided a username. In the V3 identity API a " + "username is only unique within a domain so you must " "also provide either a user_domain_id or user_domain_name." + ) raise exceptions.OptionError(m) class Password(loading.BaseV3Loader): - @property def plugin_class(self): return identity.V3Password def get_options(self): - options = super(Password, self).get_options() + options = super().get_options() _add_common_identity_options(options) - options.extend([ - loading.Opt('password', - secret=True, - prompt='Password: ', - help="User's password"), - ]) + options.extend( + [ + loading.Opt( + 'password', + secret=True, + prompt='Password: ', + help="User's password", + ) + ] + ) return options def load_from_options(self, **kwargs): _assert_identity_options(kwargs) - return super(Password, self).load_from_options(**kwargs) + return super().load_from_options(**kwargs) class Token(loading.BaseV3Loader): - @property def plugin_class(self): return identity.V3Token def get_options(self): - options = super(Token, self).get_options() + options = super().get_options() - options.extend([ - loading.Opt('token', - secret=True, - help='Token to authenticate with'), - ]) + options.extend( + [ + loading.Opt( + 'token', secret=True, help='Token to authenticate with' + ) + ] + ) return options class _OpenIDConnectBase(loading.BaseFederationLoader): - def load_from_options(self, **kwargs): - if not (kwargs.get('access_token_endpoint') or - kwargs.get('discovery_endpoint')): - m = ("You have to specify either an 'access-token-endpoint' or " - "a 'discovery-endpoint'.") + if not ( + kwargs.get('access_token_endpoint') + or kwargs.get('discovery_endpoint') + ): + m = ( + "You have to specify either an 'access-token-endpoint' or " + "a 'discovery-endpoint'." + ) raise exceptions.OptionError(m) - return super(_OpenIDConnectBase, self).load_from_options(**kwargs) + return super().load_from_options(**kwargs) def get_options(self): - options = super(_OpenIDConnectBase, self).get_options() - - options.extend([ - loading.Opt('client-id', help='OAuth 2.0 Client ID'), - loading.Opt('client-secret', secret=True, - help='OAuth 2.0 Client Secret'), - loading.Opt('openid-scope', default="openid profile", - dest="scope", - help='OpenID Connect scope that is requested from ' - 'authorization server. Note that the OpenID ' - 'Connect specification states that "openid" ' - 'must be always specified.'), - loading.Opt('access-token-endpoint', - help='OpenID Connect Provider Token Endpoint. Note ' - 'that if a discovery document is being passed this ' - 'option will override the endpoint provided by the ' - 'server in the discovery document.'), - loading.Opt('discovery-endpoint', - help='OpenID Connect Discovery Document URL. ' - 'The discovery document will be used to obtain the ' - 'values of the access token endpoint and the ' - 'authentication endpoint. This URL should look like ' - 'https://idp.example.org/.well-known/' - 'openid-configuration'), - loading.Opt('access-token-type', - help='OAuth 2.0 Authorization Server Introspection ' - 'token type, it is used to decide which type ' - 'of token will be used when processing token ' - 'introspection. Valid values are: ' - '"access_token" or "id_token"'), - ]) + options = super().get_options() + + options.extend( + [ + loading.Opt('client-id', help='OAuth 2.0 Client ID'), + loading.Opt( + 'client-secret', + secret=True, + help='OAuth 2.0 Client Secret', + ), + loading.Opt( + 'openid-scope', + default="openid profile", + dest="scope", + help='OpenID Connect scope that is requested from ' + 'authorization server. Note that the OpenID ' + 'Connect specification states that "openid" ' + 'must be always specified.', + ), + loading.Opt( + 'access-token-endpoint', + help='OpenID Connect Provider Token Endpoint. Note ' + 'that if a discovery document is being passed this ' + 'option will override the endpoint provided by the ' + 'server in the discovery document.', + ), + loading.Opt( + 'discovery-endpoint', + help='OpenID Connect Discovery Document URL. ' + 'The discovery document will be used to obtain the ' + 'values of the access token endpoint and the ' + 'authentication endpoint. This URL should look like ' + 'https://idp.example.org/.well-known/' + 'openid-configuration', + ), + loading.Opt( + 'access-token-type', + help='OAuth 2.0 Authorization Server Introspection ' + 'token type, it is used to decide which type ' + 'of token will be used when processing token ' + 'introspection. Valid values are: ' + '"access_token" or "id_token"', + ), + ] + ) return options class OpenIDConnectClientCredentials(_OpenIDConnectBase): - @property def plugin_class(self): return identity.V3OidcClientCredentials def get_options(self): - options = super(OpenIDConnectClientCredentials, self).get_options() + options = super().get_options() return options class OpenIDConnectPassword(_OpenIDConnectBase): - @property def plugin_class(self): return identity.V3OidcPassword def get_options(self): - options = super(OpenIDConnectPassword, self).get_options() - - options.extend([ - loading.Opt('username', help='Username', required=True), - loading.Opt('password', secret=True, - help='Password', required=True), - loading.Opt('idp_otp_key', - help='A key to be used in the Identity Provider access' - ' token endpoint to pass the OTP value. ' - 'E.g. totp'), - ]) + options = super().get_options() + + options.extend( + [ + loading.Opt('username', help='Username', required=True), + loading.Opt( + 'password', secret=True, help='Password', required=True + ), + loading.Opt( + 'idp_otp_key', + help='A key to be used in the Identity Provider access' + ' token endpoint to pass the OTP value. ' + 'E.g. totp', + ), + ] + ) return options class OpenIDConnectAuthorizationCode(_OpenIDConnectBase): - @property def plugin_class(self): return identity.V3OidcAuthorizationCode def get_options(self): - options = super(OpenIDConnectAuthorizationCode, self).get_options() - - options.extend([ - loading.Opt('redirect-uri', help='OpenID Connect Redirect URL'), - loading.Opt('code', secret=True, required=True, - deprecated=[loading.Opt('authorization-code')], - help='OAuth 2.0 Authorization Code'), - ]) + options = super().get_options() + + options.extend( + [ + loading.Opt( + 'redirect-uri', help='OpenID Connect Redirect URL' + ), + loading.Opt( + 'code', + secret=True, + required=True, + deprecated=[loading.Opt('authorization-code')], + help='OAuth 2.0 Authorization Code', + ), + ] + ) return options class OpenIDConnectAccessToken(loading.BaseFederationLoader): - @property def plugin_class(self): return identity.V3OidcAccessToken def get_options(self): - options = super(OpenIDConnectAccessToken, self).get_options() - - options.extend([ - loading.Opt('access-token', secret=True, required=True, - help='OAuth 2.0 Access Token'), - ]) + options = super().get_options() + + options.extend( + [ + loading.Opt( + 'access-token', + secret=True, + required=True, + help='OAuth 2.0 Access Token', + ) + ] + ) return options class OpenIDConnectDeviceAuthorization(_OpenIDConnectBase): - @property def plugin_class(self): return identity.V3OidcDeviceAuthorization def get_options(self): - options = super(OpenIDConnectDeviceAuthorization, self).get_options() + options = super().get_options() # RFC 8628 doesn't support id_token options = [opt for opt in options if opt.name != 'access-token-type'] - options.extend([ - loading.Opt('device-authorization-endpoint', - help='OAuth 2.0 Device Authorization Endpoint. Note ' - 'that if a discovery document is being passed this ' - 'option will override the endpoint provided by the ' - 'server in the discovery document.'), - loading.Opt('code-challenge-method', - help='PKCE Challenge Method (RFC 7636)'), - ]) + options.extend( + [ + loading.Opt( + 'device-authorization-endpoint', + help='OAuth 2.0 Device Authorization Endpoint. Note ' + 'that if a discovery document is being passed this ' + 'option will override the endpoint provided by the ' + 'server in the discovery document.', + ), + loading.Opt( + 'code-challenge-method', + help='PKCE Challenge Method (RFC 7636)', + ), + ] + ) return options class TOTP(loading.BaseV3Loader): - @property def plugin_class(self): return identity.V3TOTP def get_options(self): - options = super(TOTP, self).get_options() + options = super().get_options() _add_common_identity_options(options) - options.extend([ - loading.Opt( - 'passcode', - secret=True, - prompt='TOTP passcode: ', - help="User's TOTP passcode"), - ]) + options.extend( + [ + loading.Opt( + 'passcode', + secret=True, + prompt='TOTP passcode: ', + help="User's TOTP passcode", + ) + ] + ) return options def load_from_options(self, **kwargs): _assert_identity_options(kwargs) - return super(TOTP, self).load_from_options(**kwargs) + return super().load_from_options(**kwargs) class TokenlessAuth(loading.BaseLoader): - @property def plugin_class(self): return identity.V3TokenlessAuth def get_options(self): - options = super(TokenlessAuth, self).get_options() - - options.extend([ - loading.Opt('auth-url', required=True, - help='Authentication URL'), - loading.Opt('domain-id', help='Domain ID to scope to'), - loading.Opt('domain-name', help='Domain name to scope to'), - loading.Opt('project-id', help='Project ID to scope to'), - loading.Opt('project-name', help='Project name to scope to'), - loading.Opt('project-domain-id', - help='Domain ID containing project'), - loading.Opt('project-domain-name', - help='Domain name containing project'), - ]) + options = super().get_options() + + options.extend( + [ + loading.Opt( + 'auth-url', required=True, help='Authentication URL' + ), + loading.Opt('domain-id', help='Domain ID to scope to'), + loading.Opt('domain-name', help='Domain name to scope to'), + loading.Opt('project-id', help='Project ID to scope to'), + loading.Opt('project-name', help='Project name to scope to'), + loading.Opt( + 'project-domain-id', help='Domain ID containing project' + ), + loading.Opt( + 'project-domain-name', + help='Domain name containing project', + ), + ] + ) return options def load_from_options(self, **kwargs): - if (not kwargs.get('domain_id') and - not kwargs.get('domain_name') and - not kwargs.get('project_id') and - not kwargs.get('project_name') or - (kwargs.get('project_name') and - not (kwargs.get('project_domain_name') or - kwargs.get('project_domain_id')))): - m = ('You need to provide either a domain_name, domain_id, ' - 'project_id or project_name. ' - 'If you have provided a project_name, in the V3 identity ' - 'API a project_name is only unique within a domain so ' - 'you must also provide either a project_domain_id or ' - 'project_domain_name.') + if ( + not kwargs.get('domain_id') + and not kwargs.get('domain_name') + and not kwargs.get('project_id') + and not kwargs.get('project_name') + or ( + kwargs.get('project_name') + and not ( + kwargs.get('project_domain_name') + or kwargs.get('project_domain_id') + ) + ) + ): + m = ( + 'You need to provide either a domain_name, domain_id, ' + 'project_id or project_name. ' + 'If you have provided a project_name, in the V3 identity ' + 'API a project_name is only unique within a domain so ' + 'you must also provide either a project_domain_id or ' + 'project_domain_name.' + ) raise exceptions.OptionError(m) - return super(TokenlessAuth, self).load_from_options(**kwargs) + return super().load_from_options(**kwargs) class ApplicationCredential(loading.BaseV3Loader): - @property def plugin_class(self): return identity.V3ApplicationCredential def get_options(self): - options = super(ApplicationCredential, self).get_options() + options = super().get_options() _add_common_identity_options(options) - options.extend([ - loading.Opt('application_credential_secret', secret=True, - required=True, - help="Application credential auth secret"), - loading.Opt('application_credential_id', - help='Application credential ID'), - loading.Opt('application_credential_name', - help='Application credential name'), - ]) + options.extend( + [ + loading.Opt( + 'application_credential_secret', + secret=True, + required=True, + help="Application credential auth secret", + ), + loading.Opt( + 'application_credential_id', + help='Application credential ID', + ), + loading.Opt( + 'application_credential_name', + help='Application credential name', + ), + ] + ) return options def load_from_options(self, **kwargs): _assert_identity_options(kwargs) - if (not kwargs.get('application_credential_id') and - not kwargs.get('application_credential_name')): - m = ('You must provide either an application credential ID or an ' - 'application credential name and user.') + if not kwargs.get('application_credential_id') and not kwargs.get( + 'application_credential_name' + ): + m = ( + 'You must provide either an application credential ID or an ' + 'application credential name and user.' + ) raise exceptions.OptionError(m) if not kwargs.get('application_credential_secret'): - m = ('You must provide an auth secret.') + m = 'You must provide an auth secret.' raise exceptions.OptionError(m) - return super(ApplicationCredential, self).load_from_options(**kwargs) + return super().load_from_options(**kwargs) class MultiFactor(loading.BaseV3Loader): - def __init__(self, *args, **kwargs): self._methods = None - return super(MultiFactor, self).__init__(*args, **kwargs) + return super().__init__(*args, **kwargs) @property def plugin_class(self): return identity.V3MultiFactor def get_options(self): - options = super(MultiFactor, self).get_options() - - options.extend([ - loading.Opt( - 'auth_methods', - required=True, - help="Methods to authenticate with."), - ]) + options = super().get_options() + + options.extend( + [ + loading.Opt( + 'auth_methods', + required=True, + help="Methods to authenticate with.", + ) + ] + ) if self._methods: options_dict = {o.name: o for o in options} @@ -362,29 +437,36 @@ def load_from_options(self, **kwargs): self._methods = kwargs['auth_methods'] - return super(MultiFactor, self).load_from_options(**kwargs) + return super().load_from_options(**kwargs) class OAuth2ClientCredential(loading.BaseV3Loader): - @property def plugin_class(self): return identity.V3OAuth2ClientCredential def get_options(self): - options = super(OAuth2ClientCredential, self).get_options() - options.extend([ - loading.Opt('oauth2_endpoint', - required=True, - help='Endpoint for OAuth2.0'), - loading.Opt('oauth2_client_id', - required=True, - help='Client id for OAuth2.0'), - loading.Opt('oauth2_client_secret', - secret=True, - required=True, - help='Client secret for OAuth2.0'), - ]) + options = super().get_options() + options.extend( + [ + loading.Opt( + 'oauth2_endpoint', + required=True, + help='Endpoint for OAuth2.0', + ), + loading.Opt( + 'oauth2_client_id', + required=True, + help='Client id for OAuth2.0', + ), + loading.Opt( + 'oauth2_client_secret', + secret=True, + required=True, + help='Client secret for OAuth2.0', + ), + ] + ) return options @@ -399,26 +481,31 @@ def load_from_options(self, **kwargs): m = 'You must provide an OAuth2.0 client credential auth secret.' raise exceptions.OptionError(m) - return super(OAuth2ClientCredential, self).load_from_options(**kwargs) + return super().load_from_options(**kwargs) class OAuth2mTlsClientCredential(loading.BaseV3Loader): - @property def plugin_class(self): return identity.V3OAuth2mTlsClientCredential def get_options(self): - options = super(OAuth2mTlsClientCredential, self).get_options() - options.extend([ - loading.Opt('oauth2-endpoint', - required=True, - help='Endpoint for OAuth2.0 Mutual-TLS Authorization'), - loading.Opt('oauth2-client-id', - required=True, - help='Client credential ID for OAuth2.0 Mutual-TLS ' - 'Authorization') - ]) + options = super().get_options() + options.extend( + [ + loading.Opt( + 'oauth2-endpoint', + required=True, + help='Endpoint for OAuth2.0 Mutual-TLS Authorization', + ), + loading.Opt( + 'oauth2-client-id', + required=True, + help='Client credential ID for OAuth2.0 Mutual-TLS ' + 'Authorization', + ), + ] + ) return options def load_from_options(self, **kwargs): @@ -426,8 +513,9 @@ def load_from_options(self, **kwargs): m = 'You must provide an OAuth2.0 Mutual-TLS endpoint.' raise exceptions.OptionError(m) if not kwargs.get('oauth2_client_id'): - m = ('You must provide an client credential ID for ' - 'OAuth2.0 Mutual-TLS Authorization.') + m = ( + 'You must provide an client credential ID for ' + 'OAuth2.0 Mutual-TLS Authorization.' + ) raise exceptions.OptionError(m) - return super(OAuth2mTlsClientCredential, - self).load_from_options(**kwargs) + return super().load_from_options(**kwargs) diff --git a/keystoneauth1/loading/_plugins/noauth.py b/keystoneauth1/loading/_plugins/noauth.py index 29a83a26..bfe884da 100644 --- a/keystoneauth1/loading/_plugins/noauth.py +++ b/keystoneauth1/loading/_plugins/noauth.py @@ -31,11 +31,14 @@ def plugin_class(self): return noauth.NoAuth def get_options(self): - options = super(NoAuth, self).get_options() - - options.extend([ - loading.Opt('endpoint', - help='The endpoint that will always be used'), - ]) + options = super().get_options() + + options.extend( + [ + loading.Opt( + 'endpoint', help='The endpoint that will always be used' + ) + ] + ) return options diff --git a/keystoneauth1/loading/_utils.py b/keystoneauth1/loading/_utils.py index 2cb796cf..88e93bac 100644 --- a/keystoneauth1/loading/_utils.py +++ b/keystoneauth1/loading/_utils.py @@ -32,9 +32,11 @@ def get_oslo_config(): cfg = _NOT_FOUND if cfg is _NOT_FOUND: - raise ImportError("oslo.config is not an automatic dependency of " - "keystoneauth. If you wish to use oslo.config " - "you need to import it into your application's " - "requirements file. ") + raise ImportError( + "oslo.config is not an automatic dependency of " + "keystoneauth. If you wish to use oslo.config " + "you need to import it into your application's " + "requirements file. " + ) return cfg diff --git a/keystoneauth1/loading/adapter.py b/keystoneauth1/loading/adapter.py index c973b1ae..851d2d11 100644 --- a/keystoneauth1/loading/adapter.py +++ b/keystoneauth1/loading/adapter.py @@ -15,15 +15,16 @@ from keystoneauth1.loading import base -__all__ = ('register_argparse_arguments', - 'register_service_argparse_arguments', - 'register_conf_options', - 'load_from_conf_options', - 'get_conf_options') +__all__ = ( + 'register_argparse_arguments', + 'register_service_argparse_arguments', + 'register_conf_options', + 'load_from_conf_options', + 'get_conf_options', +) class Adapter(base.BaseLoader): - @property def plugin_class(self): return adapter.Adapter @@ -76,7 +77,7 @@ def get_conf_options(include_deprecated=True, deprecated_opts=None): the new ``endpoint_override`` option name:: old_opt = oslo_cfg.DeprecatedOpt('api_endpoint', 'old_group') - deprecated_opts={'endpoint_override': [old_opt]} + deprecated_opts = {'endpoint_override': [old_opt]} :returns: A list of oslo_config options. """ @@ -86,106 +87,127 @@ def get_conf_options(include_deprecated=True, deprecated_opts=None): deprecated_opts = {} # This is goofy, but need to support hyphens *or* underscores - deprecated_opts = {name.replace('_', '-'): opt - for name, opt in deprecated_opts.items()} - - opts = [cfg.StrOpt('service-type', - deprecated_opts=deprecated_opts.get('service-type'), - help='The default service_type for endpoint URL ' - 'discovery.'), - cfg.StrOpt('service-name', - deprecated_opts=deprecated_opts.get('service-name'), - help='The default service_name for endpoint URL ' - 'discovery.'), - cfg.ListOpt('valid-interfaces', - deprecated_opts=deprecated_opts.get( - 'valid-interfaces'), - help='List of interfaces, in order of preference, ' - 'for endpoint URL.'), - cfg.StrOpt('region-name', - deprecated_opts=deprecated_opts.get('region-name'), - help='The default region_name for endpoint URL ' - 'discovery.'), - cfg.StrOpt('endpoint-override', - deprecated_opts=deprecated_opts.get( - 'endpoint-override'), - help='Always use this endpoint URL for requests ' - 'for this client. NOTE: The unversioned ' - 'endpoint should be specified here; to ' - 'request a particular API version, use the ' - '`version`, `min-version`, and/or ' - '`max-version` options.'), - cfg.StrOpt('version', - deprecated_opts=deprecated_opts.get('version'), - help='Minimum Major API version within a given ' - 'Major API version for endpoint URL ' - 'discovery. Mutually exclusive with ' - 'min_version and max_version'), - cfg.StrOpt('min-version', - deprecated_opts=deprecated_opts.get('min-version'), - help='The minimum major version of a given API, ' - 'intended to be used as the lower bound of a ' - 'range with max_version. Mutually exclusive ' - 'with version. If min_version is given with ' - 'no max_version it is as if max version is ' - '"latest".'), - cfg.StrOpt('max-version', - deprecated_opts=deprecated_opts.get('max-version'), - help='The maximum major version of a given API, ' - 'intended to be used as the upper bound of a ' - 'range with min_version. Mutually exclusive ' - 'with version.'), - cfg.IntOpt('connect-retries', - deprecated_opts=deprecated_opts.get( - 'connect-retries'), - help='The maximum number of retries that should be ' - 'attempted for connection errors.'), - cfg.FloatOpt('connect-retry-delay', - deprecated_opts=deprecated_opts.get( - 'connect-retry-delay'), - help='Delay (in seconds) between two retries ' - 'for connection errors. If not set, ' - 'exponential retry starting with 0.5 ' - 'seconds up to a maximum of 60 seconds ' - 'is used.'), - cfg.IntOpt('status-code-retries', - deprecated_opts=deprecated_opts.get( - 'status-code-retries'), - help='The maximum number of retries that should be ' - 'attempted for retriable HTTP status codes.'), - cfg.FloatOpt('status-code-retry-delay', - deprecated_opts=deprecated_opts.get( - 'status-code-retry-delay'), - help='Delay (in seconds) between two retries ' - 'for retriable status codes. If not set, ' - 'exponential retry starting with 0.5 ' - 'seconds up to a maximum of 60 seconds ' - 'is used.'), - cfg.ListOpt('retriable-status-codes', - deprecated_opts=deprecated_opts.get( - 'retriable-status-codes'), - item_type=cfg.types.Integer(), - help='List of retriable HTTP status codes that ' - 'should be retried. If not set default to ' - ' [503]' - ), - ] + deprecated_opts = { + name.replace('_', '-'): opt + for name, opt in deprecated_opts.items() + } + + opts = [ + cfg.StrOpt( + 'service-type', + deprecated_opts=deprecated_opts.get('service-type'), + help='The default service_type for endpoint URL discovery.', + ), + cfg.StrOpt( + 'service-name', + deprecated_opts=deprecated_opts.get('service-name'), + help='The default service_name for endpoint URL discovery.', + ), + cfg.ListOpt( + 'valid-interfaces', + deprecated_opts=deprecated_opts.get('valid-interfaces'), + help='List of interfaces, in order of preference, ' + 'for endpoint URL.', + ), + cfg.StrOpt( + 'region-name', + deprecated_opts=deprecated_opts.get('region-name'), + help='The default region_name for endpoint URL discovery.', + ), + cfg.StrOpt( + 'endpoint-override', + deprecated_opts=deprecated_opts.get('endpoint-override'), + help='Always use this endpoint URL for requests ' + 'for this client. NOTE: The unversioned ' + 'endpoint should be specified here; to ' + 'request a particular API version, use the ' + '`version`, `min-version`, and/or ' + '`max-version` options.', + ), + cfg.StrOpt( + 'version', + deprecated_opts=deprecated_opts.get('version'), + help='Minimum Major API version within a given ' + 'Major API version for endpoint URL ' + 'discovery. Mutually exclusive with ' + 'min_version and max_version', + ), + cfg.StrOpt( + 'min-version', + deprecated_opts=deprecated_opts.get('min-version'), + help='The minimum major version of a given API, ' + 'intended to be used as the lower bound of a ' + 'range with max_version. Mutually exclusive ' + 'with version. If min_version is given with ' + 'no max_version it is as if max version is ' + '"latest".', + ), + cfg.StrOpt( + 'max-version', + deprecated_opts=deprecated_opts.get('max-version'), + help='The maximum major version of a given API, ' + 'intended to be used as the upper bound of a ' + 'range with min_version. Mutually exclusive ' + 'with version.', + ), + cfg.IntOpt( + 'connect-retries', + deprecated_opts=deprecated_opts.get('connect-retries'), + help='The maximum number of retries that should be ' + 'attempted for connection errors.', + ), + cfg.FloatOpt( + 'connect-retry-delay', + deprecated_opts=deprecated_opts.get('connect-retry-delay'), + help='Delay (in seconds) between two retries ' + 'for connection errors. If not set, ' + 'exponential retry starting with 0.5 ' + 'seconds up to a maximum of 60 seconds ' + 'is used.', + ), + cfg.IntOpt( + 'status-code-retries', + deprecated_opts=deprecated_opts.get('status-code-retries'), + help='The maximum number of retries that should be ' + 'attempted for retriable HTTP status codes.', + ), + cfg.FloatOpt( + 'status-code-retry-delay', + deprecated_opts=deprecated_opts.get('status-code-retry-delay'), + help='Delay (in seconds) between two retries ' + 'for retriable status codes. If not set, ' + 'exponential retry starting with 0.5 ' + 'seconds up to a maximum of 60 seconds ' + 'is used.', + ), + cfg.ListOpt( + 'retriable-status-codes', + deprecated_opts=deprecated_opts.get('retriable-status-codes'), + item_type=cfg.types.Integer(), + help='List of retriable HTTP status codes that ' + 'should be retried. If not set default to ' + ' [503]', + ), + ] if include_deprecated: opts += [ - cfg.StrOpt('interface', - help='The default interface for endpoint URL ' - 'discovery.', - deprecated_for_removal=True, - deprecated_reason='Using valid-interfaces is' - ' preferrable because it is' - ' capable of accepting a list of' - ' possible interfaces.'), + cfg.StrOpt( + 'interface', + help='The default interface for endpoint URL ' + 'discovery.', + deprecated_for_removal=True, + deprecated_reason='Using valid-interfaces is' + ' preferrable because it is' + ' capable of accepting a list of' + ' possible interfaces.', + ) ] return opts - def register_conf_options(self, conf, group, include_deprecated=True, - deprecated_opts=None): + def register_conf_options( + self, conf, group, include_deprecated=True, deprecated_opts=None + ): """Register the oslo_config options that are needed for an Adapter. The options that are set are: @@ -231,12 +253,14 @@ def register_conf_options(self, conf, group, include_deprecated=True, the new ``endpoint_override`` option name:: old_opt = oslo_cfg.DeprecatedOpt('api_endpoint', 'old_group') - deprecated_opts={'endpoint_override': [old_opt]} + deprecated_opts = {'endpoint_override': [old_opt]} :returns: The list of options that was registered. """ - opts = self.get_conf_options(include_deprecated=include_deprecated, - deprecated_opts=deprecated_opts) + opts = self.get_conf_options( + include_deprecated=include_deprecated, + deprecated_opts=deprecated_opts, + ) conf.register_group(_utils.get_oslo_config().OptGroup(group)) conf.register_opts(opts, group=group) return opts @@ -270,16 +294,19 @@ def process_conf_options(confgrp, kwargs): :raise TypeError: If invalid conf option values or combinations are found. """ if confgrp.valid_interfaces and getattr(confgrp, 'interface', None): - raise TypeError("interface and valid_interfaces are mutually" - " exclusive. Please use valid_interfaces.") + raise TypeError( + "interface and valid_interfaces are mutually" + " exclusive. Please use valid_interfaces." + ) if confgrp.valid_interfaces: for iface in confgrp.valid_interfaces: if iface not in ('public', 'internal', 'admin'): # TODO(efried): s/valies/values/ - are we allowed to fix this? - raise TypeError("'{iface}' is not a valid value for" - " valid_interfaces. Valid valies are" - " public, internal or admin".format( - iface=iface)) + raise TypeError( + f"'{iface}' is not a valid value for" + " valid_interfaces. Valid valies are" + " public, internal or admin" + ) kwargs.setdefault('interface', confgrp.valid_interfaces) elif hasattr(confgrp, 'interface'): kwargs.setdefault('interface', confgrp.interface) @@ -290,16 +317,16 @@ def process_conf_options(confgrp, kwargs): kwargs.setdefault('version', confgrp.version) kwargs.setdefault('min_version', confgrp.min_version) kwargs.setdefault('max_version', confgrp.max_version) - if kwargs['version'] and ( - kwargs['max_version'] or kwargs['min_version']): + if kwargs['version'] and (kwargs['max_version'] or kwargs['min_version']): raise TypeError( - "version is mutually exclusive with min_version and" - " max_version") + "version is mutually exclusive with min_version and max_version" + ) kwargs.setdefault('connect_retries', confgrp.connect_retries) kwargs.setdefault('connect_retry_delay', confgrp.connect_retry_delay) kwargs.setdefault('status_code_retries', confgrp.status_code_retries) - kwargs.setdefault('status_code_retry_delay', - confgrp.status_code_retry_delay) + kwargs.setdefault( + 'status_code_retry_delay', confgrp.status_code_retry_delay + ) kwargs.setdefault('retriable_status_codes', confgrp.retriable_status_codes) diff --git a/keystoneauth1/loading/base.py b/keystoneauth1/loading/base.py index c40a9614..1a1774b0 100644 --- a/keystoneauth1/loading/base.py +++ b/keystoneauth1/loading/base.py @@ -19,12 +19,14 @@ PLUGIN_NAMESPACE = 'keystoneauth1.plugin' -__all__ = ('get_available_plugin_names', - 'get_available_plugin_loaders', - 'get_plugin_loader', - 'get_plugin_options', - 'BaseLoader', - 'PLUGIN_NAMESPACE') +__all__ = ( + 'get_available_plugin_names', + 'get_available_plugin_loaders', + 'get_plugin_loader', + 'get_plugin_options', + 'BaseLoader', + 'PLUGIN_NAMESPACE', +) def _auth_plugin_available(ext): @@ -41,10 +43,12 @@ def get_available_plugin_names(): :returns: A list of names. :rtype: frozenset """ - mgr = stevedore.EnabledExtensionManager(namespace=PLUGIN_NAMESPACE, - check_func=_auth_plugin_available, - invoke_on_load=True, - propagate_map_exceptions=True) + mgr = stevedore.EnabledExtensionManager( + namespace=PLUGIN_NAMESPACE, + check_func=_auth_plugin_available, + invoke_on_load=True, + propagate_map_exceptions=True, + ) return frozenset(mgr.names()) @@ -55,10 +59,12 @@ def get_available_plugin_loaders(): loader as the value. :rtype: dict """ - mgr = stevedore.EnabledExtensionManager(namespace=PLUGIN_NAMESPACE, - check_func=_auth_plugin_available, - invoke_on_load=True, - propagate_map_exceptions=True) + mgr = stevedore.EnabledExtensionManager( + namespace=PLUGIN_NAMESPACE, + check_func=_auth_plugin_available, + invoke_on_load=True, + propagate_map_exceptions=True, + ) return dict(mgr.map(lambda ext: (ext.entry_point.name, ext.obj))) @@ -75,9 +81,9 @@ def get_plugin_loader(name): if a plugin cannot be created. """ try: - mgr = stevedore.DriverManager(namespace=PLUGIN_NAMESPACE, - invoke_on_load=True, - name=name) + mgr = stevedore.DriverManager( + namespace=PLUGIN_NAMESPACE, invoke_on_load=True, name=name + ) except RuntimeError: raise exceptions.NoMatchingPlugin(name) @@ -99,7 +105,6 @@ def get_plugin_options(name): class BaseLoader(metaclass=abc.ABCMeta): - @property def plugin_class(self): raise NotImplementedError() @@ -153,8 +158,11 @@ def load_from_options(self, **kwargs): handle differences between the registered options and what is required to create the plugin. """ - missing_required = [o for o in self.get_options() - if o.required and kwargs.get(o.dest) is None] + missing_required = [ + o + for o in self.get_options() + if o.required and kwargs.get(o.dest) is None + ] if missing_required: raise exceptions.MissingRequiredOptions(missing_required) diff --git a/keystoneauth1/loading/cli.py b/keystoneauth1/loading/cli.py index 1804d099..7aa50387 100644 --- a/keystoneauth1/loading/cli.py +++ b/keystoneauth1/loading/cli.py @@ -16,17 +16,18 @@ from keystoneauth1.loading import base -__all__ = ('register_argparse_arguments', - 'load_from_argparse_arguments') +__all__ = ('register_argparse_arguments', 'load_from_argparse_arguments') def _register_plugin_argparse_arguments(parser, plugin): for opt in plugin.get_options(): - parser.add_argument(*opt.argparse_args, - default=opt.argparse_default, - metavar=opt.metavar, - help=opt.help, - dest='os_%s' % opt.dest) + parser.add_argument( + *opt.argparse_args, + default=opt.argparse_default, + metavar=opt.metavar, + help=opt.help, + dest=f'os_{opt.dest}', + ) def register_argparse_arguments(parser, argv, default=None): @@ -48,14 +49,17 @@ def register_argparse_arguments(parser, argv, default=None): if a plugin cannot be created. """ in_parser = argparse.ArgumentParser(add_help=False) - env_plugin = os.environ.get('OS_AUTH_TYPE', - os.environ.get('OS_AUTH_PLUGIN', default)) + env_plugin = os.environ.get( + 'OS_AUTH_TYPE', os.environ.get('OS_AUTH_PLUGIN', default) + ) for p in (in_parser, parser): - p.add_argument('--os-auth-type', - '--os-auth-plugin', - metavar='', - default=env_plugin, - help='Authentication type to use') + p.add_argument( + '--os-auth-type', + '--os-auth-plugin', + metavar='', + default=env_plugin, + help='Authentication type to use', + ) options, _args = in_parser.parse_known_args(argv) @@ -66,7 +70,7 @@ def register_argparse_arguments(parser, argv, default=None): msg = 'Default Authentication options' plugin = options.os_auth_type else: - msg = 'Options specific to the %s plugin.' % options.os_auth_type + msg = f'Options specific to the {options.os_auth_type} plugin.' plugin = base.get_plugin_loader(options.os_auth_type) group = parser.add_argument_group('Authentication Options', msg) @@ -97,6 +101,6 @@ def load_from_argparse_arguments(namespace, **kwargs): plugin = base.get_plugin_loader(namespace.os_auth_type) def _getter(opt): - return getattr(namespace, 'os_%s' % opt.dest) + return getattr(namespace, f'os_{opt.dest}') return plugin.load_from_options_getter(_getter, **kwargs) diff --git a/keystoneauth1/loading/conf.py b/keystoneauth1/loading/conf.py index a1502607..3ca00a25 100644 --- a/keystoneauth1/loading/conf.py +++ b/keystoneauth1/loading/conf.py @@ -13,18 +13,22 @@ from keystoneauth1.loading import base from keystoneauth1.loading import opts -_AUTH_TYPE_OPT = opts.Opt('auth_type', - deprecated=[opts.Opt('auth_plugin')], - help='Authentication type to load') +_AUTH_TYPE_OPT = opts.Opt( + 'auth_type', + deprecated=[opts.Opt('auth_plugin')], + help='Authentication type to load', +) _section_help = 'Config Section from which to load plugin specific options' _AUTH_SECTION_OPT = opts.Opt('auth_section', help=_section_help) -__all__ = ('get_common_conf_options', - 'get_plugin_conf_options', - 'register_conf_options', - 'load_from_conf_options') +__all__ = ( + 'get_common_conf_options', + 'get_plugin_conf_options', + 'register_conf_options', + 'load_from_conf_options', +) def get_common_conf_options(): diff --git a/keystoneauth1/loading/identity.py b/keystoneauth1/loading/identity.py index 446c7667..9274f39d 100644 --- a/keystoneauth1/loading/identity.py +++ b/keystoneauth1/loading/identity.py @@ -14,11 +14,13 @@ from keystoneauth1.loading import base from keystoneauth1.loading import opts -__all__ = ('BaseIdentityLoader', - 'BaseV2Loader', - 'BaseV3Loader', - 'BaseFederationLoader', - 'BaseGenericLoader') +__all__ = ( + 'BaseIdentityLoader', + 'BaseV2Loader', + 'BaseV3Loader', + 'BaseFederationLoader', + 'BaseGenericLoader', +) class BaseIdentityLoader(base.BaseLoader): @@ -31,13 +33,11 @@ class BaseIdentityLoader(base.BaseLoader): """ def get_options(self): - options = super(BaseIdentityLoader, self).get_options() + options = super().get_options() - options.extend([ - opts.Opt('auth-url', - required=True, - help='Authentication URL'), - ]) + options.extend( + [opts.Opt('auth-url', required=True, help='Authentication URL')] + ) return options @@ -51,14 +51,17 @@ class BaseV2Loader(BaseIdentityLoader): """ def get_options(self): - options = super(BaseV2Loader, self).get_options() - - options.extend([ - opts.Opt('tenant-id', help='Tenant ID'), - opts.Opt('tenant-name', help='Tenant Name'), - opts.Opt('trust-id', - help='ID of the trust to use as a trustee use'), - ]) + options = super().get_options() + + options.extend( + [ + opts.Opt('tenant-id', help='Tenant ID'), + opts.Opt('tenant-name', help='Tenant Name'), + opts.Opt( + 'trust-id', help='ID of the trust to use as a trustee use' + ), + ] + ) return options @@ -72,35 +75,44 @@ class BaseV3Loader(BaseIdentityLoader): """ def get_options(self): - options = super(BaseV3Loader, self).get_options() - - options.extend([ - opts.Opt('system-scope', help='Scope for system operations'), - opts.Opt('domain-id', help='Domain ID to scope to'), - opts.Opt('domain-name', help='Domain name to scope to'), - opts.Opt('project-id', help='Project ID to scope to'), - opts.Opt('project-name', help='Project name to scope to'), - opts.Opt('project-domain-id', - help='Domain ID containing project'), - opts.Opt('project-domain-name', - help='Domain name containing project'), - opts.Opt('trust-id', - help='ID of the trust to use as a trustee use'), - ]) + options = super().get_options() + + options.extend( + [ + opts.Opt('system-scope', help='Scope for system operations'), + opts.Opt('domain-id', help='Domain ID to scope to'), + opts.Opt('domain-name', help='Domain name to scope to'), + opts.Opt('project-id', help='Project ID to scope to'), + opts.Opt('project-name', help='Project name to scope to'), + opts.Opt( + 'project-domain-id', help='Domain ID containing project' + ), + opts.Opt( + 'project-domain-name', + help='Domain name containing project', + ), + opts.Opt( + 'trust-id', help='ID of the trust to use as a trustee use' + ), + ] + ) return options def load_from_options(self, **kwargs): - if (kwargs.get('project_name') and - not (kwargs.get('project_domain_name') or - kwargs.get('project_domain_id'))): - m = "You have provided a project_name. In the V3 identity API a " \ - "project_name is only unique within a domain so you must " \ - "also provide either a project_domain_id or " \ + if kwargs.get('project_name') and not ( + kwargs.get('project_domain_name') + or kwargs.get('project_domain_id') + ): + m = ( + "You have provided a project_name. In the V3 identity API a " + "project_name is only unique within a domain so you must " + "also provide either a project_domain_id or " "project_domain_name." + ) raise exceptions.OptionError(m) - return super(BaseV3Loader, self).load_from_options(**kwargs) + return super().load_from_options(**kwargs) class BaseFederationLoader(BaseV3Loader): @@ -112,16 +124,22 @@ class BaseFederationLoader(BaseV3Loader): """ def get_options(self): - options = super(BaseFederationLoader, self).get_options() - - options.extend([ - opts.Opt('identity-provider', - help="Identity Provider's name", - required=True), - opts.Opt('protocol', - help='Protocol for federated plugin', - required=True), - ]) + options = super().get_options() + + options.extend( + [ + opts.Opt( + 'identity-provider', + help="Identity Provider's name", + required=True, + ), + opts.Opt( + 'protocol', + help='Protocol for federated plugin', + required=True, + ), + ] + ) return options @@ -136,32 +154,48 @@ class BaseGenericLoader(BaseIdentityLoader): """ def get_options(self): - options = super(BaseGenericLoader, self).get_options() - - options.extend([ - opts.Opt('system-scope', help='Scope for system operations'), - opts.Opt('domain-id', help='Domain ID to scope to'), - opts.Opt('domain-name', help='Domain name to scope to'), - opts.Opt('project-id', help='Project ID to scope to', - deprecated=[opts.Opt('tenant-id')]), - opts.Opt('project-name', help='Project name to scope to', - deprecated=[opts.Opt('tenant-name')]), - opts.Opt('project-domain-id', - help='Domain ID containing project'), - opts.Opt('project-domain-name', - help='Domain name containing project'), - opts.Opt('trust-id', - help='ID of the trust to use as a trustee use'), - opts.Opt('default-domain-id', - help='Optional domain ID to use with v3 and v2 ' - 'parameters. It will be used for both the user ' - 'and project domain in v3 and ignored in ' - 'v2 authentication.'), - opts.Opt('default-domain-name', - help='Optional domain name to use with v3 API and v2 ' - 'parameters. It will be used for both the user ' - 'and project domain in v3 and ignored in ' - 'v2 authentication.'), - ]) + options = super().get_options() + + options.extend( + [ + opts.Opt('system-scope', help='Scope for system operations'), + opts.Opt('domain-id', help='Domain ID to scope to'), + opts.Opt('domain-name', help='Domain name to scope to'), + opts.Opt( + 'project-id', + help='Project ID to scope to', + deprecated=[opts.Opt('tenant-id')], + ), + opts.Opt( + 'project-name', + help='Project name to scope to', + deprecated=[opts.Opt('tenant-name')], + ), + opts.Opt( + 'project-domain-id', help='Domain ID containing project' + ), + opts.Opt( + 'project-domain-name', + help='Domain name containing project', + ), + opts.Opt( + 'trust-id', help='ID of the trust to use as a trustee use' + ), + opts.Opt( + 'default-domain-id', + help='Optional domain ID to use with v3 and v2 ' + 'parameters. It will be used for both the user ' + 'and project domain in v3 and ignored in ' + 'v2 authentication.', + ), + opts.Opt( + 'default-domain-name', + help='Optional domain name to use with v3 API and v2 ' + 'parameters. It will be used for both the user ' + 'and project domain in v3 and ignored in ' + 'v2 authentication.', + ), + ] + ) return options diff --git a/keystoneauth1/loading/opts.py b/keystoneauth1/loading/opts.py index b46a3ba9..dbae978b 100644 --- a/keystoneauth1/loading/opts.py +++ b/keystoneauth1/loading/opts.py @@ -19,7 +19,7 @@ __all__ = ('Opt',) -class Opt(object): +class Opt: """An option required by an authentication plugin. Opts provide a means for authentication plugins that are going to be @@ -60,17 +60,19 @@ class Opt(object): appropriate) set the string that should be used to prompt with. """ - def __init__(self, - name, - type=str, - help=None, - secret=False, - dest=None, - deprecated=None, - default=None, - metavar=None, - required=False, - prompt=None): + def __init__( + self, + name, + type=str, + help=None, + secret=False, + dest=None, + deprecated=None, + default=None, + metavar=None, + required=False, + prompt=None, + ): if not callable(type): raise TypeError('type must be callable') @@ -95,33 +97,37 @@ def __init__(self, def __repr__(self): """Return string representation of option name.""" - return '' % self.name + return f'' def _to_oslo_opt(self): cfg = _utils.get_oslo_config() deprecated_opts = [cfg.DeprecatedOpt(o.name) for o in self.deprecated] - return cfg.Opt(name=self.name, - type=self.type, - help=self.help, - secret=self.secret, - required=self.required, - dest=self.dest, - deprecated_opts=deprecated_opts, - metavar=self.metavar) + return cfg.Opt( + name=self.name, + type=self.type, + help=self.help, + secret=self.secret, + required=self.required, + dest=self.dest, + deprecated_opts=deprecated_opts, + metavar=self.metavar, + ) def __eq__(self, other): """Define equality operator on option parameters.""" - return (type(self) is type(other) and - self.name == other.name and - self.type == other.type and - self.help == other.help and - self.secret == other.secret and - self.required == other.required and - self.dest == other.dest and - self.deprecated == other.deprecated and - self.default == other.default and - self.metavar == other.metavar) + return ( + type(self) is type(other) + and self.name == other.name + and self.type == other.type + and self.help == other.help + and self.secret == other.secret + and self.required == other.required + and self.dest == other.dest + and self.deprecated == other.deprecated + and self.default == other.default + and self.metavar == other.metavar + ) # NOTE: This function is only needed by Python 2. If we get to point where # we don't support Python 2 anymore, this function should be removed. @@ -135,13 +141,15 @@ def _all_opts(self): @property def argparse_args(self): - return ['--os-%s' % o.name for o in self._all_opts] + return [f'--os-{o.name}' for o in self._all_opts] @property def argparse_default(self): # select the first ENV that is not false-y or return None for o in self._all_opts: - v = os.environ.get('OS_%s' % o.name.replace('-', '_').upper()) + v = os.environ.get( + 'OS_{}'.format(o.name.replace('-', '_').upper()) + ) if v: return v diff --git a/keystoneauth1/loading/session.py b/keystoneauth1/loading/session.py index 25a7b136..e4e37700 100644 --- a/keystoneauth1/loading/session.py +++ b/keystoneauth1/loading/session.py @@ -18,11 +18,13 @@ from keystoneauth1 import session -__all__ = ('register_argparse_arguments', - 'load_from_argparse_arguments', - 'register_conf_options', - 'load_from_conf_options', - 'get_conf_options') +__all__ = ( + 'register_argparse_arguments', + 'load_from_argparse_arguments', + 'register_conf_options', + 'load_from_conf_options', + 'get_conf_options', +) def _positive_non_zero_float(argument_value): @@ -31,16 +33,15 @@ def _positive_non_zero_float(argument_value): try: value = float(argument_value) except ValueError: - msg = "%s must be a float" % argument_value + msg = f"{argument_value} must be a float" raise argparse.ArgumentTypeError(msg) if value <= 0: - msg = "%s must be greater than 0" % argument_value + msg = f"{argument_value} must be greater than 0" raise argparse.ArgumentTypeError(msg) return value class Session(base.BaseLoader): - @property def plugin_class(self): return session.Session @@ -48,13 +49,15 @@ def plugin_class(self): def get_options(self): return [] - def load_from_options(self, - insecure=False, - verify=None, - cacert=None, - cert=None, - key=None, - **kwargs): + def load_from_options( + self, + insecure=False, + verify=None, + cacert=None, + cert=None, + key=None, + **kwargs, + ): """Create a session with individual certificate parameters. Some parameters used to create a session don't lend themselves to be @@ -72,14 +75,13 @@ def load_from_options(self, # requests lib form of having the cert and key as a tuple cert = (cert, key) - return super(Session, self).load_from_options(verify=verify, - cert=cert, - **kwargs) + return super().load_from_options(verify=verify, cert=cert, **kwargs) def register_argparse_arguments(self, parser): session_group = parser.add_argument_group( 'API Connection Options', - 'Options controlling the HTTP API Connections') + 'Options controlling the HTTP API Connections', + ) session_group.add_argument( '--insecure', @@ -89,7 +91,8 @@ def register_argparse_arguments(self, parser): '"insecure" TLS (https) requests. The ' 'server\'s certificate will not be verified ' 'against any certificate authorities. This ' - 'option should be used with caution.') + 'option should be used with caution.', + ) session_group.add_argument( '--os-cacert', @@ -97,36 +100,41 @@ def register_argparse_arguments(self, parser): default=os.environ.get('OS_CACERT'), help='Specify a CA bundle file to use in ' 'verifying a TLS (https) server certificate. ' - 'Defaults to env[OS_CACERT].') + 'Defaults to env[OS_CACERT].', + ) session_group.add_argument( '--os-cert', metavar='', default=os.environ.get('OS_CERT'), help='The location for the keystore (PEM formatted) ' - 'containing the public key of this client. ' - 'Defaults to env[OS_CERT].') + 'containing the public key of this client. ' + 'Defaults to env[OS_CERT].', + ) session_group.add_argument( '--os-key', metavar='', default=os.environ.get('OS_KEY'), help='The location for the keystore (PEM formatted) ' - 'containing the private key of this client. ' - 'Defaults to env[OS_KEY].') + 'containing the private key of this client. ' + 'Defaults to env[OS_KEY].', + ) session_group.add_argument( '--timeout', default=600, type=_positive_non_zero_float, metavar='', - help='Set request timeout (in seconds).') + help='Set request timeout (in seconds).', + ) session_group.add_argument( '--collect-timing', default=False, action='store_true', - help='Collect per-API call timing information.') + help='Collect per-API call timing information.', + ) def load_from_argparse_arguments(self, namespace, **kwargs): kwargs.setdefault('insecure', namespace.insecure) @@ -162,7 +170,7 @@ def get_conf_options(self, deprecated_opts=None): ``cafile`` option name:: old_opt = oslo_cfg.DeprecatedOpt('ca_file', 'old_group') - deprecated_opts={'cafile': [old_opt]} + deprecated_opts = {'cafile': [old_opt]} :returns: A list of oslo_config options. """ @@ -171,34 +179,47 @@ def get_conf_options(self, deprecated_opts=None): if deprecated_opts is None: deprecated_opts = {} - return [cfg.StrOpt('cafile', - deprecated_opts=deprecated_opts.get('cafile'), - help='PEM encoded Certificate Authority to use ' - 'when verifying HTTPs connections.'), - cfg.StrOpt('certfile', - deprecated_opts=deprecated_opts.get('certfile'), - help='PEM encoded client certificate cert file'), - cfg.StrOpt('keyfile', - deprecated_opts=deprecated_opts.get('keyfile'), - help='PEM encoded client certificate key file'), - cfg.BoolOpt('insecure', - default=False, - deprecated_opts=deprecated_opts.get('insecure'), - help='Verify HTTPS connections.'), - cfg.IntOpt('timeout', - deprecated_opts=deprecated_opts.get('timeout'), - help='Timeout value for http requests'), - cfg.BoolOpt('collect-timing', - deprecated_opts=deprecated_opts.get( - 'collect-timing'), - default=False, - help='Collect per-API call timing information.'), - cfg.BoolOpt('split-loggers', - deprecated_opts=deprecated_opts.get( - 'split-loggers'), - default=False, - help='Log requests to multiple loggers.') - ] + return [ + cfg.StrOpt( + 'cafile', + deprecated_opts=deprecated_opts.get('cafile'), + help='PEM encoded Certificate Authority to use ' + 'when verifying HTTPs connections.', + ), + cfg.StrOpt( + 'certfile', + deprecated_opts=deprecated_opts.get('certfile'), + help='PEM encoded client certificate cert file', + ), + cfg.StrOpt( + 'keyfile', + deprecated_opts=deprecated_opts.get('keyfile'), + help='PEM encoded client certificate key file', + ), + cfg.BoolOpt( + 'insecure', + default=False, + deprecated_opts=deprecated_opts.get('insecure'), + help='Verify HTTPS connections.', + ), + cfg.IntOpt( + 'timeout', + deprecated_opts=deprecated_opts.get('timeout'), + help='Timeout value for http requests', + ), + cfg.BoolOpt( + 'collect-timing', + deprecated_opts=deprecated_opts.get('collect-timing'), + default=False, + help='Collect per-API call timing information.', + ), + cfg.BoolOpt( + 'split-loggers', + deprecated_opts=deprecated_opts.get('split-loggers'), + default=False, + help='Log requests to multiple loggers.', + ), + ] def register_conf_options(self, conf, group, deprecated_opts=None): """Register the oslo_config options that are needed for a session. @@ -223,7 +244,7 @@ def register_conf_options(self, conf, group, deprecated_opts=None): ``cafile`` option name:: old_opt = oslo_cfg.DeprecatedOpt('ca_file', 'old_group') - deprecated_opts={'cafile': [old_opt]} + deprecated_opts = {'cafile': [old_opt]} :returns: The list of options that was registered. """ diff --git a/keystoneauth1/plugin.py b/keystoneauth1/plugin.py index 440d65e2..a355af4e 100644 --- a/keystoneauth1/plugin.py +++ b/keystoneauth1/plugin.py @@ -20,7 +20,7 @@ IDENTITY_AUTH_HEADER_NAME = 'X-Auth-Token' -class BaseAuthPlugin(object): +class BaseAuthPlugin: """The basic structure of an authentication plugin. .. note:: @@ -110,10 +110,9 @@ def get_headers(self, session, **kwargs): return {IDENTITY_AUTH_HEADER_NAME: token} - def get_endpoint_data(self, session, - endpoint_override=None, - discover_versions=True, - **kwargs): + def get_endpoint_data( + self, session, endpoint_override=None, discover_versions=True, **kwargs + ): """Return a valid endpoint data for a the service. :param session: A session object that can be used for communication. @@ -140,8 +139,10 @@ def get_endpoint_data(self, session, return endpoint_data return endpoint_data.get_versioned_data( - session, cache=self._discovery_cache, - discover_versions=discover_versions) + session, + cache=self._discovery_cache, + discover_versions=discover_versions, + ) def get_api_major_version(self, session, endpoint_override=None, **kwargs): """Get the major API version from the endpoint. @@ -158,16 +159,22 @@ def get_api_major_version(self, session, endpoint_override=None, **kwargs): :rtype: `keystoneauth1.discover.EndpointData` or None """ endpoint_data = self.get_endpoint_data( - session, endpoint_override=endpoint_override, - discover_versions=False, **kwargs) + session, + endpoint_override=endpoint_override, + discover_versions=False, + **kwargs, + ) if endpoint_data is None: return if endpoint_data.api_version is None: # No version detected from the URL, trying full discovery. endpoint_data = self.get_endpoint_data( - session, endpoint_override=endpoint_override, - discover_versions=True, **kwargs) + session, + endpoint_override=endpoint_override, + discover_versions=True, + **kwargs, + ) if endpoint_data and endpoint_data.api_version: return endpoint_data.api_version @@ -195,7 +202,8 @@ def get_endpoint(self, session, **kwargs): :rtype: string """ endpoint_data = self.get_endpoint_data( - session, discover_versions=False, **kwargs) + session, discover_versions=False, **kwargs + ) if not endpoint_data: return None return endpoint_data.url @@ -340,7 +348,7 @@ class FixedEndpointPlugin(BaseAuthPlugin): """A base class for plugins that have one fixed endpoint.""" def __init__(self, endpoint=None): - super(FixedEndpointPlugin, self).__init__() + super().__init__() self.endpoint = endpoint def get_endpoint(self, session, **kwargs): @@ -352,10 +360,9 @@ def get_endpoint(self, session, **kwargs): """ return kwargs.get('endpoint_override') or self.endpoint - def get_endpoint_data(self, session, - endpoint_override=None, - discover_versions=True, - **kwargs): + def get_endpoint_data( + self, session, endpoint_override=None, discover_versions=True, **kwargs + ): """Return a valid endpoint data for a the service. :param session: A session object that can be used for communication. @@ -374,8 +381,9 @@ def get_endpoint_data(self, session, :return: Valid EndpointData or None if not available. :rtype: `keystoneauth1.discover.EndpointData` or None """ - return super(FixedEndpointPlugin, self).get_endpoint_data( + return super().get_endpoint_data( session, endpoint_override=endpoint_override or self.endpoint, discover_versions=discover_versions, - **kwargs) + **kwargs, + ) diff --git a/keystoneauth1/service_token.py b/keystoneauth1/service_token.py index 3cd7e605..fb79e2b3 100644 --- a/keystoneauth1/service_token.py +++ b/keystoneauth1/service_token.py @@ -18,9 +18,8 @@ class ServiceTokenAuthWrapper(plugin.BaseAuthPlugin): - def __init__(self, user_auth, service_auth): - super(ServiceTokenAuthWrapper, self).__init__() + super().__init__() self.user_auth = user_auth self.service_auth = service_auth diff --git a/keystoneauth1/session.py b/keystoneauth1/session.py index d79bb9e9..5944e3e7 100644 --- a/keystoneauth1/session.py +++ b/keystoneauth1/session.py @@ -40,14 +40,12 @@ except ImportError: osprofiler_web = None -DEFAULT_USER_AGENT = 'keystoneauth1/%s %s %s/%s' % ( - keystoneauth1.__version__, requests.utils.default_user_agent(), - platform.python_implementation(), platform.python_version()) +DEFAULT_USER_AGENT = f'keystoneauth1/{keystoneauth1.__version__} {requests.utils.default_user_agent()} {platform.python_implementation()}/{platform.python_version()}' # NOTE(jamielennox): Clients will likely want to print more than json. Please # propose a patch if you have a content type you think is reasonable to print # here and we'll add it to the list as required. -_LOG_CONTENT_TYPES = set(['application/json', 'text/plain']) +_LOG_CONTENT_TYPES = {'application/json', 'text/plain'} _MAX_RETRY_INTERVAL = 60.0 _EXPONENTIAL_DELAY_START = 0.5 @@ -101,7 +99,7 @@ def _sanitize_headers(headers): return str_dict -class NoOpSemaphore(object): +class NoOpSemaphore: """Empty context manager for use as a default semaphore.""" def __enter__(self): @@ -114,7 +112,6 @@ def __exit__(self, exc_type, exc_value, traceback): class _JSONEncoder(json.JSONEncoder): - def default(self, o): if isinstance(o, datetime.datetime): return o.isoformat() @@ -123,10 +120,10 @@ def default(self, o): if netaddr and isinstance(o, netaddr.IPAddress): return str(o) - return super(_JSONEncoder, self).default(o) + return super().default(o) -class _StringFormatter(object): +class _StringFormatter: """A String formatter that fetches values on demand.""" def __init__(self, session, auth): @@ -142,8 +139,10 @@ def __getitem__(self, item): raise AttributeError(item) if not value: - raise ValueError("This type of authentication does not provide a " - "%s that can be substituted" % item) + raise ValueError( + "This type of authentication does not provide a " + f"{item} that can be substituted" + ) return value @@ -159,8 +158,11 @@ def _determine_calling_package(): # because sys.modules can change during iteration, which results # in a RuntimeError # https://docs.python.org/3/library/sys.html#sys.modules - mod_lookup = dict((m.__file__, n) for n, m in sys.modules.copy().items() - if hasattr(m, '__file__')) + mod_lookup = { + m.__file__: n + for n, m in sys.modules.copy().items() + if hasattr(m, '__file__') + } # NOTE(shaleh): these are not useful because they hide the real # user of the code. debtcollector did not import keystoneauth but @@ -205,7 +207,7 @@ def _determine_user_agent(): # NOTE(shaleh): mod_wsgi is not any more useful than just # reporting "keystoneauth". Ignore it and perform the package name # heuristic. - ignored = ('mod_wsgi', ) + ignored = ('mod_wsgi',) try: name = sys.argv[0] @@ -222,7 +224,7 @@ def _determine_user_agent(): return name -class RequestTiming(object): +class RequestTiming: """Contains timing information for an HTTP interaction.""" #: HTTP method used for the call (GET, POST, etc) @@ -240,7 +242,7 @@ def __init__(self, method, url, elapsed): self.elapsed = elapsed -class _Retries(object): +class _Retries: __slots__ = ('_fixed_delay', '_current') def __init__(self, fixed_delay=None): @@ -263,7 +265,7 @@ def reset(self): next = __next__ -class Session(object): +class Session: """Maintains client communication state and common functionality. As much as possible the parameters to this class reflect and are passed @@ -341,14 +343,26 @@ class Session(object): _DEFAULT_REDIRECT_LIMIT = 30 - def __init__(self, auth=None, session=None, original_ip=None, verify=True, - cert=None, timeout=None, user_agent=None, - redirect=_DEFAULT_REDIRECT_LIMIT, additional_headers=None, - app_name=None, app_version=None, additional_user_agent=None, - discovery_cache=None, split_loggers=None, - collect_timing=False, rate_semaphore=None, - connect_retries=0): - + def __init__( + self, + auth=None, + session=None, + original_ip=None, + verify=True, + cert=None, + timeout=None, + user_agent=None, + redirect=_DEFAULT_REDIRECT_LIMIT, + additional_headers=None, + app_name=None, + app_version=None, + additional_user_agent=None, + discovery_cache=None, + split_loggers=None, + collect_timing=False, + rate_semaphore=None, + connect_retries=0, + ): self.auth = auth self.session = _construct_session(session) # NOTE(mwhahaha): keep a reference to the session object so we can @@ -383,7 +397,7 @@ def __init__(self, auth=None, session=None, original_ip=None, verify=True, self.timeout = float(timeout) if user_agent is not None: - self.user_agent = "%s %s" % (user_agent, DEFAULT_USER_AGENT) + self.user_agent = f"{user_agent} {DEFAULT_USER_AGENT}" self._json = _JSONEncoder() @@ -431,13 +445,17 @@ def _remove_service_catalog(self, body): @staticmethod def _process_header(header): """Redact the secure headers to be logged.""" - secure_headers = ('authorization', 'x-auth-token', - 'x-subject-token', 'x-service-token') + secure_headers = ( + 'authorization', + 'x-auth-token', + 'x-subject-token', + 'x-service-token', + ) if header[0].lower() in secure_headers: token_hasher = hashlib.sha256() token_hasher.update(header[1].encode('utf-8')) token_hash = token_hasher.hexdigest() - return (header[0], '{SHA256}%s' % token_hash) + return (header[0], f'{{SHA256}}{token_hash}') return header def _get_split_loggers(self, split_loggers): @@ -458,9 +476,17 @@ def _get_split_loggers(self, split_loggers): split_loggers = False return split_loggers - def _http_log_request(self, url, method=None, data=None, - json=None, headers=None, query_params=None, - logger=None, split_loggers=None): + def _http_log_request( + self, + url, + method=None, + data=None, + json=None, + headers=None, + query_params=None, + logger=None, + split_loggers=None, + ): string_parts = [] if self._get_split_loggers(split_loggers): @@ -484,7 +510,7 @@ def _http_log_request(self, url, method=None, data=None, if self.verify is False: string_parts.append('--insecure') elif isinstance(self.verify, str): - string_parts.append('--cacert "%s"' % self.verify) + string_parts.append(f'--cacert "{self.verify}"') if method: string_parts.extend(['-X', method]) @@ -495,15 +521,16 @@ def _http_log_request(self, url, method=None, data=None, url = url + '?' + urllib.parse.urlencode(query_params) # URLs with query strings need to be wrapped in quotes in order # for the CURL command to run properly. - string_parts.append('"%s"' % url) + string_parts.append(f'"{url}"') else: string_parts.append(url) if headers: # Sort headers so that testing can work consistently. for header in sorted(headers.items()): - string_parts.append('-H "%s: %s"' - % self._process_header(header)) + string_parts.append( + '-H "{}: {}"'.format(*self._process_header(header)) + ) if json: data = self._json.encode(json) if data: @@ -512,13 +539,20 @@ def _http_log_request(self, url, method=None, data=None, data = data.decode("ascii") except UnicodeDecodeError: data = "" - string_parts.append("-d '%s'" % data) + string_parts.append(f"-d '{data}'") logger.debug(' '.join(string_parts)) - def _http_log_response(self, response=None, json=None, - status_code=None, headers=None, text=None, - logger=None, split_loggers=True): + def _http_log_response( + self, + response=None, + json=None, + status_code=None, + headers=None, + text=None, + logger=None, + split_loggers=True, + ): string_parts = [] body_parts = [] if self._get_split_loggers(split_loggers): @@ -540,11 +574,13 @@ def _http_log_response(self, response=None, json=None, headers = response.headers if status_code: - string_parts.append('[%s]' % status_code) + string_parts.append(f'[{status_code}]') if headers: # Sort headers so that testing can work consistently. for header in sorted(headers.items()): - string_parts.append('%s: %s' % self._process_header(header)) + string_parts.append( + '{}: {}'.format(*self._process_header(header)) + ) logger.debug(' '.join(string_parts)) if not body_logger.isEnabledFor(logging.DEBUG): @@ -565,12 +601,15 @@ def _http_log_response(self, response=None, json=None, # [1] https://www.w3.org/Protocols/rfc1341/4_Content-Type.html for log_type in _LOG_CONTENT_TYPES: if content_type is not None and content_type.startswith( - log_type): + log_type + ): text = self._remove_service_catalog(response.text) break else: - text = ('Omitted, Content-Type is set to %s. Only ' - '%s responses have their bodies logged.') + text = ( + 'Omitted, Content-Type is set to %s. Only ' + '%s responses have their bodies logged.' + ) text = text % (content_type, ', '.join(_LOG_CONTENT_TYPES)) if json: text = self._json.encode(json) @@ -581,7 +620,8 @@ def _http_log_response(self, response=None, json=None, @staticmethod def _set_microversion_headers( - headers, microversion, service_type, endpoint_filter): + headers, microversion, service_type, endpoint_filter + ): # We're converting it to normalized version number for two reasons. # First, to validate it's a real version number. Second, so that in # the future we can pre-validate that it is within the range of @@ -592,27 +632,32 @@ def _set_microversion_headers( # with the microversion range we found in discovery. microversion = discover.normalize_version_number(microversion) # Can't specify a M.latest microversion - if (microversion[0] != discover.LATEST and - discover.LATEST in microversion[1:]): + if ( + microversion[0] != discover.LATEST + and discover.LATEST in microversion[1:] + ): raise TypeError( - "Specifying a '{major}.latest' microversion is not allowed.") + "Specifying a '{major}.latest' microversion is not allowed." + ) microversion = discover.version_to_string(microversion) if not service_type: if endpoint_filter and 'service_type' in endpoint_filter: service_type = endpoint_filter['service_type'] else: raise TypeError( - "microversion {microversion} was requested but no" + f"microversion {microversion} was requested but no" " service_type information is available. Either provide a" " service_type in endpoint_filter or pass" - " microversion_service_type as an argument.".format( - microversion=microversion)) + " microversion_service_type as an argument." + ) # TODO(mordred) cinder uses volume in its microversion header. This # logic should be handled in the future by os-service-types but for # now hard-code for cinder. - if (service_type.startswith('volume') or - service_type == 'block-storage'): + if ( + service_type.startswith('volume') + or service_type == 'block-storage' + ): service_type = 'volume' elif service_type.startswith('share'): # NOTE(gouthamr) manila doesn't honor the "OpenStack-API-Version" @@ -622,25 +667,44 @@ def _set_microversion_headers( # service catalog service_type = 'shared-file-system' - headers.setdefault('OpenStack-API-Version', - '{service_type} {microversion}'.format( - service_type=service_type, - microversion=microversion)) + headers.setdefault( + 'OpenStack-API-Version', f'{service_type} {microversion}' + ) header_names = _mv_legacy_headers_for_service(service_type) for h in header_names: headers.setdefault(h, microversion) - def request(self, url, method, json=None, original_ip=None, - user_agent=None, redirect=None, authenticated=None, - endpoint_filter=None, auth=None, requests_auth=None, - raise_exc=True, allow_reauth=True, log=True, - endpoint_override=None, connect_retries=None, logger=None, - allow=None, client_name=None, client_version=None, - microversion=None, microversion_service_type=None, - status_code_retries=0, retriable_status_codes=None, - rate_semaphore=None, global_request_id=None, - connect_retry_delay=None, status_code_retry_delay=None, - **kwargs): + def request( + self, + url, + method, + json=None, + original_ip=None, + user_agent=None, + redirect=None, + authenticated=None, + endpoint_filter=None, + auth=None, + requests_auth=None, + raise_exc=True, + allow_reauth=True, + log=True, + endpoint_override=None, + connect_retries=None, + logger=None, + allow=None, + client_name=None, + client_version=None, + microversion=None, + microversion_service_type=None, + status_code_retries=0, + retriable_status_codes=None, + rate_semaphore=None, + global_request_id=None, + connect_retry_delay=None, + status_code_retry_delay=None, + **kwargs, + ): """Send an HTTP request with the specified characteristics. Wrapper around `requests.Session.request` to handle tasks such as @@ -766,21 +830,26 @@ def request(self, url, method, json=None, original_ip=None, # case insensitive. if kwargs.get('headers'): kwargs['headers'] = requests.structures.CaseInsensitiveDict( - kwargs['headers']) + kwargs['headers'] + ) else: kwargs['headers'] = requests.structures.CaseInsensitiveDict() if connect_retries is None: connect_retries = self._connect_retries # HTTP 503 - Service Unavailable - retriable_status_codes = retriable_status_codes or \ - _RETRIABLE_STATUS_CODES + retriable_status_codes = ( + retriable_status_codes or _RETRIABLE_STATUS_CODES + ) rate_semaphore = rate_semaphore or self._rate_semaphore - headers = kwargs.setdefault('headers', dict()) + headers = kwargs.setdefault('headers', {}) if microversion: self._set_microversion_headers( - headers, microversion, microversion_service_type, - endpoint_filter) + headers, + microversion, + microversion_service_type, + endpoint_filter, + ) if authenticated is None: authenticated = bool(auth or self.auth) @@ -807,13 +876,14 @@ def request(self, url, method, json=None, original_ip=None, if endpoint_override: base_url = endpoint_override % _StringFormatter(self, auth) elif endpoint_filter: - base_url = self.get_endpoint(auth, allow=allow, - **endpoint_filter) + base_url = self.get_endpoint( + auth, allow=allow, **endpoint_filter + ) if not base_url: raise exceptions.EndpointNotFound() - url = '%s/%s' % (base_url.rstrip('/'), url.lstrip('/')) + url = '{}/{}'.format(base_url.rstrip('/'), url.lstrip('/')) if self.cert: kwargs.setdefault('cert', self.cert) @@ -835,17 +905,17 @@ def request(self, url, method, json=None, original_ip=None, agent = [] if self.app_name and self.app_version: - agent.append('%s/%s' % (self.app_name, self.app_version)) + agent.append(f'{self.app_name}/{self.app_version}') elif self.app_name: agent.append(self.app_name) if client_name and client_version: - agent.append('%s/%s' % (client_name, client_version)) + agent.append(f'{client_name}/{client_version}') elif client_name: agent.append(client_name) for additional in self.additional_user_agent: - agent.append('%s/%s' % additional) + agent.append('{}/{}'.format(*additional)) if not agent: # NOTE(jamielennox): determine_user_agent will return an empty @@ -861,8 +931,9 @@ def request(self, url, method, json=None, original_ip=None, user_agent = headers.setdefault('User-Agent', ' '.join(agent)) if self.original_ip: - headers.setdefault('Forwarded', - 'for=%s;by=%s' % (self.original_ip, user_agent)) + headers.setdefault( + 'Forwarded', f'for={self.original_ip};by={user_agent}' + ) if json is not None: headers.setdefault('Content-Type', 'application/json') @@ -890,14 +961,18 @@ def request(self, url, method, json=None, original_ip=None, # be logged properly, but those sent in the `params` parameter # (which the requests library handles) need to be explicitly # picked out so they can be included in the URL that gets loggged. - query_params = kwargs.get('params', dict()) + query_params = kwargs.get('params', {}) if log: - self._http_log_request(url, method=method, - data=kwargs.get('data'), - headers=headers, - query_params=query_params, - logger=logger, split_loggers=split_loggers) + self._http_log_request( + url, + method=method, + data=kwargs.get('data'), + headers=headers, + query_params=query_params, + logger=logger, + split_loggers=split_loggers, + ) # Force disable requests redirect handling. We will manage this below. kwargs['allow_redirects'] = False @@ -908,12 +983,21 @@ def request(self, url, method, json=None, original_ip=None, connect_retry_delays = _Retries(connect_retry_delay) status_code_retry_delays = _Retries(status_code_retry_delay) - send = functools.partial(self._send_request, - url, method, redirect, log, logger, - split_loggers, connect_retries, - status_code_retries, retriable_status_codes, - rate_semaphore, connect_retry_delays, - status_code_retry_delays) + send = functools.partial( + self._send_request, + url, + method, + redirect, + log, + logger, + split_loggers, + connect_retries, + status_code_retries, + retriable_status_codes, + rate_semaphore, + connect_retry_delays, + status_code_retry_delays, + ) try: connection_params = self.get_auth_connection_params(auth=auth) @@ -942,8 +1026,9 @@ def request(self, url, method, json=None, original_ip=None, # Nova uses 'x-compute-request-id' and other services like # Glance, Cinder etc are using 'x-openstack-request-id' to store # request-id in the header - request_id = (resp.headers.get('x-openstack-request-id') or - resp.headers.get('x-compute-request-id')) + request_id = resp.headers.get( + 'x-openstack-request-id' + ) or resp.headers.get('x-compute-request-id') if request_id: if self._get_split_loggers(split_loggers): id_logger = utils.get_logger(__name__ + '.request-id') @@ -953,21 +1038,25 @@ def request(self, url, method, json=None, original_ip=None, id_logger.debug( '%(method)s call to %(service_name)s for ' '%(url)s used request id ' - '%(response_request_id)s', { + '%(response_request_id)s', + { 'method': resp.request.method, 'service_name': service_name, 'url': resp.url, - 'response_request_id': request_id - }) + 'response_request_id': request_id, + }, + ) else: id_logger.debug( '%(method)s call to ' '%(url)s used request id ' - '%(response_request_id)s', { + '%(response_request_id)s', + { 'method': resp.request.method, 'url': resp.url, - 'response_request_id': request_id - }) + 'response_request_id': request_id, + }, + ) # handle getting a 401 Unauthorized response by invalidating the plugin # and then retrying the request. This is only tried once. @@ -980,30 +1069,46 @@ def request(self, url, method, json=None, original_ip=None, resp = send(**kwargs) if raise_exc and resp.status_code >= 400: - logger.debug('Request returned failure status: %s', - resp.status_code) + logger.debug( + 'Request returned failure status: %s', resp.status_code + ) raise exceptions.from_response(resp, method, url) if self._collect_timing: for h in resp.history: - self._api_times.append(RequestTiming( - method=h.request.method, - url=h.request.url, - elapsed=h.elapsed, - )) - self._api_times.append(RequestTiming( - method=resp.request.method, - url=resp.request.url, - elapsed=resp.elapsed, - )) + self._api_times.append( + RequestTiming( + method=h.request.method, + url=h.request.url, + elapsed=h.elapsed, + ) + ) + self._api_times.append( + RequestTiming( + method=resp.request.method, + url=resp.request.url, + elapsed=resp.elapsed, + ) + ) return resp - def _send_request(self, url, method, redirect, log, logger, split_loggers, - connect_retries, status_code_retries, - retriable_status_codes, rate_semaphore, - connect_retry_delays, status_code_retry_delays, - **kwargs): + def _send_request( + self, + url, + method, + redirect, + log, + logger, + split_loggers, + connect_retries, + status_code_retries, + retriable_status_codes, + rate_semaphore, + connect_retry_delays, + status_code_retry_delays, + **kwargs, + ): # NOTE(jamielennox): We handle redirection manually because the # requests lib follows some browser patterns where it will redirect # POSTs as GETs for certain statuses which is not want we want for an @@ -1020,11 +1125,10 @@ def _send_request(self, url, method, redirect, log, logger, split_loggers, with rate_semaphore: resp = self.session.request(method, url, **kwargs) except requests.exceptions.SSLError as e: - msg = 'SSL exception connecting to %(url)s: %(error)s' % { - 'url': url, 'error': e} + msg = f'SSL exception connecting to {url}: {e}' raise exceptions.SSLError(msg) except requests.exceptions.Timeout: - msg = 'Request to %s timed out' % url + msg = f'Request to {url} timed out' raise exceptions.ConnectTimeout(msg) except requests.exceptions.ConnectionError as e: # NOTE(sdague): urllib3/requests connection error is a @@ -1033,11 +1137,10 @@ def _send_request(self, url, method, redirect, log, logger, split_loggers, # level message is often really important in figuring # out the difference between network misconfigurations # and firewall blocking. - msg = 'Unable to establish connection to %s: %s' % (url, e) + msg = f'Unable to establish connection to {url}: {e}' raise exceptions.ConnectFailure(msg) except requests.exceptions.RequestException as e: - msg = 'Unexpected exception for %(url)s: %(error)s' % { - 'url': url, 'error': e} + msg = f'Unexpected exception for {url}: {e}' raise exceptions.UnknownConnectionError(msg, e) except exceptions.RetriableConnectionFailure as e: @@ -1045,26 +1148,33 @@ def _send_request(self, url, method, redirect, log, logger, split_loggers, raise delay = next(connect_retry_delays) - logger.warning('Failure: %(e)s. Retrying in %(delay).1fs.' - '%(retries)s retries left', - {'e': e, 'delay': delay, - 'retries': connect_retries}) + logger.warning( + 'Failure: %(e)s. Retrying in %(delay).1fs.' + '%(retries)s retries left', + {'e': e, 'delay': delay, 'retries': connect_retries}, + ) time.sleep(delay) return self._send_request( - url, method, redirect, log, logger, split_loggers, + url, + method, + redirect, + log, + logger, + split_loggers, status_code_retries=status_code_retries, retriable_status_codes=retriable_status_codes, rate_semaphore=rate_semaphore, connect_retries=connect_retries - 1, connect_retry_delays=connect_retry_delays, status_code_retry_delays=status_code_retry_delays, - **kwargs) + **kwargs, + ) if log: self._http_log_response( - response=resp, logger=logger, - split_loggers=split_loggers) + response=resp, logger=logger, split_loggers=split_loggers + ) if resp.status_code in self._REDIRECT_STATUSES: # be careful here in python True == 1 and False == 0 @@ -1080,8 +1190,11 @@ def _send_request(self, url, method, redirect, log, logger, split_loggers, try: location = resp.headers['location'] except KeyError: - logger.warning("Failed to redirect request to %s as new " - "location was not provided.", resp.url) + logger.warning( + "Failed to redirect request to %s as new " + "location was not provided.", + resp.url, + ) else: # NOTE(TheJulia): Location redirects generally should have # URI's to the destination. @@ -1090,50 +1203,69 @@ def _send_request(self, url, method, redirect, log, logger, split_loggers, kwargs['params'] = {} if 'x-openstack-request-id' in resp.headers: - kwargs['headers'].setdefault('x-openstack-request-id', - resp.headers[ - 'x-openstack-request-id']) + kwargs['headers'].setdefault( + 'x-openstack-request-id', + resp.headers['x-openstack-request-id'], + ) # NOTE(jamielennox): We don't keep increasing delays. # This request actually worked so we can reset the delay count. connect_retry_delays.reset() status_code_retry_delays.reset() new_resp = self._send_request( - location, method, redirect, log, logger, split_loggers, + location, + method, + redirect, + log, + logger, + split_loggers, rate_semaphore=rate_semaphore, connect_retries=connect_retries, status_code_retries=status_code_retries, retriable_status_codes=retriable_status_codes, connect_retry_delays=connect_retry_delays, status_code_retry_delays=status_code_retry_delays, - **kwargs) + **kwargs, + ) if not isinstance(new_resp.history, list): new_resp.history = list(new_resp.history) new_resp.history.insert(0, resp) resp = new_resp - elif (resp.status_code in retriable_status_codes and - status_code_retries > 0): - + elif ( + resp.status_code in retriable_status_codes + and status_code_retries > 0 + ): delay = next(status_code_retry_delays) - logger.warning('Retriable status code %(code)s. Retrying in ' - '%(delay).1fs. %(retries)s retries left', - {'code': resp.status_code, 'delay': delay, - 'retries': status_code_retries}) + logger.warning( + 'Retriable status code %(code)s. Retrying in ' + '%(delay).1fs. %(retries)s retries left', + { + 'code': resp.status_code, + 'delay': delay, + 'retries': status_code_retries, + }, + ) time.sleep(delay) # NOTE(jamielennox): We don't keep increasing connection delays. # This request actually worked so we can reset the delay count. connect_retry_delays.reset() return self._send_request( - url, method, redirect, log, logger, split_loggers, + url, + method, + redirect, + log, + logger, + split_loggers, connect_retries=connect_retries, status_code_retries=status_code_retries - 1, retriable_status_codes=retriable_status_codes, rate_semaphore=rate_semaphore, connect_retry_delays=connect_retry_delays, status_code_retry_delays=status_code_retry_delays, - **kwargs) + **kwargs, + ) return resp @@ -1288,9 +1420,14 @@ def get_api_major_version(self, auth=None, **kwargs): auth = self._auth_required(auth, 'determine endpoint URL') return auth.get_api_major_version(self, **kwargs) - def get_all_version_data(self, auth=None, interface='public', - region_name=None, service_type=None, - **kwargs): + def get_all_version_data( + self, + auth=None, + interface='public', + region_name=None, + service_type=None, + **kwargs, + ): """Get version data for all services in the catalog. :param auth: @@ -1318,7 +1455,8 @@ def get_all_version_data(self, auth=None, interface='public', interface=interface, region_name=region_name, service_type=service_type, - **kwargs) + **kwargs, + ) def get_auth_connection_params(self, auth=None, **kwargs): """Return auth connection params as provided by the auth plugin. @@ -1461,17 +1599,19 @@ def init_poolmanager(self, *args, **kwargs): ] # Windows subsystem for Linux does not support this feature - if (hasattr(socket, 'TCP_KEEPCNT') and - not utils.is_windows_linux_subsystem): + if ( + hasattr(socket, 'TCP_KEEPCNT') + and not utils.is_windows_linux_subsystem + ): socket_options += [ # Set the maximum number of keep-alive probes - (socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 4), + (socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 4) ] if hasattr(socket, 'TCP_KEEPINTVL'): socket_options += [ # Send keep-alive probes every 15 seconds - (socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 15), + (socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 15) ] # After waiting 60 seconds, and then sending a probe once every 15 @@ -1479,4 +1619,4 @@ def init_poolmanager(self, *args, **kwargs): # hands for no longer than 2 minutes before a ConnectionError is # raised. kwargs['socket_options'] = socket_options - super(TCPKeepAliveAdapter, self).init_poolmanager(*args, **kwargs) + super().init_poolmanager(*args, **kwargs) diff --git a/keystoneauth1/tests/unit/access/test_v2_access.py b/keystoneauth1/tests/unit/access/test_v2_access.py index aabef671..49fe0419 100644 --- a/keystoneauth1/tests/unit/access/test_v2_access.py +++ b/keystoneauth1/tests/unit/access/test_v2_access.py @@ -21,7 +21,6 @@ class AccessV2Test(utils.TestCase): - def test_building_unscoped_accessinfo(self): token = fixture.V2Token(expires='2012-10-03T16:58:01Z') @@ -115,12 +114,9 @@ def test_diablo_token(self): 'user': { 'id': 'user_id1', 'name': 'user_name1', - 'roles': [ - {'name': 'role1'}, - {'name': 'role2'}, - ], + 'roles': [{'name': 'role1'}, {'name': 'role2'}], }, - }, + } } auth_ref = access.create(body=diablo_token) @@ -148,12 +144,9 @@ def test_grizzly_token(self): 'name': 'user_name1', 'tenantId': 'tenant_id1', 'tenantName': 'tenant_name1', - 'roles': [ - {'name': 'role1'}, - {'name': 'role2'}, - ], + 'roles': [{'name': 'role1'}, {'name': 'role2'}], }, - }, + } } auth_ref = access.create(body=grizzly_token) @@ -179,11 +172,13 @@ def test_v2_roles(self): self.assertIsInstance(auth_ref, access.AccessInfoV2) self.assertEqual([role_id], auth_ref.role_ids) - self.assertEqual([role_id], - auth_ref._data['access']['metadata']['roles']) + self.assertEqual( + [role_id], auth_ref._data['access']['metadata']['roles'] + ) self.assertEqual([role_name], auth_ref.role_names) - self.assertEqual([{'name': role_name}], - auth_ref._data['access']['user']['roles']) + self.assertEqual( + [{'name': role_name}], auth_ref._data['access']['user']['roles'] + ) def test_trusts(self): user_id = uuid.uuid4().hex diff --git a/keystoneauth1/tests/unit/access/test_v2_service_catalog.py b/keystoneauth1/tests/unit/access/test_v2_service_catalog.py index f62764a6..149b926f 100644 --- a/keystoneauth1/tests/unit/access/test_v2_service_catalog.py +++ b/keystoneauth1/tests/unit/access/test_v2_service_catalog.py @@ -20,7 +20,7 @@ class ServiceCatalogTest(utils.TestCase): def setUp(self): - super(ServiceCatalogTest, self).setUp() + super().setUp() self.AUTH_RESPONSE_BODY = fixture.V2Token( token_id='ab48a9efdfedb23ty3494', @@ -29,18 +29,21 @@ def setUp(self): tenant_name='My Project', user_id='123', user_name='jqsmith', - audit_chain_id=uuid.uuid4().hex) + audit_chain_id=uuid.uuid4().hex, + ) self.AUTH_RESPONSE_BODY.add_role(id='234', name='compute:admin') - role = self.AUTH_RESPONSE_BODY.add_role(id='235', - name='object-store:admin') + role = self.AUTH_RESPONSE_BODY.add_role( + id='235', name='object-store:admin' + ) role['tenantId'] = '1' s = self.AUTH_RESPONSE_BODY.add_service('compute', 'Cloud Servers') endpoint = s.add_endpoint( public='https://compute.north.host/v1/1234', internal='https://compute.north.host/v1/1234', - region='North') + region='North', + ) endpoint['tenantId'] = '1' endpoint['versionId'] = '1.0' endpoint['versionInfo'] = 'https://compute.north.host/v1.0/' @@ -49,16 +52,19 @@ def setUp(self): endpoint = s.add_endpoint( public='https://compute.north.host/v1.1/3456', internal='https://compute.north.host/v1.1/3456', - region='North') + region='North', + ) endpoint['tenantId'] = '2' endpoint['versionId'] = '1.1' endpoint['versionInfo'] = 'https://compute.north.host/v1.1/' endpoint['versionList'] = 'https://compute.north.host/' s = self.AUTH_RESPONSE_BODY.add_service('object-store', 'Cloud Files') - endpoint = s.add_endpoint(public='https://swift.north.host/v1/blah', - internal='https://swift.north.host/v1/blah', - region='South') + endpoint = s.add_endpoint( + public='https://swift.north.host/v1/blah', + internal='https://swift.north.host/v1/blah', + region='South', + ) endpoint['tenantId'] = '11' endpoint['versionId'] = '1.0' endpoint['versionInfo'] = 'uri' @@ -67,48 +73,62 @@ def setUp(self): endpoint = s.add_endpoint( public='https://swift.north.host/v1.1/blah', internal='https://compute.north.host/v1.1/blah', - region='South') + region='South', + ) endpoint['tenantId'] = '2' endpoint['versionId'] = '1.1' endpoint['versionInfo'] = 'https://swift.north.host/v1.1/' endpoint['versionList'] = 'https://swift.north.host/' s = self.AUTH_RESPONSE_BODY.add_service('image', 'Image Servers') - s.add_endpoint(public='https://image.north.host/v1/', - internal='https://image-internal.north.host/v1/', - region='North') - s.add_endpoint(public='https://image.south.host/v1/', - internal='https://image-internal.south.host/v1/', - region='South') + s.add_endpoint( + public='https://image.north.host/v1/', + internal='https://image-internal.north.host/v1/', + region='North', + ) + s.add_endpoint( + public='https://image.south.host/v1/', + internal='https://image-internal.south.host/v1/', + region='South', + ) def test_building_a_service_catalog(self): auth_ref = access.create(body=self.AUTH_RESPONSE_BODY) sc = auth_ref.service_catalog - self.assertEqual(sc.url_for(service_type='compute'), - "https://compute.north.host/v1/1234") - self.assertRaises(exceptions.EndpointNotFound, - sc.url_for, - region_name="South", - service_type='compute') + self.assertEqual( + sc.url_for(service_type='compute'), + "https://compute.north.host/v1/1234", + ) + self.assertRaises( + exceptions.EndpointNotFound, + sc.url_for, + region_name="South", + service_type='compute', + ) def test_service_catalog_endpoints(self): auth_ref = access.create(body=self.AUTH_RESPONSE_BODY) sc = auth_ref.service_catalog - public_ep = sc.get_endpoints(service_type='compute', - interface='publicURL') + public_ep = sc.get_endpoints( + service_type='compute', interface='publicURL' + ) self.assertEqual(public_ep['compute'][1]['tenantId'], '2') self.assertEqual(public_ep['compute'][1]['versionId'], '1.1') - self.assertEqual(public_ep['compute'][1]['internalURL'], - "https://compute.north.host/v1.1/3456") + self.assertEqual( + public_ep['compute'][1]['internalURL'], + "https://compute.north.host/v1.1/3456", + ) def test_service_catalog_empty(self): self.AUTH_RESPONSE_BODY['access']['serviceCatalog'] = [] auth_ref = access.create(body=self.AUTH_RESPONSE_BODY) - self.assertRaises(exceptions.EmptyCatalog, - auth_ref.service_catalog.url_for, - service_type='image', - interface='internalURL') + self.assertRaises( + exceptions.EmptyCatalog, + auth_ref.service_catalog.url_for, + service_type='image', + interface='internalURL', + ) def test_service_catalog_get_endpoints_region_names(self): auth_ref = access.create(body=self.AUTH_RESPONSE_BODY) @@ -116,23 +136,27 @@ def test_service_catalog_get_endpoints_region_names(self): endpoints = sc.get_endpoints(service_type='image', region_name='North') self.assertEqual(len(endpoints), 1) - self.assertEqual(endpoints['image'][0]['publicURL'], - 'https://image.north.host/v1/') + self.assertEqual( + endpoints['image'][0]['publicURL'], 'https://image.north.host/v1/' + ) endpoints = sc.get_endpoints(service_type='image', region_name='South') self.assertEqual(len(endpoints), 1) - self.assertEqual(endpoints['image'][0]['publicURL'], - 'https://image.south.host/v1/') + self.assertEqual( + endpoints['image'][0]['publicURL'], 'https://image.south.host/v1/' + ) endpoints = sc.get_endpoints(service_type='compute') self.assertEqual(len(endpoints['compute']), 2) - endpoints = sc.get_endpoints(service_type='compute', - region_name='North') + endpoints = sc.get_endpoints( + service_type='compute', region_name='North' + ) self.assertEqual(len(endpoints['compute']), 2) - endpoints = sc.get_endpoints(service_type='compute', - region_name='West') + endpoints = sc.get_endpoints( + service_type='compute', region_name='West' + ) self.assertEqual(len(endpoints['compute']), 0) def test_service_catalog_url_for_region_names(self): @@ -145,8 +169,12 @@ def test_service_catalog_url_for_region_names(self): url = sc.url_for(service_type='image', region_name='South') self.assertEqual(url, 'https://image.south.host/v1/') - self.assertRaises(exceptions.EndpointNotFound, sc.url_for, - service_type='image', region_name='West') + self.assertRaises( + exceptions.EndpointNotFound, + sc.url_for, + service_type='image', + region_name='West', + ) def test_servcie_catalog_get_url_region_names(self): auth_ref = access.create(body=self.AUTH_RESPONSE_BODY) @@ -170,21 +198,33 @@ def test_service_catalog_service_name(self): auth_ref = access.create(body=self.AUTH_RESPONSE_BODY) sc = auth_ref.service_catalog - url = sc.url_for(service_name='Image Servers', interface='public', - service_type='image', region_name='North') + url = sc.url_for( + service_name='Image Servers', + interface='public', + service_type='image', + region_name='North', + ) self.assertEqual('https://image.north.host/v1/', url) - self.assertRaises(exceptions.EndpointNotFound, sc.url_for, - service_name='Image Servers', service_type='compute') + self.assertRaises( + exceptions.EndpointNotFound, + sc.url_for, + service_name='Image Servers', + service_type='compute', + ) - urls = sc.get_urls(service_type='image', service_name='Image Servers', - interface='public') + urls = sc.get_urls( + service_type='image', + service_name='Image Servers', + interface='public', + ) self.assertIn('https://image.north.host/v1/', urls) self.assertIn('https://image.south.host/v1/', urls) - urls = sc.get_urls(service_type='image', service_name='Servers', - interface='public') + urls = sc.get_urls( + service_type='image', service_name='Servers', interface='public' + ) self.assertEqual(0, len(urls)) @@ -194,23 +234,28 @@ def test_service_catalog_multiple_service_types(self): for i in range(3): s = token.add_service('compute') - s.add_endpoint(public='public-%d' % i, - admin='admin-%d' % i, - internal='internal-%d' % i, - region='region-%d' % i) + s.add_endpoint( + public='public-%d' % i, + admin='admin-%d' % i, + internal='internal-%d' % i, + region='region-%d' % i, + ) auth_ref = access.create(body=token) - urls = auth_ref.service_catalog.get_urls(service_type='compute', - interface='publicURL') + urls = auth_ref.service_catalog.get_urls( + service_type='compute', interface='publicURL' + ) - self.assertEqual(set(['public-0', 'public-1', 'public-2']), set(urls)) + self.assertEqual({'public-0', 'public-1', 'public-2'}, set(urls)) - urls = auth_ref.service_catalog.get_urls(service_type='compute', - interface='publicURL', - region_name='region-1') + urls = auth_ref.service_catalog.get_urls( + service_type='compute', + interface='publicURL', + region_name='region-1', + ) - self.assertEqual(('public-1', ), urls) + self.assertEqual(('public-1',), urls) def test_service_catalog_endpoint_id(self): token = fixture.V2Token() @@ -228,23 +273,27 @@ def test_service_catalog_endpoint_id(self): urls = auth_ref.service_catalog.get_urls(interface='public') self.assertEqual(2, len(urls)) - urls = auth_ref.service_catalog.get_urls(endpoint_id=endpoint_id, - interface='public') + urls = auth_ref.service_catalog.get_urls( + endpoint_id=endpoint_id, interface='public' + ) - self.assertEqual((public_url, ), urls) + self.assertEqual((public_url,), urls) # with bad endpoint_id nothing should be found - urls = auth_ref.service_catalog.get_urls(endpoint_id=uuid.uuid4().hex, - interface='public') + urls = auth_ref.service_catalog.get_urls( + endpoint_id=uuid.uuid4().hex, interface='public' + ) self.assertEqual(0, len(urls)) # we ignore a service_id because v2 doesn't know what it is - urls = auth_ref.service_catalog.get_urls(endpoint_id=endpoint_id, - service_id=uuid.uuid4().hex, - interface='public') + urls = auth_ref.service_catalog.get_urls( + endpoint_id=endpoint_id, + service_id=uuid.uuid4().hex, + interface='public', + ) - self.assertEqual((public_url, ), urls) + self.assertEqual((public_url,), urls) def test_service_catalog_without_service_type(self): token = fixture.V2Token() @@ -260,8 +309,9 @@ def test_service_catalog_without_service_type(self): s.add_endpoint(public=public_url) auth_ref = access.create(body=token) - urls = auth_ref.service_catalog.get_urls(service_type=None, - interface='public') + urls = auth_ref.service_catalog.get_urls( + service_type=None, interface='public' + ) self.assertEqual(3, len(urls)) diff --git a/keystoneauth1/tests/unit/access/test_v3_access.py b/keystoneauth1/tests/unit/access/test_v3_access.py index 5c122633..1b464ee7 100644 --- a/keystoneauth1/tests/unit/access/test_v3_access.py +++ b/keystoneauth1/tests/unit/access/test_v3_access.py @@ -21,7 +21,6 @@ class AccessV3Test(utils.TestCase): - def test_building_unscoped_accessinfo(self): token = fixture.V3Token() token_id = uuid.uuid4().hex @@ -52,10 +51,14 @@ def test_building_unscoped_accessinfo(self): self.assertIsNone(auth_ref.project_domain_id) self.assertIsNone(auth_ref.project_domain_name) - self.assertEqual(auth_ref.expires, timeutils.parse_isotime( - token['token']['expires_at'])) - self.assertEqual(auth_ref.issued, timeutils.parse_isotime( - token['token']['issued_at'])) + self.assertEqual( + auth_ref.expires, + timeutils.parse_isotime(token['token']['expires_at']), + ) + self.assertEqual( + auth_ref.issued, + timeutils.parse_isotime(token['token']['issued_at']), + ) self.assertEqual(auth_ref.expires, token.expires) self.assertEqual(auth_ref.issued, token.issued) @@ -197,8 +200,9 @@ def test_building_project_scoped_accessinfo(self): self.assertEqual(auth_ref.tenant_id, auth_ref.project_id) self.assertEqual(token.project_domain_id, auth_ref.project_domain_id) - self.assertEqual(token.project_domain_name, - auth_ref.project_domain_name) + self.assertEqual( + token.project_domain_name, auth_ref.project_domain_name + ) self.assertEqual(token.user_domain_id, auth_ref.user_domain_id) self.assertEqual(token.user_domain_name, auth_ref.user_domain_name) @@ -243,8 +247,9 @@ def test_building_project_as_domain_scoped_accessinfo(self): self.assertEqual(auth_ref.tenant_id, auth_ref.project_id) self.assertEqual(token.project_domain_id, auth_ref.project_domain_id) - self.assertEqual(token.project_domain_name, - auth_ref.project_domain_name) + self.assertEqual( + token.project_domain_name, auth_ref.project_domain_name + ) self.assertEqual(token.user_domain_id, auth_ref.user_domain_id) self.assertEqual(token.user_domain_name, auth_ref.user_domain_name) @@ -262,19 +267,22 @@ def test_oauth_access(self): token = fixture.V3Token() token.set_project_scope() - token.set_oauth(access_token_id=access_token_id, - consumer_id=consumer_id) + token.set_oauth( + access_token_id=access_token_id, consumer_id=consumer_id + ) auth_ref = access.create(body=token) self.assertEqual(consumer_id, auth_ref.oauth_consumer_id) self.assertEqual(access_token_id, auth_ref.oauth_access_token_id) - self.assertEqual(consumer_id, - auth_ref._data['token']['OS-OAUTH1']['consumer_id']) + self.assertEqual( + consumer_id, auth_ref._data['token']['OS-OAUTH1']['consumer_id'] + ) self.assertEqual( access_token_id, - auth_ref._data['token']['OS-OAUTH1']['access_token_id']) + auth_ref._data['token']['OS-OAUTH1']['access_token_id'], + ) def test_federated_property_standard_token(self): """Check if is_federated property returns expected value.""" diff --git a/keystoneauth1/tests/unit/access/test_v3_service_catalog.py b/keystoneauth1/tests/unit/access/test_v3_service_catalog.py index 4df17590..470b8e53 100644 --- a/keystoneauth1/tests/unit/access/test_v3_service_catalog.py +++ b/keystoneauth1/tests/unit/access/test_v3_service_catalog.py @@ -20,10 +20,11 @@ class ServiceCatalogTest(utils.TestCase): def setUp(self): - super(ServiceCatalogTest, self).setUp() + super().setUp() self.AUTH_RESPONSE_BODY = fixture.V3Token( - audit_chain_id=uuid.uuid4().hex) + audit_chain_id=uuid.uuid4().hex + ) self.AUTH_RESPONSE_BODY.set_project_scope() self.AUTH_RESPONSE_BODY.add_role(name='admin') @@ -34,207 +35,251 @@ def setUp(self): public='https://compute.north.host/novapi/public', internal='https://compute.north.host/novapi/internal', admin='https://compute.north.host/novapi/admin', - region='North') + region='North', + ) s = self.AUTH_RESPONSE_BODY.add_service('object-store', name='swift') s.add_standard_endpoints( public='http://swift.north.host/swiftapi/public', internal='http://swift.north.host/swiftapi/internal', admin='http://swift.north.host/swiftapi/admin', - region='South') + region='South', + ) s = self.AUTH_RESPONSE_BODY.add_service('image', name='glance') s.add_standard_endpoints( public='http://glance.north.host/glanceapi/public', internal='http://glance.north.host/glanceapi/internal', admin='http://glance.north.host/glanceapi/admin', - region='North') + region='North', + ) s.add_standard_endpoints( public='http://glance.south.host/glanceapi/public', internal='http://glance.south.host/glanceapi/internal', admin='http://glance.south.host/glanceapi/admin', - region='South') + region='South', + ) s = self.AUTH_RESPONSE_BODY.add_service('block-storage', name='cinder') s.add_standard_endpoints( public='http://cinder.north.host/cinderapi/public', internal='http://cinder.north.host/cinderapi/internal', admin='http://cinder.north.host/cinderapi/admin', - region='North') + region='North', + ) s = self.AUTH_RESPONSE_BODY.add_service('volumev2', name='cinder') s.add_standard_endpoints( public='http://cinder.south.host/cinderapi/public/v2', internal='http://cinder.south.host/cinderapi/internal/v2', admin='http://cinder.south.host/cinderapi/admin/v2', - region='South') + region='South', + ) s = self.AUTH_RESPONSE_BODY.add_service('volumev3', name='cinder') s.add_standard_endpoints( public='http://cinder.south.host/cinderapi/public/v3', internal='http://cinder.south.host/cinderapi/internal/v3', admin='http://cinder.south.host/cinderapi/admin/v3', - region='South') - - self.north_endpoints = {'public': - 'http://glance.north.host/glanceapi/public', - 'internal': - 'http://glance.north.host/glanceapi/internal', - 'admin': - 'http://glance.north.host/glanceapi/admin'} - - self.south_endpoints = {'public': - 'http://glance.south.host/glanceapi/public', - 'internal': - 'http://glance.south.host/glanceapi/internal', - 'admin': - 'http://glance.south.host/glanceapi/admin'} + region='South', + ) + + self.north_endpoints = { + 'public': 'http://glance.north.host/glanceapi/public', + 'internal': 'http://glance.north.host/glanceapi/internal', + 'admin': 'http://glance.north.host/glanceapi/admin', + } + + self.south_endpoints = { + 'public': 'http://glance.south.host/glanceapi/public', + 'internal': 'http://glance.south.host/glanceapi/internal', + 'admin': 'http://glance.south.host/glanceapi/admin', + } def test_building_a_service_catalog(self): - auth_ref = access.create(auth_token=uuid.uuid4().hex, - body=self.AUTH_RESPONSE_BODY) + auth_ref = access.create( + auth_token=uuid.uuid4().hex, body=self.AUTH_RESPONSE_BODY + ) sc = auth_ref.service_catalog - self.assertEqual(sc.url_for(service_type='compute'), - "https://compute.north.host/novapi/public") - self.assertEqual(sc.url_for(service_type='compute', - interface='internal'), - "https://compute.north.host/novapi/internal") - - self.assertRaises(exceptions.EndpointNotFound, - sc.url_for, - region_name='South', - service_type='compute') + self.assertEqual( + sc.url_for(service_type='compute'), + "https://compute.north.host/novapi/public", + ) + self.assertEqual( + sc.url_for(service_type='compute', interface='internal'), + "https://compute.north.host/novapi/internal", + ) + + self.assertRaises( + exceptions.EndpointNotFound, + sc.url_for, + region_name='South', + service_type='compute', + ) def test_service_catalog_endpoints(self): - auth_ref = access.create(auth_token=uuid.uuid4().hex, - body=self.AUTH_RESPONSE_BODY) + auth_ref = access.create( + auth_token=uuid.uuid4().hex, body=self.AUTH_RESPONSE_BODY + ) sc = auth_ref.service_catalog - public_ep = sc.get_endpoints(service_type='compute', - interface='public') + public_ep = sc.get_endpoints( + service_type='compute', interface='public' + ) self.assertEqual(public_ep['compute'][0]['region'], 'North') - self.assertEqual(public_ep['compute'][0]['url'], - "https://compute.north.host/novapi/public") + self.assertEqual( + public_ep['compute'][0]['url'], + "https://compute.north.host/novapi/public", + ) def test_service_catalog_alias_find_official(self): - auth_ref = access.create(auth_token=uuid.uuid4().hex, - body=self.AUTH_RESPONSE_BODY) + auth_ref = access.create( + auth_token=uuid.uuid4().hex, body=self.AUTH_RESPONSE_BODY + ) sc = auth_ref.service_catalog # Tests that we find the block-storage endpoint when we request # the volume endpoint. - public_ep = sc.get_endpoints(service_type='volume', - interface='public', - region_name='North') + public_ep = sc.get_endpoints( + service_type='volume', interface='public', region_name='North' + ) self.assertEqual(public_ep['block-storage'][0]['region'], 'North') - self.assertEqual(public_ep['block-storage'][0]['url'], - "http://cinder.north.host/cinderapi/public") + self.assertEqual( + public_ep['block-storage'][0]['url'], + "http://cinder.north.host/cinderapi/public", + ) def test_service_catalog_alias_find_exact_match(self): - auth_ref = access.create(auth_token=uuid.uuid4().hex, - body=self.AUTH_RESPONSE_BODY) + auth_ref = access.create( + auth_token=uuid.uuid4().hex, body=self.AUTH_RESPONSE_BODY + ) sc = auth_ref.service_catalog # Tests that we find the volumev3 endpoint when we request it. - public_ep = sc.get_endpoints(service_type='volumev3', - interface='public') + public_ep = sc.get_endpoints( + service_type='volumev3', interface='public' + ) self.assertEqual(public_ep['volumev3'][0]['region'], 'South') - self.assertEqual(public_ep['volumev3'][0]['url'], - "http://cinder.south.host/cinderapi/public/v3") + self.assertEqual( + public_ep['volumev3'][0]['url'], + "http://cinder.south.host/cinderapi/public/v3", + ) def test_service_catalog_alias_find_best_match(self): - auth_ref = access.create(auth_token=uuid.uuid4().hex, - body=self.AUTH_RESPONSE_BODY) + auth_ref = access.create( + auth_token=uuid.uuid4().hex, body=self.AUTH_RESPONSE_BODY + ) sc = auth_ref.service_catalog # Tests that we find the volumev3 endpoint when we request # block-storage when only volumev2 and volumev3 are present since # volumev3 comes first in the list. - public_ep = sc.get_endpoints(service_type='block-storage', - interface='public', - region_name='South') + public_ep = sc.get_endpoints( + service_type='block-storage', + interface='public', + region_name='South', + ) self.assertEqual(public_ep['volumev3'][0]['region'], 'South') - self.assertEqual(public_ep['volumev3'][0]['url'], - "http://cinder.south.host/cinderapi/public/v3") + self.assertEqual( + public_ep['volumev3'][0]['url'], + "http://cinder.south.host/cinderapi/public/v3", + ) def test_service_catalog_alias_all_by_name(self): - auth_ref = access.create(auth_token=uuid.uuid4().hex, - body=self.AUTH_RESPONSE_BODY) + auth_ref = access.create( + auth_token=uuid.uuid4().hex, body=self.AUTH_RESPONSE_BODY + ) sc = auth_ref.service_catalog # Tests that we find all the cinder endpoints since we request # them by name and that no filtering related to aliases happens. - public_ep = sc.get_endpoints(service_name='cinder', - interface='public') + public_ep = sc.get_endpoints(service_name='cinder', interface='public') self.assertEqual(public_ep['volumev2'][0]['region'], 'South') - self.assertEqual(public_ep['volumev2'][0]['url'], - "http://cinder.south.host/cinderapi/public/v2") + self.assertEqual( + public_ep['volumev2'][0]['url'], + "http://cinder.south.host/cinderapi/public/v2", + ) self.assertEqual(public_ep['volumev3'][0]['region'], 'South') - self.assertEqual(public_ep['volumev3'][0]['url'], - "http://cinder.south.host/cinderapi/public/v3") + self.assertEqual( + public_ep['volumev3'][0]['url'], + "http://cinder.south.host/cinderapi/public/v3", + ) self.assertEqual(public_ep['block-storage'][0]['region'], 'North') - self.assertEqual(public_ep['block-storage'][0]['url'], - "http://cinder.north.host/cinderapi/public") + self.assertEqual( + public_ep['block-storage'][0]['url'], + "http://cinder.north.host/cinderapi/public", + ) def test_service_catalog_regions(self): self.AUTH_RESPONSE_BODY['token']['region_name'] = "North" - auth_ref = access.create(auth_token=uuid.uuid4().hex, - body=self.AUTH_RESPONSE_BODY) + auth_ref = access.create( + auth_token=uuid.uuid4().hex, body=self.AUTH_RESPONSE_BODY + ) sc = auth_ref.service_catalog url = sc.url_for(service_type='image', interface='public') self.assertEqual(url, "http://glance.north.host/glanceapi/public") self.AUTH_RESPONSE_BODY['token']['region_name'] = "South" - auth_ref = access.create(auth_token=uuid.uuid4().hex, - body=self.AUTH_RESPONSE_BODY) + auth_ref = access.create( + auth_token=uuid.uuid4().hex, body=self.AUTH_RESPONSE_BODY + ) sc = auth_ref.service_catalog - url = sc.url_for(service_type='image', - region_name="South", - interface='internal') + url = sc.url_for( + service_type='image', region_name="South", interface='internal' + ) self.assertEqual(url, "http://glance.south.host/glanceapi/internal") def test_service_catalog_empty(self): self.AUTH_RESPONSE_BODY['token']['catalog'] = [] - auth_ref = access.create(auth_token=uuid.uuid4().hex, - body=self.AUTH_RESPONSE_BODY) - self.assertRaises(exceptions.EmptyCatalog, - auth_ref.service_catalog.url_for, - service_type='image', - interface='internalURL') + auth_ref = access.create( + auth_token=uuid.uuid4().hex, body=self.AUTH_RESPONSE_BODY + ) + self.assertRaises( + exceptions.EmptyCatalog, + auth_ref.service_catalog.url_for, + service_type='image', + interface='internalURL', + ) def test_service_catalog_get_endpoints_region_names(self): - sc = access.create(auth_token=uuid.uuid4().hex, - body=self.AUTH_RESPONSE_BODY).service_catalog + sc = access.create( + auth_token=uuid.uuid4().hex, body=self.AUTH_RESPONSE_BODY + ).service_catalog endpoints = sc.get_endpoints(service_type='image', region_name='North') self.assertEqual(len(endpoints), 1) for endpoint in endpoints['image']: - self.assertEqual(endpoint['url'], - self.north_endpoints[endpoint['interface']]) + self.assertEqual( + endpoint['url'], self.north_endpoints[endpoint['interface']] + ) endpoints = sc.get_endpoints(service_type='image', region_name='South') self.assertEqual(len(endpoints), 1) for endpoint in endpoints['image']: - self.assertEqual(endpoint['url'], - self.south_endpoints[endpoint['interface']]) + self.assertEqual( + endpoint['url'], self.south_endpoints[endpoint['interface']] + ) endpoints = sc.get_endpoints(service_type='compute') self.assertEqual(len(endpoints['compute']), 3) - endpoints = sc.get_endpoints(service_type='compute', - region_name='North') + endpoints = sc.get_endpoints( + service_type='compute', region_name='North' + ) self.assertEqual(len(endpoints['compute']), 3) - endpoints = sc.get_endpoints(service_type='compute', - region_name='West') + endpoints = sc.get_endpoints( + service_type='compute', region_name='West' + ) self.assertEqual(len(endpoints['compute']), 0) def test_service_catalog_url_for_region_names(self): - sc = access.create(auth_token=uuid.uuid4().hex, - body=self.AUTH_RESPONSE_BODY).service_catalog + sc = access.create( + auth_token=uuid.uuid4().hex, body=self.AUTH_RESPONSE_BODY + ).service_catalog url = sc.url_for(service_type='image', region_name='North') self.assertEqual(url, self.north_endpoints['public']) @@ -242,12 +287,17 @@ def test_service_catalog_url_for_region_names(self): url = sc.url_for(service_type='image', region_name='South') self.assertEqual(url, self.south_endpoints['public']) - self.assertRaises(exceptions.EndpointNotFound, sc.url_for, - service_type='image', region_name='West') + self.assertRaises( + exceptions.EndpointNotFound, + sc.url_for, + service_type='image', + region_name='West', + ) def test_service_catalog_get_url_region_names(self): - sc = access.create(auth_token=uuid.uuid4().hex, - body=self.AUTH_RESPONSE_BODY).service_catalog + sc = access.create( + auth_token=uuid.uuid4().hex, body=self.AUTH_RESPONSE_BODY + ).service_catalog urls = sc.get_urls(service_type='image') self.assertEqual(len(urls), 2) @@ -264,29 +314,43 @@ def test_service_catalog_get_url_region_names(self): self.assertEqual(len(urls), 0) def test_service_catalog_service_name(self): - sc = access.create(auth_token=uuid.uuid4().hex, - body=self.AUTH_RESPONSE_BODY).service_catalog - - url = sc.url_for(service_name='glance', interface='public', - service_type='image', region_name='North') + sc = access.create( + auth_token=uuid.uuid4().hex, body=self.AUTH_RESPONSE_BODY + ).service_catalog + + url = sc.url_for( + service_name='glance', + interface='public', + service_type='image', + region_name='North', + ) self.assertEqual('http://glance.north.host/glanceapi/public', url) - url = sc.url_for(service_name='glance', interface='public', - service_type='image', region_name='South') + url = sc.url_for( + service_name='glance', + interface='public', + service_type='image', + region_name='South', + ) self.assertEqual('http://glance.south.host/glanceapi/public', url) - self.assertRaises(exceptions.EndpointNotFound, sc.url_for, - service_name='glance', service_type='compute') + self.assertRaises( + exceptions.EndpointNotFound, + sc.url_for, + service_name='glance', + service_type='compute', + ) - urls = sc.get_urls(service_type='image', service_name='glance', - interface='public') + urls = sc.get_urls( + service_type='image', service_name='glance', interface='public' + ) self.assertIn('http://glance.north.host/glanceapi/public', urls) self.assertIn('http://glance.south.host/glanceapi/public', urls) - urls = sc.get_urls(service_type='image', - service_name='Servers', - interface='public') + urls = sc.get_urls( + service_type='image', service_name='Servers', interface='public' + ) self.assertEqual(0, len(urls)) @@ -304,81 +368,102 @@ def test_service_catalog_without_name(self): s = f.add_service('volume') s.add_standard_endpoints( - public='http://public.com:8776/v1/%s' % tenant, - internal='http://internal:8776/v1/%s' % tenant, - admin='http://admin:8776/v1/%s' % tenant, - region=region) + public=f'http://public.com:8776/v1/{tenant}', + internal=f'http://internal:8776/v1/{tenant}', + admin=f'http://admin:8776/v1/{tenant}', + region=region, + ) s = f.add_service('image') - s.add_standard_endpoints(public='http://public.com:9292/v1', - internal='http://internal:9292/v1', - admin='http://admin:9292/v1', - region=region) + s.add_standard_endpoints( + public='http://public.com:9292/v1', + internal='http://internal:9292/v1', + admin='http://admin:9292/v1', + region=region, + ) s = f.add_service('compute') s.add_standard_endpoints( - public='http://public.com:8774/v2/%s' % tenant, - internal='http://internal:8774/v2/%s' % tenant, - admin='http://admin:8774/v2/%s' % tenant, - region=region) + public=f'http://public.com:8774/v2/{tenant}', + internal=f'http://internal:8774/v2/{tenant}', + admin=f'http://admin:8774/v2/{tenant}', + region=region, + ) s = f.add_service('ec2') s.add_standard_endpoints( public='http://public.com:8773/services/Cloud', internal='http://internal:8773/services/Cloud', admin='http://admin:8773/services/Admin', - region=region) + region=region, + ) s = f.add_service('identity') - s.add_standard_endpoints(public='http://public.com:5000/v3', - internal='http://internal:5000/v3', - admin='http://admin:35357/v3', - region=region) + s.add_standard_endpoints( + public='http://public.com:5000/v3', + internal='http://internal:5000/v3', + admin='http://admin:35357/v3', + region=region, + ) pr_auth_ref = access.create(body=f) pr_sc = pr_auth_ref.service_catalog # this will work because there are no service names on that token url_ref = 'http://public.com:8774/v2/225da22d3ce34b15877ea70b2a575f58' - url = pr_sc.url_for(service_type='compute', service_name='NotExist', - interface='public') + url = pr_sc.url_for( + service_type='compute', service_name='NotExist', interface='public' + ) self.assertEqual(url_ref, url) ab_auth_ref = access.create(body=self.AUTH_RESPONSE_BODY) ab_sc = ab_auth_ref.service_catalog # this won't work because there is a name and it's not this one - self.assertRaises(exceptions.EndpointNotFound, ab_sc.url_for, - service_type='compute', service_name='NotExist', - interface='public') + self.assertRaises( + exceptions.EndpointNotFound, + ab_sc.url_for, + service_type='compute', + service_name='NotExist', + interface='public', + ) class ServiceCatalogV3Test(ServiceCatalogTest): - def test_building_a_service_catalog(self): - sc = access.create(auth_token=uuid.uuid4().hex, - body=self.AUTH_RESPONSE_BODY).service_catalog - - self.assertEqual(sc.url_for(service_type='compute'), - 'https://compute.north.host/novapi/public') - self.assertEqual(sc.url_for(service_type='compute', - interface='internal'), - 'https://compute.north.host/novapi/internal') - - self.assertRaises(exceptions.EndpointNotFound, - sc.url_for, - region_name='South', - service_type='compute') + sc = access.create( + auth_token=uuid.uuid4().hex, body=self.AUTH_RESPONSE_BODY + ).service_catalog + + self.assertEqual( + sc.url_for(service_type='compute'), + 'https://compute.north.host/novapi/public', + ) + self.assertEqual( + sc.url_for(service_type='compute', interface='internal'), + 'https://compute.north.host/novapi/internal', + ) + + self.assertRaises( + exceptions.EndpointNotFound, + sc.url_for, + region_name='South', + service_type='compute', + ) def test_service_catalog_endpoints(self): - sc = access.create(auth_token=uuid.uuid4().hex, - body=self.AUTH_RESPONSE_BODY).service_catalog + sc = access.create( + auth_token=uuid.uuid4().hex, body=self.AUTH_RESPONSE_BODY + ).service_catalog - public_ep = sc.get_endpoints(service_type='compute', - interface='public') + public_ep = sc.get_endpoints( + service_type='compute', interface='public' + ) self.assertEqual(public_ep['compute'][0]['region_id'], 'North') - self.assertEqual(public_ep['compute'][0]['url'], - 'https://compute.north.host/novapi/public') + self.assertEqual( + public_ep['compute'][0]['url'], + 'https://compute.north.host/novapi/public', + ) def test_service_catalog_multiple_service_types(self): token = fixture.V3Token() @@ -386,23 +471,26 @@ def test_service_catalog_multiple_service_types(self): for i in range(3): s = token.add_service('compute') - s.add_standard_endpoints(public='public-%d' % i, - admin='admin-%d' % i, - internal='internal-%d' % i, - region='region-%d' % i) + s.add_standard_endpoints( + public='public-%d' % i, + admin='admin-%d' % i, + internal='internal-%d' % i, + region='region-%d' % i, + ) auth_ref = access.create(resp=None, body=token) - urls = auth_ref.service_catalog.get_urls(service_type='compute', - interface='public') + urls = auth_ref.service_catalog.get_urls( + service_type='compute', interface='public' + ) - self.assertEqual(set(['public-0', 'public-1', 'public-2']), set(urls)) + self.assertEqual({'public-0', 'public-1', 'public-2'}, set(urls)) - urls = auth_ref.service_catalog.get_urls(service_type='compute', - interface='public', - region_name='region-1') + urls = auth_ref.service_catalog.get_urls( + service_type='compute', interface='public', region_name='region-1' + ) - self.assertEqual(('public-1', ), urls) + self.assertEqual(('public-1',), urls) def test_service_catalog_endpoint_id(self): token = fixture.V3Token() @@ -419,37 +507,42 @@ def test_service_catalog_endpoint_id(self): auth_ref = access.create(body=token) # initially assert that we get back all our urls for a simple filter - urls = auth_ref.service_catalog.get_urls(service_type='compute', - interface='public') + urls = auth_ref.service_catalog.get_urls( + service_type='compute', interface='public' + ) self.assertEqual(2, len(urls)) # with bad endpoint_id nothing should be found - urls = auth_ref.service_catalog.get_urls(service_type='compute', - endpoint_id=uuid.uuid4().hex, - interface='public') + urls = auth_ref.service_catalog.get_urls( + service_type='compute', + endpoint_id=uuid.uuid4().hex, + interface='public', + ) self.assertEqual(0, len(urls)) # with service_id we get back both public endpoints - urls = auth_ref.service_catalog.get_urls(service_type='compute', - service_id=service_id, - interface='public') + urls = auth_ref.service_catalog.get_urls( + service_type='compute', service_id=service_id, interface='public' + ) self.assertEqual(2, len(urls)) # with service_id and endpoint_id we get back the url we want - urls = auth_ref.service_catalog.get_urls(service_type='compute', - service_id=service_id, - endpoint_id=endpoint_id, - interface='public') + urls = auth_ref.service_catalog.get_urls( + service_type='compute', + service_id=service_id, + endpoint_id=endpoint_id, + interface='public', + ) - self.assertEqual((public_url, ), urls) + self.assertEqual((public_url,), urls) # with service_id and endpoint_id we get back the url we want - urls = auth_ref.service_catalog.get_urls(service_type='compute', - endpoint_id=endpoint_id, - interface='public') + urls = auth_ref.service_catalog.get_urls( + service_type='compute', endpoint_id=endpoint_id, interface='public' + ) - self.assertEqual((public_url, ), urls) + self.assertEqual((public_url,), urls) def test_service_catalog_without_service_type(self): token = fixture.V3Token() diff --git a/keystoneauth1/tests/unit/client_fixtures.py b/keystoneauth1/tests/unit/client_fixtures.py index e749ac21..25a5adbc 100644 --- a/keystoneauth1/tests/unit/client_fixtures.py +++ b/keystoneauth1/tests/unit/client_fixtures.py @@ -23,7 +23,8 @@ def project_scoped_token(): project_id='225da22d3ce34b15877ea70b2a575f58', project_name='exampleproject', project_domain_id='4e6893b7ba0b4006840c3845660b86ed', - project_domain_name='exampledomain') + project_domain_name='exampledomain', + ) fixture.add_role(id='76e72a', name='admin') fixture.add_role(id='f4f392', name='member') @@ -33,36 +34,43 @@ def project_scoped_token(): service = fixture.add_service('volume') service.add_standard_endpoints( - public='http://public.com:8776/v1/%s' % tenant, - internal='http://internal:8776/v1/%s' % tenant, - admin='http://admin:8776/v1/%s' % tenant, - region=region) + public=f'http://public.com:8776/v1/{tenant}', + internal=f'http://internal:8776/v1/{tenant}', + admin=f'http://admin:8776/v1/{tenant}', + region=region, + ) service = fixture.add_service('image') - service.add_standard_endpoints(public='http://public.com:9292/v1', - internal='http://internal:9292/v1', - admin='http://admin:9292/v1', - region=region) + service.add_standard_endpoints( + public='http://public.com:9292/v1', + internal='http://internal:9292/v1', + admin='http://admin:9292/v1', + region=region, + ) service = fixture.add_service('compute') service.add_standard_endpoints( - public='http://public.com:8774/v2/%s' % tenant, - internal='http://internal:8774/v2/%s' % tenant, - admin='http://admin:8774/v2/%s' % tenant, - region=region) + public=f'http://public.com:8774/v2/{tenant}', + internal=f'http://internal:8774/v2/{tenant}', + admin=f'http://admin:8774/v2/{tenant}', + region=region, + ) service = fixture.add_service('ec2') service.add_standard_endpoints( public='http://public.com:8773/services/Cloud', internal='http://internal:8773/services/Cloud', admin='http://admin:8773/services/Admin', - region=region) + region=region, + ) service = fixture.add_service('identity') - service.add_standard_endpoints(public='http://public.com:5000/v3', - internal='http://internal:5000/v3', - admin='http://admin:35357/v3', - region=region) + service.add_standard_endpoints( + public='http://public.com:5000/v3', + internal='http://internal:5000/v3', + admin='http://admin:35357/v3', + region=region, + ) return fixture @@ -75,48 +83,56 @@ def domain_scoped_token(): user_domain_name='exampledomain', expires='2010-11-01T03:32:15-05:00', domain_id='8e9283b7ba0b1038840c3842058b86ab', - domain_name='anotherdomain') + domain_name='anotherdomain', + ) fixture.add_role(id='76e72a', name='admin') fixture.add_role(id='f4f392', name='member') region = 'RegionOne' service = fixture.add_service('volume') - service.add_standard_endpoints(public='http://public.com:8776/v1/None', - internal='http://internal.com:8776/v1/None', - admin='http://admin.com:8776/v1/None', - region=region) + service.add_standard_endpoints( + public='http://public.com:8776/v1/None', + internal='http://internal.com:8776/v1/None', + admin='http://admin.com:8776/v1/None', + region=region, + ) service = fixture.add_service('image') - service.add_standard_endpoints(public='http://public.com:9292/v1', - internal='http://internal:9292/v1', - admin='http://admin:9292/v1', - region=region) + service.add_standard_endpoints( + public='http://public.com:9292/v1', + internal='http://internal:9292/v1', + admin='http://admin:9292/v1', + region=region, + ) service = fixture.add_service('compute') - service.add_standard_endpoints(public='http://public.com:8774/v1.1/None', - internal='http://internal:8774/v1.1/None', - admin='http://admin:8774/v1.1/None', - region=region) + service.add_standard_endpoints( + public='http://public.com:8774/v1.1/None', + internal='http://internal:8774/v1.1/None', + admin='http://admin:8774/v1.1/None', + region=region, + ) service = fixture.add_service('ec2') service.add_standard_endpoints( public='http://public.com:8773/services/Cloud', internal='http://internal:8773/services/Cloud', admin='http://admin:8773/services/Admin', - region=region) + region=region, + ) service = fixture.add_service('identity') - service.add_standard_endpoints(public='http://public.com:5000/v3', - internal='http://internal:5000/v3', - admin='http://admin:35357/v3', - region=region) + service.add_standard_endpoints( + public='http://public.com:5000/v3', + internal='http://internal:5000/v3', + admin='http://admin:35357/v3', + region=region, + ) return fixture AUTH_SUBJECT_TOKEN = '3e2813b7ba0b4006840c3825860b86ed' -AUTH_RESPONSE_HEADERS = { - 'X-Subject-Token': AUTH_SUBJECT_TOKEN, -} +AUTH_RESPONSE_HEADERS = {'X-Subject-Token': AUTH_SUBJECT_TOKEN} diff --git a/keystoneauth1/tests/unit/exceptions/test_exceptions.py b/keystoneauth1/tests/unit/exceptions/test_exceptions.py index 341ef573..b48fb374 100644 --- a/keystoneauth1/tests/unit/exceptions/test_exceptions.py +++ b/keystoneauth1/tests/unit/exceptions/test_exceptions.py @@ -15,7 +15,6 @@ class ExceptionTests(utils.TestCase): - def test_clientexception_with_message(self): test_message = 'Unittest exception message.' exc = exceptions.ClientException(message=test_message) @@ -23,10 +22,8 @@ def test_clientexception_with_message(self): def test_clientexception_with_no_message(self): exc = exceptions.ClientException() - self.assertEqual(exceptions.ClientException.__name__, - exc.message) + self.assertEqual(exceptions.ClientException.__name__, exc.message) def test_using_default_message(self): exc = exceptions.AuthorizationFailure() - self.assertEqual(exceptions.AuthorizationFailure.message, - exc.message) + self.assertEqual(exceptions.AuthorizationFailure.message, exc.message) diff --git a/keystoneauth1/tests/unit/extras/kerberos/base.py b/keystoneauth1/tests/unit/extras/kerberos/base.py index f76d1481..e20e4258 100644 --- a/keystoneauth1/tests/unit/extras/kerberos/base.py +++ b/keystoneauth1/tests/unit/extras/kerberos/base.py @@ -17,8 +17,7 @@ from keystoneauth1.tests.unit import utils as test_utils -REQUEST = {'auth': {'identity': {'methods': ['kerberos'], - 'kerberos': {}}}} +REQUEST = {'auth': {'identity': {'methods': ['kerberos'], 'kerberos': {}}}} class TestCase(test_utils.TestCase): @@ -27,7 +26,7 @@ class TestCase(test_utils.TestCase): TEST_V3_URL = test_utils.TestCase.TEST_ROOT_URL + 'v3' def setUp(self): - super(TestCase, self).setUp() + super().setUp() km = utils.KerberosMock(self.requests_mock) self.kerberos_mock = self.useFixture(km) diff --git a/keystoneauth1/tests/unit/extras/kerberos/test_fedkerb_loading.py b/keystoneauth1/tests/unit/extras/kerberos/test_fedkerb_loading.py index 17056580..84cfb351 100644 --- a/keystoneauth1/tests/unit/extras/kerberos/test_fedkerb_loading.py +++ b/keystoneauth1/tests/unit/extras/kerberos/test_fedkerb_loading.py @@ -16,24 +16,26 @@ class FedKerbLoadingTests(test_utils.TestCase): - def test_options(self): - opts = [o.name for o in - loading.get_plugin_loader('v3fedkerb').get_options()] - - allowed_opts = ['system-scope', - 'domain-id', - 'domain-name', - 'identity-provider', - 'project-id', - 'project-name', - 'project-domain-id', - 'project-domain-name', - 'protocol', - 'trust-id', - 'auth-url', - 'mutual-auth', - ] + opts = [ + o.name + for o in loading.get_plugin_loader('v3fedkerb').get_options() + ] + + allowed_opts = [ + 'system-scope', + 'domain-id', + 'domain-name', + 'identity-provider', + 'project-id', + 'project-name', + 'project-domain-id', + 'project-domain-name', + 'protocol', + 'trust-id', + 'auth-url', + 'mutual-auth', + ] self.assertCountEqual(allowed_opts, opts) @@ -45,6 +47,6 @@ def test_load_none(self): self.assertRaises(exceptions.MissingRequiredOptions, self.create) def test_load(self): - self.create(auth_url='auth_url', - identity_provider='idp', - protocol='protocol') + self.create( + auth_url='auth_url', identity_provider='idp', protocol='protocol' + ) diff --git a/keystoneauth1/tests/unit/extras/kerberos/test_kerberos_loading.py b/keystoneauth1/tests/unit/extras/kerberos/test_kerberos_loading.py index f2288347..54d87d27 100644 --- a/keystoneauth1/tests/unit/extras/kerberos/test_kerberos_loading.py +++ b/keystoneauth1/tests/unit/extras/kerberos/test_kerberos_loading.py @@ -15,21 +15,23 @@ class KerberosLoadingTests(test_utils.TestCase): - def test_options(self): - opts = [o.name for o in - loading.get_plugin_loader('v3kerberos').get_options()] + opts = [ + o.name + for o in loading.get_plugin_loader('v3kerberos').get_options() + ] - allowed_opts = ['system-scope', - 'domain-id', - 'domain-name', - 'project-id', - 'project-name', - 'project-domain-id', - 'project-domain-name', - 'trust-id', - 'auth-url', - 'mutual-auth', - ] + allowed_opts = [ + 'system-scope', + 'domain-id', + 'domain-name', + 'project-id', + 'project-name', + 'project-domain-id', + 'project-domain-name', + 'trust-id', + 'auth-url', + 'mutual-auth', + ] self.assertCountEqual(allowed_opts, opts) diff --git a/keystoneauth1/tests/unit/extras/kerberos/test_mapped.py b/keystoneauth1/tests/unit/extras/kerberos/test_mapped.py index a7b86c2a..baeebd80 100644 --- a/keystoneauth1/tests/unit/extras/kerberos/test_mapped.py +++ b/keystoneauth1/tests/unit/extras/kerberos/test_mapped.py @@ -19,12 +19,11 @@ class TestMappedAuth(base.TestCase): - def setUp(self): if kerberos.requests_kerberos is None: self.skipTest("Kerberos support isn't available.") - super(TestMappedAuth, self).setUp() + super().setUp() self.protocol = uuid.uuid4().hex self.identity_provider = uuid.uuid4().hex @@ -32,18 +31,18 @@ def setUp(self): @property def token_url(self): fmt = '%s/OS-FEDERATION/identity_providers/%s/protocols/%s/auth' - return fmt % ( - self.TEST_V3_URL, - self.identity_provider, - self.protocol) + return fmt % (self.TEST_V3_URL, self.identity_provider, self.protocol) def test_unscoped_mapped_auth(self): token_id, _ = self.kerberos_mock.mock_auth_success( - url=self.token_url, method='GET') + url=self.token_url, method='GET' + ) plugin = kerberos.MappedKerberos( - auth_url=self.TEST_V3_URL, protocol=self.protocol, - identity_provider=self.identity_provider) + auth_url=self.TEST_V3_URL, + protocol=self.protocol, + identity_provider=self.identity_provider, + ) sess = session.Session() tok = plugin.get_token(sess) @@ -51,23 +50,27 @@ def test_unscoped_mapped_auth(self): self.assertEqual(token_id, tok) def test_project_scoped_mapped_auth(self): - self.kerberos_mock.mock_auth_success(url=self.token_url, - method='GET') + self.kerberos_mock.mock_auth_success(url=self.token_url, method='GET') scoped_id = uuid.uuid4().hex scoped_body = ks_fixture.V3Token() scoped_body.set_project_scope() self.requests_mock.post( - '%s/auth/tokens' % self.TEST_V3_URL, + f'{self.TEST_V3_URL}/auth/tokens', json=scoped_body, - headers={'X-Subject-Token': scoped_id, - 'Content-Type': 'application/json'}) + headers={ + 'X-Subject-Token': scoped_id, + 'Content-Type': 'application/json', + }, + ) plugin = kerberos.MappedKerberos( - auth_url=self.TEST_V3_URL, protocol=self.protocol, + auth_url=self.TEST_V3_URL, + protocol=self.protocol, identity_provider=self.identity_provider, - project_id=scoped_body.project_id) + project_id=scoped_body.project_id, + ) sess = session.Session() tok = plugin.get_token(sess) @@ -77,24 +80,28 @@ def test_project_scoped_mapped_auth(self): self.assertEqual(scoped_body.project_id, proj) def test_authenticate_with_mutual_authentication_required(self): - self.kerberos_mock.mock_auth_success(url=self.token_url, - method='GET') + self.kerberos_mock.mock_auth_success(url=self.token_url, method='GET') scoped_id = uuid.uuid4().hex scoped_body = ks_fixture.V3Token() scoped_body.set_project_scope() self.requests_mock.post( - '%s/auth/tokens' % self.TEST_V3_URL, + f'{self.TEST_V3_URL}/auth/tokens', json=scoped_body, - headers={'X-Subject-Token': scoped_id, - 'Content-Type': 'application/json'}) + headers={ + 'X-Subject-Token': scoped_id, + 'Content-Type': 'application/json', + }, + ) plugin = kerberos.MappedKerberos( - auth_url=self.TEST_V3_URL, protocol=self.protocol, + auth_url=self.TEST_V3_URL, + protocol=self.protocol, identity_provider=self.identity_provider, project_id=scoped_body.project_id, - mutual_auth='required') + mutual_auth='required', + ) sess = session.Session() tok = plugin.get_token(sess) @@ -105,24 +112,28 @@ def test_authenticate_with_mutual_authentication_required(self): self.assertEqual(self.kerberos_mock.called_auth_server, True) def test_authenticate_with_mutual_authentication_disabled(self): - self.kerberos_mock.mock_auth_success(url=self.token_url, - method='GET') + self.kerberos_mock.mock_auth_success(url=self.token_url, method='GET') scoped_id = uuid.uuid4().hex scoped_body = ks_fixture.V3Token() scoped_body.set_project_scope() self.requests_mock.post( - '%s/auth/tokens' % self.TEST_V3_URL, + f'{self.TEST_V3_URL}/auth/tokens', json=scoped_body, - headers={'X-Subject-Token': scoped_id, - 'Content-Type': 'application/json'}) + headers={ + 'X-Subject-Token': scoped_id, + 'Content-Type': 'application/json', + }, + ) plugin = kerberos.MappedKerberos( - auth_url=self.TEST_V3_URL, protocol=self.protocol, + auth_url=self.TEST_V3_URL, + protocol=self.protocol, identity_provider=self.identity_provider, project_id=scoped_body.project_id, - mutual_auth='disabled') + mutual_auth='disabled', + ) sess = session.Session() tok = plugin.get_token(sess) diff --git a/keystoneauth1/tests/unit/extras/kerberos/test_v3.py b/keystoneauth1/tests/unit/extras/kerberos/test_v3.py index 12e8bfe2..446c3aa8 100644 --- a/keystoneauth1/tests/unit/extras/kerberos/test_v3.py +++ b/keystoneauth1/tests/unit/extras/kerberos/test_v3.py @@ -16,12 +16,11 @@ class TestKerberosAuth(base.TestCase): - def setUp(self): if kerberos.requests_kerberos is None: self.skipTest("Kerberos support isn't available.") - super(TestKerberosAuth, self).setUp() + super().setUp() def test_authenticate_with_kerberos_domain_scoped(self): token_id, token_body = self.kerberos_mock.mock_auth_success() @@ -33,22 +32,25 @@ def test_authenticate_with_kerberos_domain_scoped(self): self.assertRequestBody() self.assertEqual( self.kerberos_mock.challenge_header, - self.requests_mock.last_request.headers['Authorization']) + self.requests_mock.last_request.headers['Authorization'], + ) self.assertEqual(token_id, a.auth_ref.auth_token) self.assertEqual(token_id, token) def test_authenticate_with_kerberos_mutual_authentication_required(self): token_id, token_body = self.kerberos_mock.mock_auth_success() - a = kerberos.Kerberos(self.TEST_ROOT_URL + 'v3', - mutual_auth='required') + a = kerberos.Kerberos( + self.TEST_ROOT_URL + 'v3', mutual_auth='required' + ) s = session.Session(a) token = a.get_token(s) self.assertRequestBody() self.assertEqual( self.kerberos_mock.challenge_header, - self.requests_mock.last_request.headers['Authorization']) + self.requests_mock.last_request.headers['Authorization'], + ) self.assertEqual(token_id, a.auth_ref.auth_token) self.assertEqual(token_id, token) self.assertEqual(self.kerberos_mock.called_auth_server, True) @@ -56,15 +58,17 @@ def test_authenticate_with_kerberos_mutual_authentication_required(self): def test_authenticate_with_kerberos_mutual_authentication_disabled(self): token_id, token_body = self.kerberos_mock.mock_auth_success() - a = kerberos.Kerberos(self.TEST_ROOT_URL + 'v3', - mutual_auth='disabled') + a = kerberos.Kerberos( + self.TEST_ROOT_URL + 'v3', mutual_auth='disabled' + ) s = session.Session(a) token = a.get_token(s) self.assertRequestBody() self.assertEqual( self.kerberos_mock.challenge_header, - self.requests_mock.last_request.headers['Authorization']) + self.requests_mock.last_request.headers['Authorization'], + ) self.assertEqual(token_id, a.auth_ref.auth_token) self.assertEqual(token_id, token) self.assertEqual(self.kerberos_mock.called_auth_server, False) diff --git a/keystoneauth1/tests/unit/extras/kerberos/utils.py b/keystoneauth1/tests/unit/extras/kerberos/utils.py index fbaece71..0f48106f 100644 --- a/keystoneauth1/tests/unit/extras/kerberos/utils.py +++ b/keystoneauth1/tests/unit/extras/kerberos/utils.py @@ -13,6 +13,7 @@ import uuid import fixtures + try: # requests_kerberos won't be available on py3, it doesn't work with py3. import requests_kerberos @@ -24,29 +25,32 @@ class KerberosMock(fixtures.Fixture): - def __init__(self, requests_mock): - super(KerberosMock, self).__init__() + super().__init__() - self.challenge_header = 'Negotiate %s' % uuid.uuid4().hex - self.pass_header = 'Negotiate %s' % uuid.uuid4().hex + self.challenge_header = f'Negotiate {uuid.uuid4().hex}' + self.pass_header = f'Negotiate {uuid.uuid4().hex}' self.requests_mock = requests_mock def setUp(self): - super(KerberosMock, self).setUp() + super().setUp() if requests_kerberos is None: return - m = fixtures.MockPatchObject(requests_kerberos.HTTPKerberosAuth, - 'generate_request_header', - self._generate_request_header) + m = fixtures.MockPatchObject( + requests_kerberos.HTTPKerberosAuth, + 'generate_request_header', + self._generate_request_header, + ) self.header_fixture = self.useFixture(m) - m = fixtures.MockPatchObject(requests_kerberos.HTTPKerberosAuth, - 'authenticate_server', - self._authenticate_server) + m = fixtures.MockPatchObject( + requests_kerberos.HTTPKerberosAuth, + 'authenticate_server', + self._authenticate_server, + ) self.authenticate_fixture = self.useFixture(m) @@ -58,11 +62,12 @@ def _authenticate_server(self, response): return response.headers.get('www-authenticate') == self.pass_header def mock_auth_success( - self, - token_id=None, - token_body=None, - method='POST', - url=test_utils.TestCase.TEST_ROOT_URL + 'v3/auth/tokens'): + self, + token_id=None, + token_body=None, + method='POST', + url=test_utils.TestCase.TEST_ROOT_URL + 'v3/auth/tokens', + ): if not token_id: token_id = uuid.uuid4().hex if not token_body: @@ -70,17 +75,25 @@ def mock_auth_success( self.called_auth_server = False - response_list = [{'text': 'Fail', - 'status_code': 401, - 'headers': {'WWW-Authenticate': 'Negotiate'}}, - {'headers': {'X-Subject-Token': token_id, - 'Content-Type': 'application/json', - 'WWW-Authenticate': self.pass_header}, - 'status_code': 200, - 'json': token_body}] - - self.requests_mock.register_uri(method, - url, - response_list=response_list) + response_list = [ + { + 'text': 'Fail', + 'status_code': 401, + 'headers': {'WWW-Authenticate': 'Negotiate'}, + }, + { + 'headers': { + 'X-Subject-Token': token_id, + 'Content-Type': 'application/json', + 'WWW-Authenticate': self.pass_header, + }, + 'status_code': 200, + 'json': token_body, + }, + ] + + self.requests_mock.register_uri( + method, url, response_list=response_list + ) return token_id, token_body diff --git a/keystoneauth1/tests/unit/extras/oauth1/test_oauth1.py b/keystoneauth1/tests/unit/extras/oauth1/test_oauth1.py index 392476b9..628f3576 100644 --- a/keystoneauth1/tests/unit/extras/oauth1/test_oauth1.py +++ b/keystoneauth1/tests/unit/extras/oauth1/test_oauth1.py @@ -22,17 +22,20 @@ class OAuth1AuthTests(test_utils.TestCase): - TEST_ROOT_URL = 'http://127.0.0.1:5000/' - TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v3') + TEST_URL = '{}{}'.format(TEST_ROOT_URL, 'v3') TEST_TOKEN = uuid.uuid4().hex def stub_auth(self, subject_token=None, **kwargs): if not subject_token: subject_token = self.TEST_TOKEN - self.stub_url('POST', ['auth', 'tokens'], - headers={'X-Subject-Token': subject_token}, **kwargs) + self.stub_url( + 'POST', + ['auth', 'tokens'], + headers={'X-Subject-Token': subject_token}, + **kwargs, + ) def _validate_oauth_headers(self, auth_header, oauth_client): """Validate data in the headers. @@ -42,22 +45,27 @@ def _validate_oauth_headers(self, auth_header, oauth_client): """ self.assertThat(auth_header, matchers.StartsWith('OAuth ')) parameters = dict( - oauth1.rfc5849.utils.parse_authorization_header(auth_header)) + oauth1.rfc5849.utils.parse_authorization_header(auth_header) + ) self.assertEqual('HMAC-SHA1', parameters['oauth_signature_method']) self.assertEqual('1.0', parameters['oauth_version']) self.assertIsInstance(parameters['oauth_nonce'], str) - self.assertEqual(oauth_client.client_key, - parameters['oauth_consumer_key']) + self.assertEqual( + oauth_client.client_key, parameters['oauth_consumer_key'] + ) if oauth_client.resource_owner_key: - self.assertEqual(oauth_client.resource_owner_key, - parameters['oauth_token'],) + self.assertEqual( + oauth_client.resource_owner_key, parameters['oauth_token'] + ) if oauth_client.verifier: - self.assertEqual(oauth_client.verifier, - parameters['oauth_verifier']) + self.assertEqual( + oauth_client.verifier, parameters['oauth_verifier'] + ) if oauth_client.callback_uri: - self.assertEqual(oauth_client.callback_uri, - parameters['oauth_callback']) + self.assertEqual( + oauth_client.callback_uri, parameters['oauth_callback'] + ) return parameters def test_oauth_authenticate_success(self): @@ -66,18 +74,22 @@ def test_oauth_authenticate_success(self): access_key = uuid.uuid4().hex access_secret = uuid.uuid4().hex - oauth_token = fixture.V3Token(methods=['oauth1'], - oauth_consumer_id=consumer_key, - oauth_access_token_id=access_key) + oauth_token = fixture.V3Token( + methods=['oauth1'], + oauth_consumer_id=consumer_key, + oauth_access_token_id=access_key, + ) oauth_token.set_project_scope() self.stub_auth(json=oauth_token) - a = ksa_oauth1.V3OAuth1(self.TEST_URL, - consumer_key=consumer_key, - consumer_secret=consumer_secret, - access_key=access_key, - access_secret=access_secret) + a = ksa_oauth1.V3OAuth1( + self.TEST_URL, + consumer_key=consumer_key, + consumer_secret=consumer_secret, + access_key=access_key, + access_secret=access_secret, + ) s = session.Session(auth=a) t = s.get_token() @@ -85,32 +97,32 @@ def test_oauth_authenticate_success(self): self.assertEqual(self.TEST_TOKEN, t) OAUTH_REQUEST_BODY = { - "auth": { - "identity": { - "methods": ["oauth1"], - "oauth1": {} - } - } + "auth": {"identity": {"methods": ["oauth1"], "oauth1": {}}} } self.assertRequestBodyIs(json=OAUTH_REQUEST_BODY) # Assert that the headers have the same oauthlib data req_headers = self.requests_mock.last_request.headers - oauth_client = oauth1.Client(consumer_key, - client_secret=consumer_secret, - resource_owner_key=access_key, - resource_owner_secret=access_secret, - signature_method=oauth1.SIGNATURE_HMAC) - self._validate_oauth_headers(req_headers['Authorization'], - oauth_client) + oauth_client = oauth1.Client( + consumer_key, + client_secret=consumer_secret, + resource_owner_key=access_key, + resource_owner_secret=access_secret, + signature_method=oauth1.SIGNATURE_HMAC, + ) + self._validate_oauth_headers( + req_headers['Authorization'], oauth_client + ) def test_warning_dual_scope(self): - ksa_oauth1.V3OAuth1(self.TEST_URL, - consumer_key=uuid.uuid4().hex, - consumer_secret=uuid.uuid4().hex, - access_key=uuid.uuid4().hex, - access_secret=uuid.uuid4().hex, - project_id=uuid.uuid4().hex) + ksa_oauth1.V3OAuth1( + self.TEST_URL, + consumer_key=uuid.uuid4().hex, + consumer_secret=uuid.uuid4().hex, + access_key=uuid.uuid4().hex, + access_secret=uuid.uuid4().hex, + project_id=uuid.uuid4().hex, + ) self.assertIn('ignored by the identity server', self.logger.output) diff --git a/keystoneauth1/tests/unit/extras/oauth1/test_oauth1_loading.py b/keystoneauth1/tests/unit/extras/oauth1/test_oauth1_loading.py index ef3ffc05..94402ece 100644 --- a/keystoneauth1/tests/unit/extras/oauth1/test_oauth1_loading.py +++ b/keystoneauth1/tests/unit/extras/oauth1/test_oauth1_loading.py @@ -17,9 +17,8 @@ class OAuth1LoadingTests(test_utils.TestCase): - def setUp(self): - super(OAuth1LoadingTests, self).setUp() + super().setUp() self.auth_url = uuid.uuid4().hex def create(self, **kwargs): @@ -33,10 +32,12 @@ def test_basic(self): consumer_key = uuid.uuid4().hex consumer_secret = uuid.uuid4().hex - p = self.create(access_key=access_key, - access_secret=access_secret, - consumer_key=consumer_key, - consumer_secret=consumer_secret) + p = self.create( + access_key=access_key, + access_secret=access_secret, + consumer_key=consumer_key, + consumer_secret=consumer_secret, + ) oauth_method = p.auth_methods[0] @@ -49,9 +50,13 @@ def test_basic(self): def test_options(self): options = loading.get_plugin_loader('v3oauth1').get_options() - self.assertEqual(set([o.name for o in options]), - set(['auth-url', - 'access-key', - 'access-secret', - 'consumer-key', - 'consumer-secret'])) + self.assertEqual( + {o.name for o in options}, + { + 'auth-url', + 'access-key', + 'access-secret', + 'consumer-key', + 'consumer-secret', + }, + ) diff --git a/keystoneauth1/tests/unit/extras/saml2/fixtures/__init__.py b/keystoneauth1/tests/unit/extras/saml2/fixtures/__init__.py index 59d87c0d..9ac88207 100644 --- a/keystoneauth1/tests/unit/extras/saml2/fixtures/__init__.py +++ b/keystoneauth1/tests/unit/extras/saml2/fixtures/__init__.py @@ -23,22 +23,25 @@ def template(f, **kwargs): def soap_response(**kwargs): kwargs.setdefault('provider', 'https://idp.testshib.org/idp/shibboleth') - kwargs.setdefault('consumer', - 'https://openstack4.local/Shibboleth.sso/SAML2/ECP') + kwargs.setdefault( + 'consumer', 'https://openstack4.local/Shibboleth.sso/SAML2/ECP' + ) kwargs.setdefault('issuer', 'https://openstack4.local/shibboleth') return template('soap_response.xml', **kwargs).encode('utf-8') def saml_assertion(**kwargs): kwargs.setdefault('issuer', 'https://idp.testshib.org/idp/shibboleth') - kwargs.setdefault('destination', - 'https://openstack4.local/Shibboleth.sso/SAML2/ECP') + kwargs.setdefault( + 'destination', 'https://openstack4.local/Shibboleth.sso/SAML2/ECP' + ) return template('saml_assertion.xml', **kwargs).encode('utf-8') def authn_request(**kwargs): - kwargs.setdefault('issuer', - 'https://openstack4.local/Shibboleth.sso/SAML2/ECP') + kwargs.setdefault( + 'issuer', 'https://openstack4.local/Shibboleth.sso/SAML2/ECP' + ) return template('authn_request.xml', **kwargs).encode('utf-8') @@ -56,19 +59,13 @@ def authn_request(**kwargs): "expires_at": "2014-06-09T10:48:59.643375Z", "user": { "OS-FEDERATION": { - "identity_provider": { - "id": "testshib" - }, - "protocol": { - "id": "saml2" - }, - "groups": [ - {"id": "1764fa5cf69a49a4918131de5ce4af9a"} - ] + "identity_provider": {"id": "testshib"}, + "protocol": {"id": "saml2"}, + "groups": [{"id": "1764fa5cf69a49a4918131de5ce4af9a"}], }, "id": "testhib%20user", - "name": "testhib user" - } + "name": "testhib user", + }, } } @@ -78,26 +75,22 @@ def authn_request(**kwargs): "domain_id": "37ef61", "enabled": 'true', "id": "12d706", - "links": { - "self": "http://identity:35357/v3/projects/12d706" - }, - "name": "a project name" + "links": {"self": "http://identity:35357/v3/projects/12d706"}, + "name": "a project name", }, { "domain_id": "37ef61", "enabled": 'true', "id": "9ca0eb", - "links": { - "self": "http://identity:35357/v3/projects/9ca0eb" - }, - "name": "another project" - } + "links": {"self": "http://identity:35357/v3/projects/9ca0eb"}, + "name": "another project", + }, ], "links": { "self": "http://identity:35357/v3/OS-FEDERATION/projects", "previous": 'null', - "next": 'null' - } + "next": 'null', + }, } DOMAINS = { @@ -106,15 +99,13 @@ def authn_request(**kwargs): "description": "desc of domain", "enabled": 'true', "id": "37ef61", - "links": { - "self": "http://identity:35357/v3/domains/37ef61" - }, - "name": "my domain" + "links": {"self": "http://identity:35357/v3/domains/37ef61"}, + "name": "my domain", } ], "links": { "self": "http://identity:35357/v3/OS-FEDERATION/domains", "previous": 'null', - "next": 'null' - } + "next": 'null', + }, } diff --git a/keystoneauth1/tests/unit/extras/saml2/test_auth_adfs.py b/keystoneauth1/tests/unit/extras/saml2/test_auth_adfs.py index 318e5353..13231a65 100644 --- a/keystoneauth1/tests/unit/extras/saml2/test_auth_adfs.py +++ b/keystoneauth1/tests/unit/extras/saml2/test_auth_adfs.py @@ -24,7 +24,6 @@ class AuthenticateviaADFSTests(utils.TestCase): - GROUP = 'auth' NAMESPACES = { @@ -33,24 +32,23 @@ class AuthenticateviaADFSTests(utils.TestCase): 'wsa': 'http://www.w3.org/2005/08/addressing', 'wsp': 'http://schemas.xmlsoap.org/ws/2004/09/policy', 'a': 'http://www.w3.org/2005/08/addressing', - 'o': ('http://docs.oasis-open.org/wss/2004/01/oasis' - '-200401-wss-wssecurity-secext-1.0.xsd') + 'o': ( + 'http://docs.oasis-open.org/wss/2004/01/oasis' + '-200401-wss-wssecurity-secext-1.0.xsd' + ), } - USER_XPATH = ('/s:Envelope/s:Header' - '/o:Security' - '/o:UsernameToken' - '/o:Username') - PASSWORD_XPATH = ('/s:Envelope/s:Header' - '/o:Security' - '/o:UsernameToken' - '/o:Password') - ADDRESS_XPATH = ('/s:Envelope/s:Body' - '/trust:RequestSecurityToken' - '/wsp:AppliesTo/wsa:EndpointReference' - '/wsa:Address') - TO_XPATH = ('/s:Envelope/s:Header' - '/a:To') + USER_XPATH = '/s:Envelope/s:Header/o:Security/o:UsernameToken/o:Username' + PASSWORD_XPATH = ( + '/s:Envelope/s:Header/o:Security/o:UsernameToken/o:Password' + ) + ADDRESS_XPATH = ( + '/s:Envelope/s:Body' + '/trust:RequestSecurityToken' + '/wsp:AppliesTo/wsa:EndpointReference' + '/wsa:Address' + ) + TO_XPATH = '/s:Envelope/s:Header/a:To' TEST_TOKEN = uuid.uuid4().hex @@ -61,24 +59,32 @@ def _uuid4(self): return '4b911420-4982-4009-8afc-5c596cd487f5' def setUp(self): - super(AuthenticateviaADFSTests, self).setUp() + super().setUp() self.IDENTITY_PROVIDER = 'adfs' - self.IDENTITY_PROVIDER_URL = ('http://adfs.local/adfs/service/trust/13' - '/usernamemixed') - self.FEDERATION_AUTH_URL = '%s/%s' % ( + self.IDENTITY_PROVIDER_URL = ( + 'http://adfs.local/adfs/service/trust/13/usernamemixed' + ) + self.FEDERATION_AUTH_URL = '{}/{}'.format( self.TEST_URL, - 'OS-FEDERATION/identity_providers/adfs/protocols/saml2/auth') + 'OS-FEDERATION/identity_providers/adfs/protocols/saml2/auth', + ) self.SP_ENDPOINT = 'https://openstack4.local/Shibboleth.sso/ADFS' self.SP_ENTITYID = 'https://openstack4.local' self.adfsplugin = saml2.V3ADFSPassword( - self.TEST_URL, self.IDENTITY_PROVIDER, - self.IDENTITY_PROVIDER_URL, self.SP_ENDPOINT, - self.TEST_USER, self.TEST_TOKEN, self.PROTOCOL) + self.TEST_URL, + self.IDENTITY_PROVIDER, + self.IDENTITY_PROVIDER_URL, + self.SP_ENDPOINT, + self.TEST_USER, + self.TEST_TOKEN, + self.PROTOCOL, + ) self.ADFS_SECURITY_TOKEN_RESPONSE = utils._load_xml( - 'ADFS_RequestSecurityTokenResponse.xml') + 'ADFS_RequestSecurityTokenResponse.xml' + ) self.ADFS_FAULT = utils._load_xml('ADFS_fault.xml') def test_get_adfs_security_token(self): @@ -86,7 +92,8 @@ def test_get_adfs_security_token(self): self.requests_mock.post( self.IDENTITY_PROVIDER_URL, content=utils.make_oneline(self.ADFS_SECURITY_TOKEN_RESPONSE), - status_code=200) + status_code=200, + ) self.adfsplugin._prepare_adfs_request() self.adfsplugin._get_adfs_security_token(self.session) @@ -94,59 +101,72 @@ def test_get_adfs_security_token(self): adfs_response = etree.tostring(self.adfsplugin.adfs_token) fixture_response = self.ADFS_SECURITY_TOKEN_RESPONSE - self.assertThat(fixture_response, - matchers.XMLEquals(adfs_response)) + self.assertThat(fixture_response, matchers.XMLEquals(adfs_response)) def test_adfs_request_user(self): self.adfsplugin._prepare_adfs_request() user = self.adfsplugin.prepared_request.xpath( - self.USER_XPATH, namespaces=self.NAMESPACES)[0] + self.USER_XPATH, namespaces=self.NAMESPACES + )[0] self.assertEqual(self.TEST_USER, user.text) def test_adfs_request_password(self): self.adfsplugin._prepare_adfs_request() password = self.adfsplugin.prepared_request.xpath( - self.PASSWORD_XPATH, namespaces=self.NAMESPACES)[0] + self.PASSWORD_XPATH, namespaces=self.NAMESPACES + )[0] self.assertEqual(self.TEST_TOKEN, password.text) def test_adfs_request_to(self): self.adfsplugin._prepare_adfs_request() to = self.adfsplugin.prepared_request.xpath( - self.TO_XPATH, namespaces=self.NAMESPACES)[0] + self.TO_XPATH, namespaces=self.NAMESPACES + )[0] self.assertEqual(self.IDENTITY_PROVIDER_URL, to.text) def test_prepare_adfs_request_address(self): self.adfsplugin._prepare_adfs_request() address = self.adfsplugin.prepared_request.xpath( - self.ADDRESS_XPATH, namespaces=self.NAMESPACES)[0] + self.ADDRESS_XPATH, namespaces=self.NAMESPACES + )[0] self.assertEqual(self.SP_ENDPOINT, address.text) def test_prepare_adfs_request_custom_endpointreference(self): self.adfsplugin = saml2.V3ADFSPassword( - self.TEST_URL, self.IDENTITY_PROVIDER, - self.IDENTITY_PROVIDER_URL, self.SP_ENDPOINT, - self.TEST_USER, self.TEST_TOKEN, self.PROTOCOL, self.SP_ENTITYID) + self.TEST_URL, + self.IDENTITY_PROVIDER, + self.IDENTITY_PROVIDER_URL, + self.SP_ENDPOINT, + self.TEST_USER, + self.TEST_TOKEN, + self.PROTOCOL, + self.SP_ENTITYID, + ) self.adfsplugin._prepare_adfs_request() address = self.adfsplugin.prepared_request.xpath( - self.ADDRESS_XPATH, namespaces=self.NAMESPACES)[0] + self.ADDRESS_XPATH, namespaces=self.NAMESPACES + )[0] self.assertEqual(self.SP_ENTITYID, address.text) def test_prepare_sp_request(self): assertion = etree.XML(self.ADFS_SECURITY_TOKEN_RESPONSE) assertion = assertion.xpath( saml2.V3ADFSPassword.ADFS_ASSERTION_XPATH, - namespaces=saml2.V3ADFSPassword.ADFS_TOKEN_NAMESPACES) + namespaces=saml2.V3ADFSPassword.ADFS_TOKEN_NAMESPACES, + ) assertion = assertion[0] assertion = etree.tostring(assertion) assertion = assertion.replace( b'http://docs.oasis-open.org/ws-sx/ws-trust/200512', - b'http://schemas.xmlsoap.org/ws/2005/02/trust') + b'http://schemas.xmlsoap.org/ws/2005/02/trust', + ) assertion = urllib.parse.quote(assertion) assertion = 'wa=wsignin1.0&wresult=' + assertion self.adfsplugin.adfs_token = etree.XML( - self.ADFS_SECURITY_TOKEN_RESPONSE) + self.ADFS_SECURITY_TOKEN_RESPONSE + ) self.adfsplugin._prepare_sp_request() self.assertEqual(assertion, self.adfsplugin.encoded_assertion) @@ -158,15 +178,19 @@ def test_get_adfs_security_token_authn_fail(self): error message from the XML message indicating where was the problem. """ content = utils.make_oneline(self.ADFS_FAULT) - self.requests_mock.register_uri('POST', - self.IDENTITY_PROVIDER_URL, - content=content, - status_code=500) + self.requests_mock.register_uri( + 'POST', + self.IDENTITY_PROVIDER_URL, + content=content, + status_code=500, + ) self.adfsplugin._prepare_adfs_request() - self.assertRaises(exceptions.AuthorizationFailure, - self.adfsplugin._get_adfs_security_token, - self.session) + self.assertRaises( + exceptions.AuthorizationFailure, + self.adfsplugin._get_adfs_security_token, + self.session, + ) # TODO(marek-denis): Python3 tests complain about missing 'message' # attributes # self.assertEqual('a:FailedAuthentication', e.message) @@ -178,14 +202,18 @@ def test_get_adfs_security_token_bad_response(self): and correctly raise exceptions.InternalServerError once it cannot parse XML fault message """ - self.requests_mock.register_uri('POST', - self.IDENTITY_PROVIDER_URL, - content=b'NOT XML', - status_code=500) + self.requests_mock.register_uri( + 'POST', + self.IDENTITY_PROVIDER_URL, + content=b'NOT XML', + status_code=500, + ) self.adfsplugin._prepare_adfs_request() - self.assertRaises(exceptions.InternalServerError, - self.adfsplugin._get_adfs_security_token, - self.session) + self.assertRaises( + exceptions.InternalServerError, + self.adfsplugin._get_adfs_security_token, + self.session, + ) # TODO(marek-denis): Need to figure out how to properly send cookies # from the request_mock methods. @@ -193,9 +221,9 @@ def _send_assertion_to_service_provider(self): """Test whether SP issues a cookie.""" cookie = uuid.uuid4().hex - self.requests_mock.post(self.SP_ENDPOINT, - headers={"set-cookie": cookie}, - status_code=302) + self.requests_mock.post( + self.SP_ENDPOINT, headers={"set-cookie": cookie}, status_code=302 + ) self.adfsplugin.adfs_token = self._build_adfs_request() self.adfsplugin._prepare_sp_request() @@ -204,55 +232,70 @@ def _send_assertion_to_service_provider(self): self.assertEqual(1, len(self.session.session.cookies)) def test_send_assertion_to_service_provider_bad_status(self): - self.requests_mock.register_uri('POST', self.SP_ENDPOINT, - status_code=500) + self.requests_mock.register_uri( + 'POST', self.SP_ENDPOINT, status_code=500 + ) self.adfsplugin.adfs_token = etree.XML( - self.ADFS_SECURITY_TOKEN_RESPONSE) + self.ADFS_SECURITY_TOKEN_RESPONSE + ) self.adfsplugin._prepare_sp_request() self.assertRaises( exceptions.InternalServerError, self.adfsplugin._send_assertion_to_service_provider, - self.session) + self.session, + ) def test_access_sp_no_cookies_fail(self): # clean cookie jar self.session.session.cookies = [] - self.assertRaises(exceptions.AuthorizationFailure, - self.adfsplugin._access_service_provider, - self.session) + self.assertRaises( + exceptions.AuthorizationFailure, + self.adfsplugin._access_service_provider, + self.session, + ) def test_check_valid_token_when_authenticated(self): self.requests_mock.register_uri( - 'GET', self.FEDERATION_AUTH_URL, + 'GET', + self.FEDERATION_AUTH_URL, json=saml2_fixtures.UNSCOPED_TOKEN, - headers=client_fixtures.AUTH_RESPONSE_HEADERS) + headers=client_fixtures.AUTH_RESPONSE_HEADERS, + ) self.session.session.cookies = [object()] self.adfsplugin._access_service_provider(self.session) response = self.adfsplugin.authenticated_response - self.assertEqual(client_fixtures.AUTH_RESPONSE_HEADERS, - response.headers) + self.assertEqual( + client_fixtures.AUTH_RESPONSE_HEADERS, response.headers + ) - self.assertEqual(saml2_fixtures.UNSCOPED_TOKEN['token'], - response.json()['token']) + self.assertEqual( + saml2_fixtures.UNSCOPED_TOKEN['token'], response.json()['token'] + ) def test_end_to_end_workflow(self): self.requests_mock.register_uri( - 'POST', self.IDENTITY_PROVIDER_URL, + 'POST', + self.IDENTITY_PROVIDER_URL, content=self.ADFS_SECURITY_TOKEN_RESPONSE, - status_code=200) + status_code=200, + ) self.requests_mock.register_uri( - 'POST', self.SP_ENDPOINT, + 'POST', + self.SP_ENDPOINT, headers={"set-cookie": 'x'}, - status_code=302) + status_code=302, + ) self.requests_mock.register_uri( - 'GET', self.FEDERATION_AUTH_URL, + 'GET', + self.FEDERATION_AUTH_URL, json=saml2_fixtures.UNSCOPED_TOKEN, - headers=client_fixtures.AUTH_RESPONSE_HEADERS) + headers=client_fixtures.AUTH_RESPONSE_HEADERS, + ) # NOTE(marek-denis): We need to mimic this until self.requests_mock can # issue cookies properly. diff --git a/keystoneauth1/tests/unit/extras/saml2/test_auth_saml2.py b/keystoneauth1/tests/unit/extras/saml2/test_auth_saml2.py index a1800a7f..fd542f3b 100644 --- a/keystoneauth1/tests/unit/extras/saml2/test_auth_saml2.py +++ b/keystoneauth1/tests/unit/extras/saml2/test_auth_saml2.py @@ -53,8 +53,8 @@ def calls(self): return [r.url.strip('/') for r in self.requests_mock.request_history] def basic_header(self, username=TEST_USER, password=TEST_PASS): - user_pass = ('%s:%s' % (username, password)).encode('utf-8') - return 'Basic %s' % base64.b64encode(user_pass).decode('utf-8') + user_pass = (f'{username}:{password}').encode() + return 'Basic {}'.format(base64.b64encode(user_pass).decode('utf-8')) def test_request_accept_headers(self): # Include some random Accept header @@ -70,18 +70,23 @@ def test_request_accept_headers(self): # added the PAOS_HEADER to it using the correct media type separator accept_header = plugin_headers['Accept'] self.assertIn(self.HEADER_MEDIA_TYPE_SEPARATOR, accept_header) - self.assertIn(random_header, - accept_header.split(self.HEADER_MEDIA_TYPE_SEPARATOR)) - self.assertIn(PAOS_HEADER, - accept_header.split(self.HEADER_MEDIA_TYPE_SEPARATOR)) + self.assertIn( + random_header, + accept_header.split(self.HEADER_MEDIA_TYPE_SEPARATOR), + ) + self.assertIn( + PAOS_HEADER, accept_header.split(self.HEADER_MEDIA_TYPE_SEPARATOR) + ) def test_passed_when_not_200(self): text = uuid.uuid4().hex test_url = 'http://another.test' - self.requests_mock.get(test_url, - status_code=201, - headers=CONTENT_TYPE_PAOS_HEADER, - text=text) + self.requests_mock.get( + test_url, + status_code=201, + headers=CONTENT_TYPE_PAOS_HEADER, + text=text, + ) resp = requests.get(test_url, auth=self.get_plugin()) self.assertEqual(201, resp.status_code) @@ -99,82 +104,115 @@ def test_200_without_paos_header(self): def test_standard_workflow_302_redirect(self): text = uuid.uuid4().hex - self.requests_mock.get(self.TEST_SP_URL, response_list=[ - dict(headers=CONTENT_TYPE_PAOS_HEADER, - content=utils.make_oneline(saml2_fixtures.SP_SOAP_RESPONSE)), - dict(text=text) - ]) - - authm = self.requests_mock.post(self.TEST_IDP_URL, - content=saml2_fixtures.SAML2_ASSERTION) + self.requests_mock.get( + self.TEST_SP_URL, + response_list=[ + { + 'headers': CONTENT_TYPE_PAOS_HEADER, + 'content': utils.make_oneline( + saml2_fixtures.SP_SOAP_RESPONSE + ), + }, + {'text': text}, + ], + ) + + authm = self.requests_mock.post( + self.TEST_IDP_URL, content=saml2_fixtures.SAML2_ASSERTION + ) self.requests_mock.post( self.TEST_CONSUMER_URL, status_code=302, - headers={'Location': self.TEST_SP_URL}) + headers={'Location': self.TEST_SP_URL}, + ) resp = requests.get(self.TEST_SP_URL, auth=self.get_plugin()) self.assertEqual(200, resp.status_code) self.assertEqual(text, resp.text) - self.assertEqual(self.calls, [self.TEST_SP_URL, - self.TEST_IDP_URL, - self.TEST_CONSUMER_URL, - self.TEST_SP_URL]) + self.assertEqual( + self.calls, + [ + self.TEST_SP_URL, + self.TEST_IDP_URL, + self.TEST_CONSUMER_URL, + self.TEST_SP_URL, + ], + ) - self.assertEqual(self.basic_header(), - authm.last_request.headers['Authorization']) + self.assertEqual( + self.basic_header(), authm.last_request.headers['Authorization'] + ) authn_request = self.requests_mock.request_history[1].text - self.assertThat(saml2_fixtures.AUTHN_REQUEST, - matchers.XMLEquals(authn_request)) + self.assertThat( + saml2_fixtures.AUTHN_REQUEST, matchers.XMLEquals(authn_request) + ) def test_standard_workflow_303_redirect(self): text = uuid.uuid4().hex - self.requests_mock.get(self.TEST_SP_URL, response_list=[ - dict(headers=CONTENT_TYPE_PAOS_HEADER, - content=utils.make_oneline(saml2_fixtures.SP_SOAP_RESPONSE)), - dict(text=text) - ]) - - authm = self.requests_mock.post(self.TEST_IDP_URL, - content=saml2_fixtures.SAML2_ASSERTION) + self.requests_mock.get( + self.TEST_SP_URL, + response_list=[ + { + 'headers': CONTENT_TYPE_PAOS_HEADER, + 'content': utils.make_oneline( + saml2_fixtures.SP_SOAP_RESPONSE + ), + }, + {'text': text}, + ], + ) + + authm = self.requests_mock.post( + self.TEST_IDP_URL, content=saml2_fixtures.SAML2_ASSERTION + ) self.requests_mock.post( self.TEST_CONSUMER_URL, status_code=303, - headers={'Location': self.TEST_SP_URL}) + headers={'Location': self.TEST_SP_URL}, + ) resp = requests.get(self.TEST_SP_URL, auth=self.get_plugin()) self.assertEqual(200, resp.status_code) self.assertEqual(text, resp.text) - url_flow = [self.TEST_SP_URL, - self.TEST_IDP_URL, - self.TEST_CONSUMER_URL, - self.TEST_SP_URL] + url_flow = [ + self.TEST_SP_URL, + self.TEST_IDP_URL, + self.TEST_CONSUMER_URL, + self.TEST_SP_URL, + ] self.assertEqual(url_flow, [r.url.rstrip('/') for r in resp.history]) self.assertEqual(url_flow, self.calls) - self.assertEqual(self.basic_header(), - authm.last_request.headers['Authorization']) + self.assertEqual( + self.basic_header(), authm.last_request.headers['Authorization'] + ) authn_request = self.requests_mock.request_history[1].text - self.assertThat(saml2_fixtures.AUTHN_REQUEST, - matchers.XMLEquals(authn_request)) + self.assertThat( + saml2_fixtures.AUTHN_REQUEST, matchers.XMLEquals(authn_request) + ) def test_initial_sp_call_invalid_response(self): """Send initial SP HTTP request and receive wrong server response.""" - self.requests_mock.get(self.TEST_SP_URL, - headers=CONTENT_TYPE_PAOS_HEADER, - text='NON XML RESPONSE') - - self.assertRaises(InvalidResponse, - requests.get, - self.TEST_SP_URL, - auth=self.get_plugin()) + self.requests_mock.get( + self.TEST_SP_URL, + headers=CONTENT_TYPE_PAOS_HEADER, + text='NON XML RESPONSE', + ) + + self.assertRaises( + InvalidResponse, + requests.get, + self.TEST_SP_URL, + auth=self.get_plugin(), + ) self.assertEqual(self.calls, [self.TEST_SP_URL]) @@ -184,25 +222,28 @@ def test_consumer_mismatch_error_workflow(self): soap_response = saml2_fixtures.soap_response(consumer=consumer1) saml_assertion = saml2_fixtures.saml_assertion(destination=consumer2) - self.requests_mock.get(self.TEST_SP_URL, - headers=CONTENT_TYPE_PAOS_HEADER, - content=soap_response) + self.requests_mock.get( + self.TEST_SP_URL, + headers=CONTENT_TYPE_PAOS_HEADER, + content=soap_response, + ) self.requests_mock.post(self.TEST_IDP_URL, content=saml_assertion) # receive the SAML error, body unchecked saml_error = self.requests_mock.post(consumer1) - self.assertRaises(saml2.v3.saml2.ConsumerMismatch, - requests.get, - self.TEST_SP_URL, - auth=self.get_plugin()) + self.assertRaises( + saml2.v3.saml2.ConsumerMismatch, + requests.get, + self.TEST_SP_URL, + auth=self.get_plugin(), + ) self.assertTrue(saml_error.called) class AuthenticateviaSAML2Tests(utils.TestCase): - TEST_USER = 'user' TEST_PASS = 'pass' TEST_IDP = 'tester' @@ -226,8 +267,10 @@ def sp_url(self, **kwargs): kwargs.setdefault('identity_provider', self.TEST_IDP) kwargs.setdefault('protocol', self.TEST_PROTOCOL) - templ = ('%(base)s/OS-FEDERATION/identity_providers/' - '%(identity_provider)s/protocols/%(protocol)s/auth') + templ = ( + '%(base)s/OS-FEDERATION/identity_providers/' + '%(identity_provider)s/protocols/%(protocol)s/auth' + ) return templ % kwargs @property @@ -235,11 +278,11 @@ def calls(self): return [r.url.strip('/') for r in self.requests_mock.request_history] def basic_header(self, username=TEST_USER, password=TEST_PASS): - user_pass = ('%s:%s' % (username, password)).encode('utf-8') - return 'Basic %s' % base64.b64encode(user_pass).decode('utf-8') + user_pass = (f'{username}:{password}').encode() + return 'Basic {}'.format(base64.b64encode(user_pass).decode('utf-8')) def setUp(self): - super(AuthenticateviaSAML2Tests, self).setUp() + super().setUp() self.session = session.Session() self.default_sp_url = self.sp_url() @@ -247,35 +290,51 @@ def test_workflow(self): token_id = uuid.uuid4().hex token = ksa_fixtures.V3Token() - self.requests_mock.get(self.default_sp_url, response_list=[ - dict(headers=CONTENT_TYPE_PAOS_HEADER, - content=utils.make_oneline(saml2_fixtures.SP_SOAP_RESPONSE)), - dict(headers={'X-Subject-Token': token_id}, json=token) - ]) - - authm = self.requests_mock.post(self.TEST_IDP_URL, - content=saml2_fixtures.SAML2_ASSERTION) + self.requests_mock.get( + self.default_sp_url, + response_list=[ + { + 'headers': CONTENT_TYPE_PAOS_HEADER, + 'content': utils.make_oneline( + saml2_fixtures.SP_SOAP_RESPONSE + ), + }, + {'headers': {'X-Subject-Token': token_id}, 'json': token}, + ], + ) + + authm = self.requests_mock.post( + self.TEST_IDP_URL, content=saml2_fixtures.SAML2_ASSERTION + ) self.requests_mock.post( self.TEST_CONSUMER_URL, status_code=302, - headers={'Location': self.sp_url()}) + headers={'Location': self.sp_url()}, + ) auth_ref = self.get_plugin().get_auth_ref(self.session) self.assertEqual(token_id, auth_ref.auth_token) - self.assertEqual(self.calls, [self.default_sp_url, - self.TEST_IDP_URL, - self.TEST_CONSUMER_URL, - self.default_sp_url]) + self.assertEqual( + self.calls, + [ + self.default_sp_url, + self.TEST_IDP_URL, + self.TEST_CONSUMER_URL, + self.default_sp_url, + ], + ) - self.assertEqual(self.basic_header(), - authm.last_request.headers['Authorization']) + self.assertEqual( + self.basic_header(), authm.last_request.headers['Authorization'] + ) authn_request = self.requests_mock.request_history[1].text - self.assertThat(saml2_fixtures.AUTHN_REQUEST, - matchers.XMLEquals(authn_request)) + self.assertThat( + saml2_fixtures.AUTHN_REQUEST, matchers.XMLEquals(authn_request) + ) def test_consumer_mismatch_error_workflow(self): consumer1 = 'http://keystone.test/Shibboleth.sso/SAML2/ECP' @@ -284,29 +343,37 @@ def test_consumer_mismatch_error_workflow(self): soap_response = saml2_fixtures.soap_response(consumer=consumer1) saml_assertion = saml2_fixtures.saml_assertion(destination=consumer2) - self.requests_mock.get(self.default_sp_url, - headers=CONTENT_TYPE_PAOS_HEADER, - content=soap_response) + self.requests_mock.get( + self.default_sp_url, + headers=CONTENT_TYPE_PAOS_HEADER, + content=soap_response, + ) self.requests_mock.post(self.TEST_IDP_URL, content=saml_assertion) # receive the SAML error, body unchecked saml_error = self.requests_mock.post(consumer1) - self.assertRaises(exceptions.AuthorizationFailure, - self.get_plugin().get_auth_ref, - self.session) + self.assertRaises( + exceptions.AuthorizationFailure, + self.get_plugin().get_auth_ref, + self.session, + ) self.assertTrue(saml_error.called) def test_initial_sp_call_invalid_response(self): """Send initial SP HTTP request and receive wrong server response.""" - self.requests_mock.get(self.default_sp_url, - headers=CONTENT_TYPE_PAOS_HEADER, - text='NON XML RESPONSE') - - self.assertRaises(exceptions.AuthorizationFailure, - self.get_plugin().get_auth_ref, - self.session) + self.requests_mock.get( + self.default_sp_url, + headers=CONTENT_TYPE_PAOS_HEADER, + text='NON XML RESPONSE', + ) + + self.assertRaises( + exceptions.AuthorizationFailure, + self.get_plugin().get_auth_ref, + self.session, + ) self.assertEqual(self.calls, [self.default_sp_url]) diff --git a/keystoneauth1/tests/unit/extras/saml2/utils.py b/keystoneauth1/tests/unit/extras/saml2/utils.py index d338c7eb..0d5a668b 100644 --- a/keystoneauth1/tests/unit/extras/saml2/utils.py +++ b/keystoneauth1/tests/unit/extras/saml2/utils.py @@ -31,9 +31,8 @@ def _load_xml(filename): class TestCase(utils.TestCase): - TEST_URL = 'https://keystone:5000/v3' def setUp(self): - super(TestCase, self).setUp() + super().setUp() self.session = session.Session() diff --git a/keystoneauth1/tests/unit/identity/test_access.py b/keystoneauth1/tests/unit/identity/test_access.py index 15eaba30..c521fd33 100644 --- a/keystoneauth1/tests/unit/identity/test_access.py +++ b/keystoneauth1/tests/unit/identity/test_access.py @@ -21,9 +21,8 @@ class AccessInfoPluginTests(utils.TestCase): - def setUp(self): - super(AccessInfoPluginTests, self).setUp() + super().setUp() self.session = session.Session() self.auth_token = uuid.uuid4().hex @@ -37,19 +36,22 @@ def _plugin(self, **kwargs): def test_auth_ref(self): plugin_obj = self._plugin() - self.assertEqual(self.TEST_ROOT_URL, - plugin_obj.get_endpoint(self.session, - service_type='identity', - interface='public')) + self.assertEqual( + self.TEST_ROOT_URL, + plugin_obj.get_endpoint( + self.session, service_type='identity', interface='public' + ), + ) self.assertEqual(self.auth_token, plugin_obj.get_token(session)) def test_auth_url(self): auth_url = 'http://keystone.test.url' obj = self._plugin(auth_url=auth_url) - self.assertEqual(auth_url, - obj.get_endpoint(self.session, - interface=plugin.AUTH_INTERFACE)) + self.assertEqual( + auth_url, + obj.get_endpoint(self.session, interface=plugin.AUTH_INTERFACE), + ) def test_invalidate(self): plugin = self._plugin() diff --git a/keystoneauth1/tests/unit/identity/test_identity_common.py b/keystoneauth1/tests/unit/identity/test_identity_common.py index ffd862bf..4a594b1f 100644 --- a/keystoneauth1/tests/unit/identity/test_identity_common.py +++ b/keystoneauth1/tests/unit/identity/test_identity_common.py @@ -27,15 +27,15 @@ from keystoneauth1.tests.unit import utils _Endpoints = collections.namedtuple( - 'ServiceVersion', - 'public, internal, admin') + 'ServiceVersion', 'public, internal, admin' +) _ServiceVersion = collections.namedtuple( - 'ServiceVersion', - 'discovery, service') + 'ServiceVersion', 'discovery, service' +) -class FakeServiceEndpoints(object): +class FakeServiceEndpoints: def __init__(self, base_url, versions=None, project_id=None, **kwargs): self.base_url = base_url self._interfaces = {} @@ -75,7 +75,6 @@ def _make_url(self, interface, *parts): class CommonIdentityTests(metaclass=abc.ABCMeta): - PROJECT_ID = uuid.uuid4().hex TEST_ROOT_URL = 'http://127.0.0.1:5000/' TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/' @@ -87,7 +86,9 @@ class CommonIdentityTests(metaclass=abc.ABCMeta): TEST_VOLUME = FakeServiceEndpoints( base_url='https://block-storage.example.com', - versions=['v3', 'v2'], project_id=PROJECT_ID) + versions=['v3', 'v2'], + project_id=PROJECT_ID, + ) TEST_BAREMETAL_BASE = 'https://baremetal.example.com' TEST_BAREMETAL_INTERNAL = TEST_BAREMETAL_BASE + '/internal' @@ -95,10 +96,10 @@ class CommonIdentityTests(metaclass=abc.ABCMeta): TEST_PASS = uuid.uuid4().hex def setUp(self): - super(CommonIdentityTests, self).setUp() + super().setUp() - self.TEST_URL = '%s%s' % (self.TEST_ROOT_URL, self.version) - self.TEST_ADMIN_URL = '%s%s' % (self.TEST_ROOT_ADMIN_URL, self.version) + self.TEST_URL = f'{self.TEST_ROOT_URL}{self.version}' + self.TEST_ADMIN_URL = f'{self.TEST_ROOT_ADMIN_URL}{self.version}' self.TEST_DISCOVERY = fixture.DiscoveryList(href=self.TEST_ROOT_URL) self.stub_auth_data() @@ -140,37 +141,46 @@ def test_discovering(self): disc.add_nova_microversion( href=self.TEST_COMPUTE_ADMIN, - id='v2.1', status='CURRENT', - min_version='2.1', version='2.38') + id='v2.1', + status='CURRENT', + min_version='2.1', + version='2.38', + ) - self.stub_url('GET', [], - base_url=self.TEST_COMPUTE_ADMIN, - json=disc) + self.stub_url('GET', [], base_url=self.TEST_COMPUTE_ADMIN, json=disc) body = 'SUCCESS' # which gives our sample values - self.stub_url('GET', ['path'], - text=body, base_url=self.TEST_COMPUTE_ADMIN) + self.stub_url( + 'GET', ['path'], text=body, base_url=self.TEST_COMPUTE_ADMIN + ) a = self.create_auth_plugin() s = session.Session(auth=a) - resp = s.get('/path', endpoint_filter={'service_type': 'compute', - 'interface': 'admin', - 'version': '2.1'}) + resp = s.get( + '/path', + endpoint_filter={ + 'service_type': 'compute', + 'interface': 'admin', + 'version': '2.1', + }, + ) self.assertEqual(200, resp.status_code) self.assertEqual(body, resp.text) new_body = 'SC SUCCESS' # if we don't specify a version, we use the URL from the SC - self.stub_url('GET', ['path'], - base_url=self.TEST_COMPUTE_ADMIN, - text=new_body) + self.stub_url( + 'GET', ['path'], base_url=self.TEST_COMPUTE_ADMIN, text=new_body + ) - resp = s.get('/path', endpoint_filter={'service_type': 'compute', - 'interface': 'admin'}) + resp = s.get( + '/path', + endpoint_filter={'service_type': 'compute', 'interface': 'admin'}, + ) self.assertEqual(200, resp.status_code) self.assertEqual(new_body, resp.text) @@ -180,8 +190,11 @@ def test_discovery_uses_provided_session_cache(self): disc.add_nova_microversion( href=self.TEST_COMPUTE_ADMIN, - id='v2.1', status='CURRENT', - min_version='2.1', version='2.38') + id='v2.1', + status='CURRENT', + min_version='2.1', + version='2.38', + ) # register responses such that if the discovery URL is hit more than # once then the response will be invalid and not point to COMPUTE_ADMIN @@ -189,8 +202,9 @@ def test_discovery_uses_provided_session_cache(self): self.requests_mock.get(self.TEST_COMPUTE_ADMIN, resps) body = 'SUCCESS' - self.stub_url('GET', ['path'], - text=body, base_url=self.TEST_COMPUTE_ADMIN) + self.stub_url( + 'GET', ['path'], text=body, base_url=self.TEST_COMPUTE_ADMIN + ) cache = {} # now either of the two plugins I use, it should not cause a second @@ -200,11 +214,15 @@ def test_discovery_uses_provided_session_cache(self): b = self.create_auth_plugin() for auth in (a, b): - resp = s.get('/path', - auth=auth, - endpoint_filter={'service_type': 'compute', - 'interface': 'admin', - 'version': '2.1'}) + resp = s.get( + '/path', + auth=auth, + endpoint_filter={ + 'service_type': 'compute', + 'interface': 'admin', + 'version': '2.1', + }, + ) self.assertEqual(200, resp.status_code) self.assertEqual(body, resp.text) @@ -215,8 +233,11 @@ def test_discovery_uses_session_cache(self): disc.add_nova_microversion( href=self.TEST_COMPUTE_ADMIN, - id='v2.1', status='CURRENT', - min_version='2.1', version='2.38') + id='v2.1', + status='CURRENT', + min_version='2.1', + version='2.38', + ) # register responses such that if the discovery URL is hit more than # once then the response will be invalid and not point to COMPUTE_ADMIN @@ -224,17 +245,21 @@ def test_discovery_uses_session_cache(self): self.requests_mock.get(self.TEST_COMPUTE_ADMIN, resps) body = 'SUCCESS' - self.stub_url('GET', ['path'], - base_url=self.TEST_COMPUTE_ADMIN, - text=body) + self.stub_url( + 'GET', ['path'], base_url=self.TEST_COMPUTE_ADMIN, text=body + ) - filter = {'service_type': 'compute', 'interface': 'admin', - 'version': '2.1'} + filter = { + 'service_type': 'compute', + 'interface': 'admin', + 'version': '2.1', + } # create a session and call the endpoint, causing its cache to be set sess = session.Session() - sess.get('/path', auth=self.create_auth_plugin(), - endpoint_filter=filter) + sess.get( + '/path', auth=self.create_auth_plugin(), endpoint_filter=filter + ) self.assertIn(self.TEST_COMPUTE_ADMIN, sess._discovery_cache.keys()) # now either of the two plugins I use, it should not cause a second @@ -252,8 +277,11 @@ def test_discovery_uses_plugin_cache(self): disc.add_nova_microversion( href=self.TEST_COMPUTE_ADMIN, - id='v2.1', status='CURRENT', - min_version='2.1', version='2.38') + id='v2.1', + status='CURRENT', + min_version='2.1', + version='2.38', + ) # register responses such that if the discovery URL is hit more than # once then the response will be invalid and not point to COMPUTE_ADMIN @@ -261,9 +289,9 @@ def test_discovery_uses_plugin_cache(self): self.requests_mock.get(self.TEST_COMPUTE_ADMIN, resps) body = 'SUCCESS' - self.stub_url('GET', ['path'], - base_url=self.TEST_COMPUTE_ADMIN, - text=body) + self.stub_url( + 'GET', ['path'], base_url=self.TEST_COMPUTE_ADMIN, text=body + ) # now either of the two sessions I use, it should not cause a second # request to the discovery url. Calling discovery directly should also @@ -273,11 +301,15 @@ def test_discovery_uses_plugin_cache(self): auth = self.create_auth_plugin() for sess in (sa, sb): - resp = sess.get('/path', - auth=auth, - endpoint_filter={'service_type': 'compute', - 'interface': 'admin', - 'version': '2.1'}) + resp = sess.get( + '/path', + auth=auth, + endpoint_filter={ + 'service_type': 'compute', + 'interface': 'admin', + 'version': '2.1', + }, + ) self.assertEqual(200, resp.status_code) self.assertEqual(body, resp.text) @@ -287,8 +319,11 @@ def test_discovery_uses_session_plugin_cache(self): disc.add_nova_microversion( href=self.TEST_COMPUTE_ADMIN, - id='v2.1', status='CURRENT', - min_version='2.1', version='2.38') + id='v2.1', + status='CURRENT', + min_version='2.1', + version='2.38', + ) # register responses such that if the discovery URL is hit more than # once then the response will be invalid and not point to COMPUTE_ADMIN @@ -296,12 +331,15 @@ def test_discovery_uses_session_plugin_cache(self): self.requests_mock.get(self.TEST_COMPUTE_ADMIN, resps) body = 'SUCCESS' - self.stub_url('GET', ['path'], - base_url=self.TEST_COMPUTE_ADMIN, - text=body) + self.stub_url( + 'GET', ['path'], base_url=self.TEST_COMPUTE_ADMIN, text=body + ) - filter = {'service_type': 'compute', 'interface': 'admin', - 'version': '2.1'} + filter = { + 'service_type': 'compute', + 'interface': 'admin', + 'version': '2.1', + } # create a plugin and call the endpoint, causing its cache to be set plugin = self.create_auth_plugin() @@ -330,9 +368,9 @@ def test_direct_discovery_provided_plugin_cache(self): expected_url = self.TEST_COMPUTE_ADMIN + '/v2.0' for sess in (sa, sb): - disc = discover.get_discovery( - sess, self.TEST_COMPUTE_ADMIN, cache=discovery_cache) + sess, self.TEST_COMPUTE_ADMIN, cache=discovery_cache + ) url = disc.url_for(('2', '0')) self.assertEqual(expected_url, url) @@ -344,10 +382,9 @@ def test_discovery_trailing_slash(self): # a slash or not. If the url is called a second time (meaning the cache # didn't work, we'll hit the 500 error. self.requests_mock.get( - 'https://example.com', [ - {'json': self.TEST_DISCOVERY}, - {'status_code': 500} - ]) + 'https://example.com', + [{'json': self.TEST_DISCOVERY}, {'status_code': 500}], + ) sess = session.Session() discovery_cache = {} @@ -356,7 +393,8 @@ def test_discovery_trailing_slash(self): for test_endpoint in ('https://example.com', 'https://example.com/'): disc = discover.get_discovery( - sess, test_endpoint, cache=discovery_cache) + sess, test_endpoint, cache=discovery_cache + ) url = disc.url_for(('2', '0')) self.assertEqual(expected_url, url) @@ -367,21 +405,31 @@ def test_discovery_trailing_slash(self): def test_discovering_with_no_data(self): # which returns discovery information pointing to TEST_URL but there is # no data there. - self.stub_url('GET', [], - base_url=self.TEST_COMPUTE_ADMIN, - status_code=400) + self.stub_url( + 'GET', [], base_url=self.TEST_COMPUTE_ADMIN, status_code=400 + ) # so the url that will be used is the same TEST_COMPUTE_ADMIN body = 'SUCCESS' - self.stub_url('GET', ['path'], base_url=self.TEST_COMPUTE_ADMIN, - text=body, status_code=200) + self.stub_url( + 'GET', + ['path'], + base_url=self.TEST_COMPUTE_ADMIN, + text=body, + status_code=200, + ) a = self.create_auth_plugin() s = session.Session(auth=a) - resp = s.get('/path', endpoint_filter={'service_type': 'compute', - 'interface': 'admin', - 'version': self.version}) + resp = s.get( + '/path', + endpoint_filter={ + 'service_type': 'compute', + 'interface': 'admin', + 'version': self.version, + }, + ) self.assertEqual(200, resp.status_code) self.assertEqual(body, resp.text) @@ -389,16 +437,20 @@ def test_discovering_with_no_data(self): def test_direct_discovering_with_no_data(self): # returns discovery information pointing to TEST_URL but there is # no data there. - self.stub_url('GET', [], - base_url=self.TEST_COMPUTE_ADMIN, - status_code=400) + self.stub_url( + 'GET', [], base_url=self.TEST_COMPUTE_ADMIN, status_code=400 + ) a = self.create_auth_plugin() s = session.Session(auth=a) # A direct call for discovery should fail - self.assertRaises(exceptions.BadRequest, - discover.get_discovery, s, self.TEST_COMPUTE_ADMIN) + self.assertRaises( + exceptions.BadRequest, + discover.get_discovery, + s, + self.TEST_COMPUTE_ADMIN, + ) def test_discovering_with_relative_link(self): # need to construct list this way for relative @@ -411,13 +463,13 @@ def test_discovering_with_relative_link(self): a = self.create_auth_plugin() s = session.Session(auth=a) - endpoint_v2 = s.get_endpoint(service_type='compute', - interface='admin', - version=(2, 0)) + endpoint_v2 = s.get_endpoint( + service_type='compute', interface='admin', version=(2, 0) + ) - endpoint_v3 = s.get_endpoint(service_type='compute', - interface='admin', - version=(3, 0)) + endpoint_v3 = s.get_endpoint( + service_type='compute', interface='admin', version=(3, 0) + ) self.assertEqual(self.TEST_COMPUTE_ADMIN + '/v2.0', endpoint_v2) self.assertEqual(self.TEST_COMPUTE_ADMIN + '/v3', endpoint_v3) @@ -435,8 +487,7 @@ def test_direct_discovering(self): a = self.create_auth_plugin() s = session.Session(auth=a) - catalog_url = s.get_endpoint( - service_type='compute', interface='admin') + catalog_url = s.get_endpoint(service_type='compute', interface='admin') disc = discover.get_discovery(s, catalog_url) url_v2 = disc.url_for(('2', '0')) @@ -453,7 +504,6 @@ def test_direct_discovering(self): self.assertEqual(v3_compute, url_v3) def test_discovering_version_no_discovery(self): - a = self.create_auth_plugin() s = session.Session(auth=a) @@ -461,11 +511,11 @@ def test_discovering_version_no_discovery(self): # This tests that it doesn't make a discovery call because we don't # have a reqquest mock, and this will throw an exception if it tries version = s.get_api_major_version( - service_type='volumev2', interface='admin') + service_type='volumev2', interface='admin' + ) self.assertEqual((2, 0), version) def test_discovering_version_with_discovery(self): - a = self.create_auth_plugin() s = session.Session(auth=a) @@ -480,11 +530,12 @@ def test_discovering_version_with_discovery(self): # This needs to do version discovery to find the version version = s.get_api_major_version( - service_type='compute', interface='admin') + service_type='compute', interface='admin' + ) self.assertEqual((3, 0), version) self.assertEqual( - self.requests_mock.request_history[-1].url, - self.TEST_COMPUTE_ADMIN) + self.requests_mock.request_history[-1].url, self.TEST_COMPUTE_ADMIN + ) def test_direct_discovering_with_relative_link(self): # need to construct list this way for relative @@ -497,8 +548,7 @@ def test_direct_discovering_with_relative_link(self): a = self.create_auth_plugin() s = session.Session(auth=a) - catalog_url = s.get_endpoint( - service_type='compute', interface='admin') + catalog_url = s.get_endpoint(service_type='compute', interface='admin') disc = discover.get_discovery(s, catalog_url) url_v2 = disc.url_for(('2', '0')) @@ -525,13 +575,13 @@ def test_discovering_with_relative_anchored_link(self): a = self.create_auth_plugin() s = session.Session(auth=a) - endpoint_v2 = s.get_endpoint(service_type='compute', - interface='admin', - version=(2, 0)) + endpoint_v2 = s.get_endpoint( + service_type='compute', interface='admin', version=(2, 0) + ) - endpoint_v3 = s.get_endpoint(service_type='compute', - interface='admin', - version=(3, 0)) + endpoint_v3 = s.get_endpoint( + service_type='compute', interface='admin', version=(3, 0) + ) # by the nature of urljoin a relative link with a /path gets joined # back to the root. @@ -540,7 +590,7 @@ def test_discovering_with_relative_anchored_link(self): def test_discovering_with_protocol_relative(self): # strip up to and including the : leaving //host/path - path = self.TEST_COMPUTE_ADMIN[self.TEST_COMPUTE_ADMIN.find(':') + 1:] + path = self.TEST_COMPUTE_ADMIN[self.TEST_COMPUTE_ADMIN.find(':') + 1 :] disc = fixture.DiscoveryList(v2=False, v3=False) disc.add_v2(path + '/v2.0') @@ -551,13 +601,13 @@ def test_discovering_with_protocol_relative(self): a = self.create_auth_plugin() s = session.Session(auth=a) - endpoint_v2 = s.get_endpoint(service_type='compute', - interface='admin', - version=(2, 0)) + endpoint_v2 = s.get_endpoint( + service_type='compute', interface='admin', version=(2, 0) + ) - endpoint_v3 = s.get_endpoint(service_type='compute', - interface='admin', - version=(3, 0)) + endpoint_v3 = s.get_endpoint( + service_type='compute', interface='admin', version=(3, 0) + ) # ensures that the http is carried over from the lookup url self.assertEqual(self.TEST_COMPUTE_ADMIN + '/v2.0', endpoint_v2) @@ -573,19 +623,19 @@ def test_discovering_when_version_missing(self): a = self.create_auth_plugin() s = session.Session(auth=a) - endpoint_v2 = s.get_endpoint(service_type='compute', - interface='admin', - version=(2, 0)) + endpoint_v2 = s.get_endpoint( + service_type='compute', interface='admin', version=(2, 0) + ) - endpoint_v3 = s.get_endpoint(service_type='compute', - interface='admin', - version=(3, 0)) + endpoint_v3 = s.get_endpoint( + service_type='compute', interface='admin', version=(3, 0) + ) self.assertEqual(self.TEST_COMPUTE_ADMIN + '/v2.0', endpoint_v2) self.assertIsNone(endpoint_v3) def test_endpoint_data_no_version(self): - path = self.TEST_COMPUTE_ADMIN[self.TEST_COMPUTE_ADMIN.find(':') + 1:] + path = self.TEST_COMPUTE_ADMIN[self.TEST_COMPUTE_ADMIN.find(':') + 1 :] disc = fixture.DiscoveryList(v2=False, v3=False) disc.add_v2(path + '/v2.0') @@ -595,450 +645,533 @@ def test_endpoint_data_no_version(self): a = self.create_auth_plugin() s = session.Session(auth=a) - data = a.get_endpoint_data(session=s, - service_type='compute', - interface='admin') + data = a.get_endpoint_data( + session=s, service_type='compute', interface='admin' + ) self.assertEqual(self.TEST_COMPUTE_ADMIN + '/v3', data.url) # We should have gotten the version from the URL self.assertEqual((3, 0), data.api_version) def test_get_all_version_data_all_interfaces(self): - for interface in ('public', 'internal', 'admin'): # The version discovery dict will not have a project_id disc = fixture.DiscoveryList(v2=False, v3=False) disc.add_nova_microversion( - href=getattr(self.TEST_VOLUME.versions['v3'].discovery, - interface), - id='v3.0', status='CURRENT', - min_version='3.0', version='3.20') + href=getattr( + self.TEST_VOLUME.versions['v3'].discovery, interface + ), + id='v3.0', + status='CURRENT', + min_version='3.0', + version='3.20', + ) # Adding a v2 version to a service named volumev3 is not # an error. The service itself is cinder and has more than # one major version. disc.add_nova_microversion( - href=getattr(self.TEST_VOLUME.versions['v2'].discovery, - interface), - id='v2.0', status='SUPPORTED') + href=getattr( + self.TEST_VOLUME.versions['v2'].discovery, interface + ), + id='v2.0', + status='SUPPORTED', + ) self.stub_url( - 'GET', [], - base_url=getattr(self.TEST_VOLUME.unversioned, - interface) + '/', - json=disc) + 'GET', + [], + base_url=getattr(self.TEST_VOLUME.unversioned, interface) + + '/', + json=disc, + ) for url in ( - self.TEST_COMPUTE_PUBLIC, - self.TEST_COMPUTE_INTERNAL, - self.TEST_COMPUTE_ADMIN): - + self.TEST_COMPUTE_PUBLIC, + self.TEST_COMPUTE_INTERNAL, + self.TEST_COMPUTE_ADMIN, + ): disc = fixture.DiscoveryList(v2=False, v3=False) + disc.add_microversion(href=url, id='v2') disc.add_microversion( - href=url, id='v2') - disc.add_microversion( - href=url, id='v2.1', - min_version='2.1', max_version='2.35') + href=url, id='v2.1', min_version='2.1', max_version='2.35' + ) self.stub_url('GET', [], base_url=url, json=disc) a = self.create_auth_plugin() s = session.Session(auth=a) - identity_endpoint = 'http://127.0.0.1:35357/{}/'.format(self.version) + identity_endpoint = f'http://127.0.0.1:35357/{self.version}/' data = s.get_all_version_data(interface=None) - self.assertEqual({ - 'RegionOne': { - 'admin': { - 'block-storage': [{ - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'SUPPORTED', - 'status': 'SUPPORTED', - 'url': 'https://block-storage.example.com/admin/v2', - 'version': '2.0' - }, { - 'collection': None, - 'max_microversion': '3.20', - 'min_microversion': '3.0', - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'CURRENT', - 'status': 'CURRENT', - 'url': 'https://block-storage.example.com/admin/v3', - 'version': '3.0' - }], - 'compute': [{ - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'stable', - 'status': 'CURRENT', - 'url': 'https://compute.example.com/nova/admin', - 'version': '2.0' - }, { - 'collection': None, - 'max_microversion': '2.35', - 'min_microversion': '2.1', - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'stable', - 'status': 'CURRENT', - 'url': 'https://compute.example.com/nova/admin', - 'version': '2.1'}], - 'identity': [{ - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'raw_status': None, - 'status': 'CURRENT', - 'url': identity_endpoint, - 'version': self.discovery_version, - }] - }, - 'internal': { - 'baremetal': [{ - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'raw_status': None, - 'status': 'CURRENT', - 'url': 'https://baremetal.example.com/internal/', - 'version': None - }], - 'block-storage': [{ - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'SUPPORTED', - 'status': 'SUPPORTED', - 'url': 'https://block-storage.example.com/internal/v2', - 'version': '2.0' - }, { - 'collection': None, - 'max_microversion': '3.20', - 'min_microversion': '3.0', - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'CURRENT', - 'status': 'CURRENT', - 'url': 'https://block-storage.example.com/internal/v3', - 'version': '3.0' - }], - 'compute': [{ - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'stable', - 'status': 'CURRENT', - 'url': 'https://compute.example.com/nova/internal', - 'version': '2.0' - }, { - 'collection': None, - 'max_microversion': '2.35', - 'min_microversion': '2.1', - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'stable', - 'status': 'CURRENT', - 'url': 'https://compute.example.com/nova/internal', - 'version': '2.1' - }] - }, - 'public': { - 'block-storage': [{ - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'SUPPORTED', - 'status': 'SUPPORTED', - 'url': 'https://block-storage.example.com/public/v2', - 'version': '2.0' - }, { - 'collection': None, - 'max_microversion': '3.20', - 'min_microversion': '3.0', - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'CURRENT', - 'status': 'CURRENT', - 'url': 'https://block-storage.example.com/public/v3', - 'version': '3.0' - }], - 'compute': [{ - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'stable', - 'status': 'CURRENT', - 'url': 'https://compute.example.com/nova/public', - 'version': '2.0' - }, { - 'collection': None, - 'max_microversion': '2.35', - 'min_microversion': '2.1', - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'stable', - 'status': 'CURRENT', - 'url': 'https://compute.example.com/nova/public', - 'version': '2.1', - }] + self.assertEqual( + { + 'RegionOne': { + 'admin': { + 'block-storage': [ + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'SUPPORTED', + 'status': 'SUPPORTED', + 'url': 'https://block-storage.example.com/admin/v2', + 'version': '2.0', + }, + { + 'collection': None, + 'max_microversion': '3.20', + 'min_microversion': '3.0', + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'CURRENT', + 'status': 'CURRENT', + 'url': 'https://block-storage.example.com/admin/v3', + 'version': '3.0', + }, + ], + 'compute': [ + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'stable', + 'status': 'CURRENT', + 'url': 'https://compute.example.com/nova/admin', + 'version': '2.0', + }, + { + 'collection': None, + 'max_microversion': '2.35', + 'min_microversion': '2.1', + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'stable', + 'status': 'CURRENT', + 'url': 'https://compute.example.com/nova/admin', + 'version': '2.1', + }, + ], + 'identity': [ + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'raw_status': None, + 'status': 'CURRENT', + 'url': identity_endpoint, + 'version': self.discovery_version, + } + ], + }, + 'internal': { + 'baremetal': [ + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'raw_status': None, + 'status': 'CURRENT', + 'url': 'https://baremetal.example.com/internal/', + 'version': None, + } + ], + 'block-storage': [ + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'SUPPORTED', + 'status': 'SUPPORTED', + 'url': 'https://block-storage.example.com/internal/v2', + 'version': '2.0', + }, + { + 'collection': None, + 'max_microversion': '3.20', + 'min_microversion': '3.0', + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'CURRENT', + 'status': 'CURRENT', + 'url': 'https://block-storage.example.com/internal/v3', + 'version': '3.0', + }, + ], + 'compute': [ + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'stable', + 'status': 'CURRENT', + 'url': 'https://compute.example.com/nova/internal', + 'version': '2.0', + }, + { + 'collection': None, + 'max_microversion': '2.35', + 'min_microversion': '2.1', + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'stable', + 'status': 'CURRENT', + 'url': 'https://compute.example.com/nova/internal', + 'version': '2.1', + }, + ], + }, + 'public': { + 'block-storage': [ + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'SUPPORTED', + 'status': 'SUPPORTED', + 'url': 'https://block-storage.example.com/public/v2', + 'version': '2.0', + }, + { + 'collection': None, + 'max_microversion': '3.20', + 'min_microversion': '3.0', + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'CURRENT', + 'status': 'CURRENT', + 'url': 'https://block-storage.example.com/public/v3', + 'version': '3.0', + }, + ], + 'compute': [ + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'stable', + 'status': 'CURRENT', + 'url': 'https://compute.example.com/nova/public', + 'version': '2.0', + }, + { + 'collection': None, + 'max_microversion': '2.35', + 'min_microversion': '2.1', + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'stable', + 'status': 'CURRENT', + 'url': 'https://compute.example.com/nova/public', + 'version': '2.1', + }, + ], + }, } - } - }, data) + }, + data, + ) def test_get_all_version_data(self): - cinder_disc = fixture.DiscoveryList(v2=False, v3=False) # The version discovery dict will not have a project_id cinder_disc.add_nova_microversion( href=self.TEST_VOLUME.versions['v3'].discovery.public, - id='v3.0', status='CURRENT', - min_version='3.0', version='3.20') + id='v3.0', + status='CURRENT', + min_version='3.0', + version='3.20', + ) # Adding a v2 version to a service named volumev3 is not # an error. The service itself is cinder and has more than # one major version. cinder_disc.add_nova_microversion( href=self.TEST_VOLUME.versions['v2'].discovery.public, - id='v2.0', status='SUPPORTED') + id='v2.0', + status='SUPPORTED', + ) self.stub_url( - 'GET', [], + 'GET', + [], base_url=self.TEST_VOLUME.unversioned.public + '/', - json=cinder_disc) + json=cinder_disc, + ) nova_disc = fixture.DiscoveryList(v2=False, v3=False) + nova_disc.add_microversion(href=self.TEST_COMPUTE_PUBLIC, id='v2') nova_disc.add_microversion( - href=self.TEST_COMPUTE_PUBLIC, id='v2') - nova_disc.add_microversion( - href=self.TEST_COMPUTE_PUBLIC, id='v2.1', - min_version='2.1', max_version='2.35') + href=self.TEST_COMPUTE_PUBLIC, + id='v2.1', + min_version='2.1', + max_version='2.35', + ) self.stub_url( - 'GET', [], base_url=self.TEST_COMPUTE_PUBLIC, json=nova_disc) + 'GET', [], base_url=self.TEST_COMPUTE_PUBLIC, json=nova_disc + ) a = self.create_auth_plugin() s = session.Session(auth=a) data = s.get_all_version_data(interface='public') - self.assertEqual({ - 'RegionOne': { - 'public': { - 'block-storage': [{ - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'SUPPORTED', - 'status': 'SUPPORTED', - 'url': 'https://block-storage.example.com/public/v2', - 'version': '2.0' - }, { - 'collection': None, - 'max_microversion': '3.20', - 'min_microversion': '3.0', - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'CURRENT', - 'status': 'CURRENT', - 'url': 'https://block-storage.example.com/public/v3', - 'version': '3.0' - }], - 'compute': [{ - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'stable', - 'status': 'CURRENT', - 'url': 'https://compute.example.com/nova/public', - 'version': '2.0' - }, { - 'collection': None, - 'max_microversion': '2.35', - 'min_microversion': '2.1', - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'stable', - 'status': 'CURRENT', - 'url': 'https://compute.example.com/nova/public', - 'version': '2.1' - }], + self.assertEqual( + { + 'RegionOne': { + 'public': { + 'block-storage': [ + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'SUPPORTED', + 'status': 'SUPPORTED', + 'url': 'https://block-storage.example.com/public/v2', + 'version': '2.0', + }, + { + 'collection': None, + 'max_microversion': '3.20', + 'min_microversion': '3.0', + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'CURRENT', + 'status': 'CURRENT', + 'url': 'https://block-storage.example.com/public/v3', + 'version': '3.0', + }, + ], + 'compute': [ + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'stable', + 'status': 'CURRENT', + 'url': 'https://compute.example.com/nova/public', + 'version': '2.0', + }, + { + 'collection': None, + 'max_microversion': '2.35', + 'min_microversion': '2.1', + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'stable', + 'status': 'CURRENT', + 'url': 'https://compute.example.com/nova/public', + 'version': '2.1', + }, + ], + } } - } - }, data) + }, + data, + ) def test_get_all_version_data_by_service_type(self): nova_disc = fixture.DiscoveryList(v2=False, v3=False) + nova_disc.add_microversion(href=self.TEST_COMPUTE_PUBLIC, id='v2') nova_disc.add_microversion( - href=self.TEST_COMPUTE_PUBLIC, id='v2') - nova_disc.add_microversion( - href=self.TEST_COMPUTE_PUBLIC, id='v2.1', - min_version='2.1', max_version='2.35') + href=self.TEST_COMPUTE_PUBLIC, + id='v2.1', + min_version='2.1', + max_version='2.35', + ) self.stub_url( - 'GET', [], base_url=self.TEST_COMPUTE_PUBLIC, json=nova_disc) + 'GET', [], base_url=self.TEST_COMPUTE_PUBLIC, json=nova_disc + ) a = self.create_auth_plugin() s = session.Session(auth=a) data = s.get_all_version_data( - interface='public', - service_type='compute') - self.assertEqual({ - 'RegionOne': { - 'public': { - 'compute': [{ - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'stable', - 'status': 'CURRENT', - 'url': 'https://compute.example.com/nova/public', - 'version': '2.0' - }, { - 'collection': None, - 'max_microversion': '2.35', - 'min_microversion': '2.1', - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'stable', - 'status': 'CURRENT', - 'url': 'https://compute.example.com/nova/public', - 'version': '2.1' - }], + interface='public', service_type='compute' + ) + self.assertEqual( + { + 'RegionOne': { + 'public': { + 'compute': [ + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'stable', + 'status': 'CURRENT', + 'url': 'https://compute.example.com/nova/public', + 'version': '2.0', + }, + { + 'collection': None, + 'max_microversion': '2.35', + 'min_microversion': '2.1', + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'stable', + 'status': 'CURRENT', + 'url': 'https://compute.example.com/nova/public', + 'version': '2.1', + }, + ] + } } - } - }, data) + }, + data, + ) def test_get_all_version_data_adapter(self): nova_disc = fixture.DiscoveryList(v2=False, v3=False) + nova_disc.add_microversion(href=self.TEST_COMPUTE_PUBLIC, id='v2') nova_disc.add_microversion( - href=self.TEST_COMPUTE_PUBLIC, id='v2') - nova_disc.add_microversion( - href=self.TEST_COMPUTE_PUBLIC, id='v2.1', - min_version='2.1', max_version='2.35') + href=self.TEST_COMPUTE_PUBLIC, + id='v2.1', + min_version='2.1', + max_version='2.35', + ) self.stub_url( - 'GET', [], base_url=self.TEST_COMPUTE_PUBLIC, json=nova_disc) + 'GET', [], base_url=self.TEST_COMPUTE_PUBLIC, json=nova_disc + ) s = session.Session(auth=self.create_auth_plugin()) a = adapter.Adapter(session=s, service_type='compute') data = a.get_all_version_data() - self.assertEqual({ - 'RegionOne': { - 'public': { - 'compute': [{ - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'stable', - 'status': 'CURRENT', - 'url': 'https://compute.example.com/nova/public', - 'version': '2.0' - }, { - 'collection': None, - 'max_microversion': '2.35', - 'min_microversion': '2.1', - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'stable', - 'status': 'CURRENT', - 'url': 'https://compute.example.com/nova/public', - 'version': '2.1' - }], + self.assertEqual( + { + 'RegionOne': { + 'public': { + 'compute': [ + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'stable', + 'status': 'CURRENT', + 'url': 'https://compute.example.com/nova/public', + 'version': '2.0', + }, + { + 'collection': None, + 'max_microversion': '2.35', + 'min_microversion': '2.1', + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'stable', + 'status': 'CURRENT', + 'url': 'https://compute.example.com/nova/public', + 'version': '2.1', + }, + ] + } } - } - }, data) + }, + data, + ) def test_get_all_version_data_service_alias(self): - cinder_disc = fixture.DiscoveryList(v2=False, v3=False) # The version discovery dict will not have a project_id cinder_disc.add_nova_microversion( href=self.TEST_VOLUME.versions['v3'].discovery.public, - id='v3.0', status='CURRENT', - min_version='3.0', version='3.20') + id='v3.0', + status='CURRENT', + min_version='3.0', + version='3.20', + ) # Adding a v2 version to a service named volumev3 is not # an error. The service itself is cinder and has more than # one major version. cinder_disc.add_nova_microversion( href=self.TEST_VOLUME.versions['v2'].discovery.public, - id='v2.0', status='SUPPORTED') + id='v2.0', + status='SUPPORTED', + ) self.stub_url( - 'GET', [], + 'GET', + [], base_url=self.TEST_VOLUME.unversioned.public + '/', - json=cinder_disc) + json=cinder_disc, + ) a = self.create_auth_plugin() s = session.Session(auth=a) data = s.get_all_version_data( - interface='public', - service_type='block-store') - self.assertEqual({ - 'RegionOne': { - 'public': { - 'block-storage': [{ - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'SUPPORTED', - 'status': 'SUPPORTED', - 'url': 'https://block-storage.example.com/public/v2', - 'version': '2.0' - }, { - 'collection': None, - 'max_microversion': '3.20', - 'min_microversion': '3.0', - 'next_min_version': None, - 'not_before': None, - 'raw_status': 'CURRENT', - 'status': 'CURRENT', - 'url': 'https://block-storage.example.com/public/v3', - 'version': '3.0' - }], + interface='public', service_type='block-store' + ) + self.assertEqual( + { + 'RegionOne': { + 'public': { + 'block-storage': [ + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'SUPPORTED', + 'status': 'SUPPORTED', + 'url': 'https://block-storage.example.com/public/v2', + 'version': '2.0', + }, + { + 'collection': None, + 'max_microversion': '3.20', + 'min_microversion': '3.0', + 'next_min_version': None, + 'not_before': None, + 'raw_status': 'CURRENT', + 'status': 'CURRENT', + 'url': 'https://block-storage.example.com/public/v3', + 'version': '3.0', + }, + ] + } } - } - }, data) + }, + data, + ) def test_endpoint_data_no_version_no_discovery(self): a = self.create_auth_plugin() s = session.Session(auth=a) - data = a.get_endpoint_data(session=s, - service_type='compute', - interface='admin', - discover_versions=False) + data = a.get_endpoint_data( + session=s, + service_type='compute', + interface='admin', + discover_versions=False, + ) self.assertEqual(self.TEST_COMPUTE_ADMIN, data.url) # There's no version in the URL and no document - we have no idea @@ -1048,13 +1181,16 @@ def test_endpoint_data_version_url_no_discovery(self): a = self.create_auth_plugin() s = session.Session(auth=a) - data = a.get_endpoint_data(session=s, - service_type='volumev3', - interface='admin', - discover_versions=False) + data = a.get_endpoint_data( + session=s, + service_type='volumev3', + interface='admin', + discover_versions=False, + ) self.assertEqual( - self.TEST_VOLUME.versions['v3'].service.admin, data.url) + self.TEST_VOLUME.versions['v3'].service.admin, data.url + ) # There's v3 in the URL self.assertEqual((3, 0), data.api_version) @@ -1062,9 +1198,9 @@ def test_endpoint_no_version(self): a = self.create_auth_plugin() s = session.Session(auth=a) - data = a.get_endpoint(session=s, - service_type='compute', - interface='admin') + data = a.get_endpoint( + session=s, service_type='compute', interface='admin' + ) self.assertEqual(self.TEST_COMPUTE_ADMIN, data) @@ -1079,16 +1215,20 @@ def test_endpoint_data_relative_version(self): a = self.create_auth_plugin() s = session.Session(auth=a) - data_v2 = a.get_endpoint_data(session=s, - service_type='compute', - interface='admin', - min_version=(2, 0), - max_version=(2, discover.LATEST)) - data_v3 = a.get_endpoint_data(session=s, - service_type='compute', - interface='admin', - min_version=(3, 0), - max_version=(3, discover.LATEST)) + data_v2 = a.get_endpoint_data( + session=s, + service_type='compute', + interface='admin', + min_version=(2, 0), + max_version=(2, discover.LATEST), + ) + data_v3 = a.get_endpoint_data( + session=s, + service_type='compute', + interface='admin', + min_version=(3, 0), + max_version=(3, discover.LATEST), + ) self.assertEqual(self.TEST_COMPUTE_ADMIN + '/v2.0', data_v2.url) self.assertEqual(self.TEST_COMPUTE_ADMIN + '/v3', data_v3.url) @@ -1110,27 +1250,30 @@ def test_get_versioned_data(self): a = self.create_auth_plugin() s = session.Session(auth=a) - data = a.get_endpoint_data(session=s, - service_type='compute', - interface='admin') + data = a.get_endpoint_data( + session=s, service_type='compute', interface='admin' + ) self.assertEqual(v3_compute, data.url) - v2_data = data.get_versioned_data(s, min_version='2.0', - max_version='2.latest') + v2_data = data.get_versioned_data( + s, min_version='2.0', max_version='2.latest' + ) self.assertEqual(v2_compute, v2_data.url) self.assertEqual(v2_compute, v2_data.service_url) self.assertEqual(self.TEST_COMPUTE_ADMIN, v2_data.catalog_url) # Variants that all return v3 data - for vkwargs in (dict(min_version='3.0', max_version='3.latest'), - # min/max spans major versions - dict(min_version='2.0', max_version='3.latest'), - # latest major max - dict(min_version='2.0', max_version='latest'), - # implicit max - dict(min_version='2.0'), - # implicit min/max - dict()): + for vkwargs in ( + {'min_version': '3.0', 'max_version': '3.latest'}, + # min/max spans major versions + {'min_version': '2.0', 'max_version': '3.latest'}, + # latest major max + {'min_version': '2.0', 'max_version': 'latest'}, + # implicit max + {'min_version': '2.0'}, + # implicit min/max + {}, + ): v3_data = data.get_versioned_data(s, **vkwargs) self.assertEqual(v3_compute, v3_data.url) self.assertEqual(v3_compute, v3_data.service_url) @@ -1153,9 +1296,9 @@ def test_get_current_versioned_data(self): a = self.create_auth_plugin() s = session.Session(auth=a) - data = a.get_endpoint_data(session=s, - service_type='compute', - interface='admin') + data = a.get_endpoint_data( + session=s, service_type='compute', interface='admin' + ) self.assertEqual(v3_compute, data.url) v3_data = data.get_current_versioned_data(s) @@ -1168,120 +1311,147 @@ def test_get_current_versioned_data(self): self.assertIsNone(v3_data.max_microversion) def test_interface_list(self): - a = self.create_auth_plugin() s = session.Session(auth=a) - ep = s.get_endpoint(service_type='baremetal', - interface=['internal', 'public']) + ep = s.get_endpoint( + service_type='baremetal', interface=['internal', 'public'] + ) self.assertEqual(ep, self.TEST_BAREMETAL_INTERNAL) - ep = s.get_endpoint(service_type='baremetal', - interface=['public', 'internal']) + ep = s.get_endpoint( + service_type='baremetal', interface=['public', 'internal'] + ) self.assertEqual(ep, self.TEST_BAREMETAL_INTERNAL) - ep = s.get_endpoint(service_type='compute', - interface=['internal', 'public']) + ep = s.get_endpoint( + service_type='compute', interface=['internal', 'public'] + ) self.assertEqual(ep, self.TEST_COMPUTE_INTERNAL) - ep = s.get_endpoint(service_type='compute', - interface=['public', 'internal']) + ep = s.get_endpoint( + service_type='compute', interface=['public', 'internal'] + ) self.assertEqual(ep, self.TEST_COMPUTE_PUBLIC) def test_get_versioned_data_volume_project_id(self): - disc = fixture.DiscoveryList(v2=False, v3=False) # The version discovery dict will not have a project_id disc.add_nova_microversion( href=self.TEST_VOLUME.versions['v3'].discovery.public, - id='v3.0', status='CURRENT', - min_version='3.0', version='3.20') + id='v3.0', + status='CURRENT', + min_version='3.0', + version='3.20', + ) # Adding a v2 version to a service named volumev3 is not # an error. The service itself is cinder and has more than # one major version. disc.add_nova_microversion( href=self.TEST_VOLUME.versions['v2'].discovery.public, - id='v2.0', status='SUPPORTED') + id='v2.0', + status='SUPPORTED', + ) a = self.create_auth_plugin() s = session.Session(auth=a) # volume endpoint ends in v3, we should not make an API call - endpoint = a.get_endpoint(session=s, - service_type='volumev3', - interface='public', - version='3.0') + endpoint = a.get_endpoint( + session=s, + service_type='volumev3', + interface='public', + version='3.0', + ) self.assertEqual(self.TEST_VOLUME.catalog.public, endpoint) resps = [{'json': disc}, {'status_code': 500}] # We should only try to fetch the versioned discovery url once self.requests_mock.get( - self.TEST_VOLUME.versions['v3'].discovery.public + '/', resps) + self.TEST_VOLUME.versions['v3'].discovery.public + '/', resps + ) - data = a.get_endpoint_data(session=s, - service_type='volumev3', - interface='public') - self.assertEqual(self.TEST_VOLUME.versions['v3'].service.public, - data.url) + data = a.get_endpoint_data( + session=s, service_type='volumev3', interface='public' + ) + self.assertEqual( + self.TEST_VOLUME.versions['v3'].service.public, data.url + ) v3_data = data.get_versioned_data( - s, min_version='3.0', max_version='3.latest', - project_id=self.project_id) + s, + min_version='3.0', + max_version='3.latest', + project_id=self.project_id, + ) - self.assertEqual(self.TEST_VOLUME.versions['v3'].service.public, - v3_data.url) + self.assertEqual( + self.TEST_VOLUME.versions['v3'].service.public, v3_data.url + ) self.assertEqual(self.TEST_VOLUME.catalog.public, v3_data.catalog_url) self.assertEqual((3, 0), v3_data.min_microversion) self.assertEqual((3, 20), v3_data.max_microversion) - self.assertEqual(self.TEST_VOLUME.versions['v3'].service.public, - v3_data.service_url) + self.assertEqual( + self.TEST_VOLUME.versions['v3'].service.public, v3_data.service_url + ) # Because of the v3 optimization before, requesting v2 should now go # find the unversioned endpoint self.requests_mock.get(self.TEST_VOLUME.unversioned.public, resps) v2_data = data.get_versioned_data( - s, min_version='2.0', max_version='2.latest', - project_id=self.project_id) + s, + min_version='2.0', + max_version='2.latest', + project_id=self.project_id, + ) # Even though we never requested volumev2 from the catalog, we should # wind up re-constructing it via version discovery and re-appending # the project_id to the URL - self.assertEqual(self.TEST_VOLUME.versions['v2'].service.public, - v2_data.url) - self.assertEqual(self.TEST_VOLUME.versions['v2'].service.public, - v2_data.service_url) + self.assertEqual( + self.TEST_VOLUME.versions['v2'].service.public, v2_data.url + ) + self.assertEqual( + self.TEST_VOLUME.versions['v2'].service.public, v2_data.service_url + ) self.assertEqual(self.TEST_VOLUME.catalog.public, v2_data.catalog_url) self.assertIsNone(v2_data.min_microversion) self.assertIsNone(v2_data.max_microversion) def test_get_versioned_data_volume_project_id_unversioned_first(self): - disc = fixture.DiscoveryList(v2=False, v3=False) # The version discovery dict will not have a project_id disc.add_nova_microversion( href=self.TEST_VOLUME.versions['v3'].discovery.public, - id='v3.0', status='CURRENT', - min_version='3.0', version='3.20') + id='v3.0', + status='CURRENT', + min_version='3.0', + version='3.20', + ) # Adding a v2 version to a service named volumev3 is not # an error. The service itself is cinder and has more than # one major version. disc.add_nova_microversion( href=self.TEST_VOLUME.versions['v2'].discovery.public, - id='v2.0', status='SUPPORTED') + id='v2.0', + status='SUPPORTED', + ) a = self.create_auth_plugin() s = session.Session(auth=a) # cinder endpoint ends in v3, we should not make an API call - endpoint = a.get_endpoint(session=s, - service_type='volumev3', - interface='public', - version='3.0') + endpoint = a.get_endpoint( + session=s, + service_type='volumev3', + interface='public', + version='3.0', + ) self.assertEqual(self.TEST_VOLUME.catalog.public, endpoint) resps = [{'json': disc}, {'status_code': 500}] @@ -1290,23 +1460,28 @@ def test_get_versioned_data_volume_project_id_unversioned_first(self): # Because the catalog has the versioned endpoint but we constructed # an unversioned endpoint, the url needs to have a trailing / self.requests_mock.get( - self.TEST_VOLUME.unversioned.public + '/', resps) + self.TEST_VOLUME.unversioned.public + '/', resps + ) # Fetch v2.0 first - since that doesn't match endpoint optimization, # it should fetch the unversioned endpoint - v2_data = s.get_endpoint_data(service_type='block-storage', - interface='public', - min_version='2.0', - max_version='2.latest', - project_id=self.project_id) + v2_data = s.get_endpoint_data( + service_type='block-storage', + interface='public', + min_version='2.0', + max_version='2.latest', + project_id=self.project_id, + ) # Even though we never requested volumev2 from the catalog, we should # wind up re-constructing it via version discovery and re-appending # the project_id to the URL - self.assertEqual(self.TEST_VOLUME.versions['v2'].service.public, - v2_data.url) - self.assertEqual(self.TEST_VOLUME.versions['v2'].service.public, - v2_data.service_url) + self.assertEqual( + self.TEST_VOLUME.versions['v2'].service.public, v2_data.url + ) + self.assertEqual( + self.TEST_VOLUME.versions['v2'].service.public, v2_data.service_url + ) self.assertEqual(self.TEST_VOLUME.catalog.public, v2_data.catalog_url) self.assertIsNone(v2_data.min_microversion) self.assertIsNone(v2_data.max_microversion) @@ -1315,26 +1490,33 @@ def test_get_versioned_data_volume_project_id_unversioned_first(self): # request for v2, we should have all the relevant data cached in the # discovery object - and should not fetch anything new. v3_data = v2_data.get_versioned_data( - s, min_version='3.0', max_version='3.latest', - project_id=self.project_id) + s, + min_version='3.0', + max_version='3.latest', + project_id=self.project_id, + ) - self.assertEqual(self.TEST_VOLUME.versions['v3'].service.public, - v3_data.url) + self.assertEqual( + self.TEST_VOLUME.versions['v3'].service.public, v3_data.url + ) self.assertEqual(self.TEST_VOLUME.catalog.public, v3_data.catalog_url) self.assertEqual((3, 0), v3_data.min_microversion) self.assertEqual((3, 20), v3_data.max_microversion) - self.assertEqual(self.TEST_VOLUME.versions['v3'].service.public, - v3_data.service_url) + self.assertEqual( + self.TEST_VOLUME.versions['v3'].service.public, v3_data.service_url + ) def test_trailing_slash_on_computed_endpoint(self): - disc = fixture.DiscoveryList(v2=False, v3=False) # A versioned URL in the Catalog disc.add_nova_microversion( href=self.TEST_VOLUME.versions['v3'].discovery.public, - id='v3.0', status='CURRENT', - min_version='3.0', version='3.20') + id='v3.0', + status='CURRENT', + min_version='3.0', + version='3.20', + ) a = self.create_auth_plugin() s = session.Session(auth=a) @@ -1343,29 +1525,35 @@ def test_trailing_slash_on_computed_endpoint(self): # Because the catalog has the versioned endpoint but we constructed # an unversioned endpoint, the url needs to have a trailing / self.requests_mock.get( - self.TEST_VOLUME.unversioned.public + '/', json=disc) + self.TEST_VOLUME.unversioned.public + '/', json=disc + ) # We're requesting version 2 of block-storage to make sure we # trigger the logic constructing the unversioned endpoint from the # versioned endpoint in the catalog - s.get_endpoint_data(service_type='block-storage', - interface='public', - min_version='2.0', - max_version='2.latest', - project_id=self.project_id) + s.get_endpoint_data( + service_type='block-storage', + interface='public', + min_version='2.0', + max_version='2.latest', + project_id=self.project_id, + ) self.assertTrue( - self.requests_mock.request_history[-1].url.endswith('/')) + self.requests_mock.request_history[-1].url.endswith('/') + ) def test_no_trailing_slash_on_catalog_endpoint(self): - disc = fixture.DiscoveryList(v2=False, v3=False) # A versioned URL in the Catalog disc.add_nova_microversion( href=self.TEST_COMPUTE_PUBLIC, - id='v2.1', status='CURRENT', - min_version='2.1', version='2.38') + id='v2.1', + status='CURRENT', + min_version='2.1', + version='2.38', + ) a = self.create_auth_plugin() s = session.Session(auth=a) @@ -1374,32 +1562,39 @@ def test_no_trailing_slash_on_catalog_endpoint(self): # modify it. self.requests_mock.get(self.TEST_COMPUTE_PUBLIC, json=disc) - s.get_endpoint_data(service_type='compute', - interface='public', - min_version='2.1', - max_version='2.latest') + s.get_endpoint_data( + service_type='compute', + interface='public', + min_version='2.1', + max_version='2.latest', + ) self.assertFalse( - self.requests_mock.request_history[-1].url.endswith('/')) + self.requests_mock.request_history[-1].url.endswith('/') + ) def test_broken_discovery_endpoint(self): - # Discovery document with a bogus/broken base URL disc = fixture.DiscoveryList(v2=False, v3=False) disc.add_nova_microversion( href='http://internal.example.com', - id='v2.1', status='CURRENT', - min_version='2.1', version='2.38') + id='v2.1', + status='CURRENT', + min_version='2.1', + version='2.38', + ) a = self.create_auth_plugin() s = session.Session(auth=a) self.requests_mock.get(self.TEST_COMPUTE_PUBLIC, json=disc) - data = s.get_endpoint_data(service_type='compute', - interface='public', - min_version='2.1', - max_version='2.latest') + data = s.get_endpoint_data( + service_type='compute', + interface='public', + min_version='2.1', + max_version='2.latest', + ) # Verify that we get the versioned url based on the catalog url self.assertTrue(data.url, self.TEST_COMPUTE_PUBLIC + '/v2.1') @@ -1408,8 +1603,9 @@ def test_asking_for_auth_endpoint_ignores_checks(self): a = self.create_auth_plugin() s = session.Session(auth=a) - auth_url = s.get_endpoint(service_type='compute', - interface=plugin.AUTH_INTERFACE) + auth_url = s.get_endpoint( + service_type='compute', interface=plugin.AUTH_INTERFACE + ) self.assertEqual(self.TEST_URL, auth_url) @@ -1538,11 +1734,11 @@ def test_pathless_url(self): # Run with a project_id to ensure that path is covered self.assertEqual( - 3, len(list(data._get_discovery_url_choices(project_id='42')))) + 3, len(list(data._get_discovery_url_choices(project_id='42'))) + ) class V3(CommonIdentityTests, utils.TestCase): - @property def version(self): return 'v3' @@ -1560,24 +1756,28 @@ def get_auth_data(self, **kwargs): svc.add_standard_endpoints(admin=self.TEST_ADMIN_URL, region=region) svc = token.add_service('compute') - svc.add_standard_endpoints(admin=self.TEST_COMPUTE_ADMIN, - public=self.TEST_COMPUTE_PUBLIC, - internal=self.TEST_COMPUTE_INTERNAL, - region=region) + svc.add_standard_endpoints( + admin=self.TEST_COMPUTE_ADMIN, + public=self.TEST_COMPUTE_PUBLIC, + internal=self.TEST_COMPUTE_INTERNAL, + region=region, + ) svc = token.add_service('volumev2') svc.add_standard_endpoints( admin=self.TEST_VOLUME.versions['v2'].service.admin, public=self.TEST_VOLUME.versions['v2'].service.public, internal=self.TEST_VOLUME.versions['v2'].service.internal, - region=region) + region=region, + ) svc = token.add_service('volumev3') svc.add_standard_endpoints( admin=self.TEST_VOLUME.versions['v3'].service.admin, public=self.TEST_VOLUME.versions['v3'].service.public, internal=self.TEST_VOLUME.versions['v3'].service.internal, - region=region) + region=region, + ) # Add block-storage as a versioned endpoint so that we can test # versioned to unversioned inference. @@ -1586,12 +1786,13 @@ def get_auth_data(self, **kwargs): admin=self.TEST_VOLUME.versions['v3'].service.admin, public=self.TEST_VOLUME.versions['v3'].service.public, internal=self.TEST_VOLUME.versions['v3'].service.internal, - region=region) + region=region, + ) svc = token.add_service('baremetal') svc.add_standard_endpoints( - internal=self.TEST_BAREMETAL_INTERNAL, - region=region) + internal=self.TEST_BAREMETAL_INTERNAL, region=region + ) return token @@ -1610,7 +1811,6 @@ def create_auth_plugin(self, **kwargs): class V2(CommonIdentityTests, utils.TestCase): - @property def version(self): return 'v2.0' @@ -1642,28 +1842,36 @@ def get_auth_data(self, **kwargs): region = 'RegionOne' svc = token.add_service('identity') - svc.add_endpoint(admin=self.TEST_ADMIN_URL, region=region, - public=None, internal=None) + svc.add_endpoint( + admin=self.TEST_ADMIN_URL, + region=region, + public=None, + internal=None, + ) svc = token.add_service('compute') - svc.add_endpoint(public=self.TEST_COMPUTE_PUBLIC, - internal=self.TEST_COMPUTE_INTERNAL, - admin=self.TEST_COMPUTE_ADMIN, - region=region) + svc.add_endpoint( + public=self.TEST_COMPUTE_PUBLIC, + internal=self.TEST_COMPUTE_INTERNAL, + admin=self.TEST_COMPUTE_ADMIN, + region=region, + ) svc = token.add_service('volumev2') svc.add_endpoint( admin=self.TEST_VOLUME.versions['v2'].service.admin, public=self.TEST_VOLUME.versions['v2'].service.public, internal=self.TEST_VOLUME.versions['v2'].service.internal, - region=region) + region=region, + ) svc = token.add_service('volumev3') svc.add_endpoint( admin=self.TEST_VOLUME.versions['v3'].service.admin, public=self.TEST_VOLUME.versions['v3'].service.public, internal=self.TEST_VOLUME.versions['v3'].service.internal, - region=region) + region=region, + ) # Add block-storage as a versioned endpoint so that we can test # versioned to unversioned inferance. @@ -1672,13 +1880,16 @@ def get_auth_data(self, **kwargs): admin=self.TEST_VOLUME.versions['v3'].service.admin, public=self.TEST_VOLUME.versions['v3'].service.public, internal=self.TEST_VOLUME.versions['v3'].service.internal, - region=region) + region=region, + ) svc = token.add_service('baremetal') svc.add_endpoint( - public=None, admin=None, + public=None, + admin=None, internal=self.TEST_BAREMETAL_INTERNAL, - region=region) + region=region, + ) return token @@ -1687,7 +1898,6 @@ def stub_auth(self, **kwargs): class CatalogHackTests(utils.TestCase): - TEST_URL = 'http://keystone.server:5000/v2.0' OTHER_URL = 'http://other.server:5000/path' @@ -1701,58 +1911,49 @@ class CatalogHackTests(utils.TestCase): def test_getting_endpoints(self): disc = fixture.DiscoveryList(href=self.BASE_URL) - self.stub_url('GET', - ['/'], - base_url=self.BASE_URL, - json=disc) + self.stub_url('GET', ['/'], base_url=self.BASE_URL, json=disc) token = fixture.V2Token() service = token.add_service(self.IDENTITY) - service.add_endpoint(public=self.V2_URL, - admin=self.V2_URL, - internal=self.V2_URL) + service.add_endpoint( + public=self.V2_URL, admin=self.V2_URL, internal=self.V2_URL + ) - self.stub_url('POST', - ['tokens'], - base_url=self.V2_URL, - json=token) + self.stub_url('POST', ['tokens'], base_url=self.V2_URL, json=token) - v2_auth = identity.V2Password(self.V2_URL, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex) + v2_auth = identity.V2Password( + self.V2_URL, username=uuid.uuid4().hex, password=uuid.uuid4().hex + ) sess = session.Session(auth=v2_auth) - endpoint = sess.get_endpoint(service_type=self.IDENTITY, - interface='public', - version=(3, 0)) + endpoint = sess.get_endpoint( + service_type=self.IDENTITY, interface='public', version=(3, 0) + ) self.assertEqual(self.V3_URL, endpoint) def test_returns_original_when_discover_fails(self): token = fixture.V2Token() service = token.add_service(self.IDENTITY) - service.add_endpoint(public=self.V2_URL, - admin=self.V2_URL, - internal=self.V2_URL) + service.add_endpoint( + public=self.V2_URL, admin=self.V2_URL, internal=self.V2_URL + ) - self.stub_url('POST', - ['tokens'], - base_url=self.V2_URL, - json=token) + self.stub_url('POST', ['tokens'], base_url=self.V2_URL, json=token) self.stub_url('GET', [], base_url=self.BASE_URL, status_code=404) self.stub_url('GET', [], base_url=self.V2_URL, status_code=404) - v2_auth = identity.V2Password(self.V2_URL, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex) + v2_auth = identity.V2Password( + self.V2_URL, username=uuid.uuid4().hex, password=uuid.uuid4().hex + ) sess = session.Session(auth=v2_auth) - endpoint = sess.get_endpoint(service_type=self.IDENTITY, - interface='public', - version=(3, 0)) + endpoint = sess.get_endpoint( + service_type=self.IDENTITY, interface='public', version=(3, 0) + ) self.assertEqual(self.V2_URL, endpoint) @@ -1761,10 +1962,7 @@ def test_getting_endpoints_project_id_and_trailing_slash_in_disc_url(self): # session but only the v2 endpoint with a trailing slash in the # catalog, we can still discover the v3 endpoint. disc = fixture.DiscoveryList(href=self.BASE_URL) - self.stub_url('GET', - ['/'], - base_url=self.BASE_URL, - json=disc) + self.stub_url('GET', ['/'], base_url=self.BASE_URL, json=disc) # Create a project-scoped token. This will exercise the flow in the # discovery URL sequence where a project ID exists in the token but @@ -1778,103 +1976,106 @@ def test_getting_endpoints_project_id_and_trailing_slash_in_disc_url(self): # Auth with v3 kwargs = {'headers': {'X-Subject-Token': self.TEST_TOKEN}} - self.stub_url('POST', - ['auth', 'tokens'], - base_url=self.V3_URL, - json=token, **kwargs) - v3_auth = identity.V3Password(self.V3_URL, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex) + self.stub_url( + 'POST', + ['auth', 'tokens'], + base_url=self.V3_URL, + json=token, + **kwargs, + ) + v3_auth = identity.V3Password( + self.V3_URL, username=uuid.uuid4().hex, password=uuid.uuid4().hex + ) sess = session.Session(auth=v3_auth) # Try to get a v3 endpoint - endpoint = sess.get_endpoint(service_type=self.IDENTITY, - interface='public', - version=(3, 0)) + endpoint = sess.get_endpoint( + service_type=self.IDENTITY, interface='public', version=(3, 0) + ) self.assertEqual(self.V3_URL, endpoint) def test_returns_original_skipping_discovery(self): token = fixture.V2Token() service = token.add_service(self.IDENTITY) - service.add_endpoint(public=self.V2_URL, - admin=self.V2_URL, - internal=self.V2_URL) + service.add_endpoint( + public=self.V2_URL, admin=self.V2_URL, internal=self.V2_URL + ) - self.stub_url('POST', - ['tokens'], - base_url=self.V2_URL, - json=token) + self.stub_url('POST', ['tokens'], base_url=self.V2_URL, json=token) - v2_auth = identity.V2Password(self.V2_URL, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex) + v2_auth = identity.V2Password( + self.V2_URL, username=uuid.uuid4().hex, password=uuid.uuid4().hex + ) sess = session.Session(auth=v2_auth) - endpoint = sess.get_endpoint(service_type=self.IDENTITY, - interface='public', - skip_discovery=True, - version=(3, 0)) + endpoint = sess.get_endpoint( + service_type=self.IDENTITY, + interface='public', + skip_discovery=True, + version=(3, 0), + ) self.assertEqual(self.V2_URL, endpoint) def test_endpoint_override_skips_discovery(self): token = fixture.V2Token() service = token.add_service(self.IDENTITY) - service.add_endpoint(public=self.V2_URL, - admin=self.V2_URL, - internal=self.V2_URL) + service.add_endpoint( + public=self.V2_URL, admin=self.V2_URL, internal=self.V2_URL + ) - self.stub_url('POST', - ['tokens'], - base_url=self.V2_URL, - json=token) + self.stub_url('POST', ['tokens'], base_url=self.V2_URL, json=token) - v2_auth = identity.V2Password(self.V2_URL, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex) + v2_auth = identity.V2Password( + self.V2_URL, username=uuid.uuid4().hex, password=uuid.uuid4().hex + ) sess = session.Session(auth=v2_auth) - endpoint = sess.get_endpoint(endpoint_override=self.OTHER_URL, - service_type=self.IDENTITY, - interface='public', - version=(3, 0)) + endpoint = sess.get_endpoint( + endpoint_override=self.OTHER_URL, + service_type=self.IDENTITY, + interface='public', + version=(3, 0), + ) self.assertEqual(self.OTHER_URL, endpoint) def test_endpoint_override_data_runs_discovery(self): common_disc = fixture.DiscoveryList(v2=False, v3=False) - common_disc.add_microversion(href=self.OTHER_URL, id='v2.1', - min_version='2.1', max_version='2.35') + common_disc.add_microversion( + href=self.OTHER_URL, + id='v2.1', + min_version='2.1', + max_version='2.35', + ) - common_m = self.stub_url('GET', - base_url=self.OTHER_URL, - status_code=200, - json=common_disc) + common_m = self.stub_url( + 'GET', base_url=self.OTHER_URL, status_code=200, json=common_disc + ) token = fixture.V2Token() service = token.add_service(self.IDENTITY) - service.add_endpoint(public=self.V2_URL, - admin=self.V2_URL, - internal=self.V2_URL) + service.add_endpoint( + public=self.V2_URL, admin=self.V2_URL, internal=self.V2_URL + ) - self.stub_url('POST', - ['tokens'], - base_url=self.V2_URL, - json=token) + self.stub_url('POST', ['tokens'], base_url=self.V2_URL, json=token) - v2_auth = identity.V2Password(self.V2_URL, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex) + v2_auth = identity.V2Password( + self.V2_URL, username=uuid.uuid4().hex, password=uuid.uuid4().hex + ) sess = session.Session(auth=v2_auth) - data = sess.get_endpoint_data(endpoint_override=self.OTHER_URL, - service_type=self.IDENTITY, - interface='public', - min_version=(2, 0), - max_version=(2, discover.LATEST)) + data = sess.get_endpoint_data( + endpoint_override=self.OTHER_URL, + service_type=self.IDENTITY, + interface='public', + min_version=(2, 0), + max_version=(2, discover.LATEST), + ) self.assertTrue(common_m.called) self.assertEqual(self.OTHER_URL, data.service_url) @@ -1888,32 +2089,33 @@ def test_forcing_discovery(self): v2_disc = fixture.V2Discovery(self.V2_URL) common_disc = fixture.DiscoveryList(href=self.BASE_URL) - v2_m = self.stub_url('GET', - ['v2.0'], - base_url=self.BASE_URL, - status_code=200, - json={'version': v2_disc}) + v2_m = self.stub_url( + 'GET', + ['v2.0'], + base_url=self.BASE_URL, + status_code=200, + json={'version': v2_disc}, + ) - common_m = self.stub_url('GET', - [], - base_url=self.BASE_URL, - status_code=300, - json=common_disc) + common_m = self.stub_url( + 'GET', + [], + base_url=self.BASE_URL, + status_code=300, + json=common_disc, + ) token = fixture.V2Token() service = token.add_service(self.IDENTITY) - service.add_endpoint(public=self.V2_URL, - admin=self.V2_URL, - internal=self.V2_URL) + service.add_endpoint( + public=self.V2_URL, admin=self.V2_URL, internal=self.V2_URL + ) - self.stub_url('POST', - ['tokens'], - base_url=self.V2_URL, - json=token) + self.stub_url('POST', ['tokens'], base_url=self.V2_URL, json=token) - v2_auth = identity.V2Password(self.V2_URL, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex) + v2_auth = identity.V2Password( + self.V2_URL, username=uuid.uuid4().hex, password=uuid.uuid4().hex + ) sess = session.Session(auth=v2_auth) @@ -1921,8 +2123,9 @@ def test_forcing_discovery(self): self.assertFalse(v2_m.called) self.assertFalse(common_m.called) - data = sess.get_endpoint_data(service_type=self.IDENTITY, - discover_versions=True) + data = sess.get_endpoint_data( + service_type=self.IDENTITY, discover_versions=True + ) # We should get the v2 document, but not the unversioned self.assertTrue(v2_m.called) @@ -1941,34 +2144,34 @@ def test_forcing_discovery_list_returns_url(self): # by "return the latest" rules, that we get the info of the url from # the catalog if we don't provide a version but do provide # discover_versions - v2_m = self.stub_url('GET', - ['v2.0'], - base_url=self.BASE_URL, - status_code=200, - json=common_disc) + v2_m = self.stub_url( + 'GET', + ['v2.0'], + base_url=self.BASE_URL, + status_code=200, + json=common_disc, + ) token = fixture.V2Token() service = token.add_service(self.IDENTITY) - service.add_endpoint(public=self.V2_URL, - admin=self.V2_URL, - internal=self.V2_URL) + service.add_endpoint( + public=self.V2_URL, admin=self.V2_URL, internal=self.V2_URL + ) - self.stub_url('POST', - ['tokens'], - base_url=self.V2_URL, - json=token) + self.stub_url('POST', ['tokens'], base_url=self.V2_URL, json=token) - v2_auth = identity.V2Password(self.V2_URL, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex) + v2_auth = identity.V2Password( + self.V2_URL, username=uuid.uuid4().hex, password=uuid.uuid4().hex + ) sess = session.Session(auth=v2_auth) # v2 auth with v2 url doesn't make any discovery calls. self.assertFalse(v2_m.called) - data = sess.get_endpoint_data(service_type=self.IDENTITY, - discover_versions=True) + data = sess.get_endpoint_data( + service_type=self.IDENTITY, discover_versions=True + ) # We should make the one call self.assertTrue(v2_m.called) @@ -1982,33 +2185,30 @@ def test_latest_version_gets_latest_version(self): # 2.0 doesn't usually return a list. But we're testing version matching # rules, so it's nice to ensure that we don't fallback to something - v2_m = self.stub_url('GET', - base_url=self.BASE_URL, - status_code=200, - json=common_disc) + v2_m = self.stub_url( + 'GET', base_url=self.BASE_URL, status_code=200, json=common_disc + ) token = fixture.V2Token() service = token.add_service(self.IDENTITY) - service.add_endpoint(public=self.V2_URL, - admin=self.V2_URL, - internal=self.V2_URL) + service.add_endpoint( + public=self.V2_URL, admin=self.V2_URL, internal=self.V2_URL + ) - self.stub_url('POST', - ['tokens'], - base_url=self.V2_URL, - json=token) + self.stub_url('POST', ['tokens'], base_url=self.V2_URL, json=token) - v2_auth = identity.V2Password(self.V2_URL, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex) + v2_auth = identity.V2Password( + self.V2_URL, username=uuid.uuid4().hex, password=uuid.uuid4().hex + ) sess = session.Session(auth=v2_auth) # v2 auth with v2 url doesn't make any discovery calls. self.assertFalse(v2_m.called) - endpoint = sess.get_endpoint(service_type=self.IDENTITY, - version='latest') + endpoint = sess.get_endpoint( + service_type=self.IDENTITY, version='latest' + ) # We should make the one call self.assertTrue(v2_m.called) @@ -2017,60 +2217,71 @@ def test_latest_version_gets_latest_version(self): self.assertEqual(self.V3_URL, endpoint) # Make sure latest logic works for min and max version - endpoint = sess.get_endpoint(service_type=self.IDENTITY, - max_version='latest') + endpoint = sess.get_endpoint( + service_type=self.IDENTITY, max_version='latest' + ) self.assertEqual(self.V3_URL, endpoint) - endpoint = sess.get_endpoint(service_type=self.IDENTITY, - min_version='latest') + endpoint = sess.get_endpoint( + service_type=self.IDENTITY, min_version='latest' + ) self.assertEqual(self.V3_URL, endpoint) - endpoint = sess.get_endpoint(service_type=self.IDENTITY, - min_version='latest', - max_version='latest') + endpoint = sess.get_endpoint( + service_type=self.IDENTITY, + min_version='latest', + max_version='latest', + ) self.assertEqual(self.V3_URL, endpoint) - self.assertRaises(ValueError, sess.get_endpoint, - service_type=self.IDENTITY, - min_version='latest', max_version='3.0') + self.assertRaises( + ValueError, + sess.get_endpoint, + service_type=self.IDENTITY, + min_version='latest', + max_version='3.0', + ) def test_version_range(self): v2_disc = fixture.V2Discovery(self.V2_URL) common_disc = fixture.DiscoveryList(href=self.BASE_URL) def stub_urls(): - v2_m = self.stub_url('GET', - ['v2.0'], - base_url=self.BASE_URL, - status_code=200, - json={'version': v2_disc}) - common_m = self.stub_url('GET', - base_url=self.BASE_URL, - status_code=200, - json=common_disc) + v2_m = self.stub_url( + 'GET', + ['v2.0'], + base_url=self.BASE_URL, + status_code=200, + json={'version': v2_disc}, + ) + common_m = self.stub_url( + 'GET', + base_url=self.BASE_URL, + status_code=200, + json=common_disc, + ) return v2_m, common_m + v2_m, common_m = stub_urls() token = fixture.V2Token() service = token.add_service(self.IDENTITY) - service.add_endpoint(public=self.V2_URL, - admin=self.V2_URL, - internal=self.V2_URL) + service.add_endpoint( + public=self.V2_URL, admin=self.V2_URL, internal=self.V2_URL + ) - self.stub_url('POST', - ['tokens'], - base_url=self.V2_URL, - json=token) + self.stub_url('POST', ['tokens'], base_url=self.V2_URL, json=token) - v2_auth = identity.V2Password(self.V2_URL, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex) + v2_auth = identity.V2Password( + self.V2_URL, username=uuid.uuid4().hex, password=uuid.uuid4().hex + ) sess = session.Session(auth=v2_auth) # v2 auth with v2 url doesn't make any discovery calls. self.assertFalse(v2_m.called) - endpoint = sess.get_endpoint(service_type=self.IDENTITY, - min_version='2.0', max_version='3.0') + endpoint = sess.get_endpoint( + service_type=self.IDENTITY, min_version='2.0', max_version='3.0' + ) # We should make the one call self.assertFalse(v2_m.called) @@ -2080,8 +2291,9 @@ def stub_urls(): self.assertEqual(self.V3_URL, endpoint) v2_m, common_m = stub_urls() - endpoint = sess.get_endpoint(service_type=self.IDENTITY, - min_version='1', max_version='2') + endpoint = sess.get_endpoint( + service_type=self.IDENTITY, min_version='1', max_version='2' + ) # We should make no calls - we peek in the cache self.assertFalse(v2_m.called) @@ -2091,8 +2303,9 @@ def stub_urls(): self.assertEqual(self.V2_URL, endpoint) v2_m, common_m = stub_urls() - endpoint = sess.get_endpoint(service_type=self.IDENTITY, - min_version='4') + endpoint = sess.get_endpoint( + service_type=self.IDENTITY, min_version='4' + ) # We should make no more calls self.assertFalse(v2_m.called) @@ -2102,8 +2315,9 @@ def stub_urls(): self.assertIsNone(endpoint) v2_m, common_m = stub_urls() - endpoint = sess.get_endpoint(service_type=self.IDENTITY, - min_version='2') + endpoint = sess.get_endpoint( + service_type=self.IDENTITY, min_version='2' + ) # We should make no more calls self.assertFalse(v2_m.called) @@ -2113,9 +2327,13 @@ def stub_urls(): self.assertEqual(self.V3_URL, endpoint) v2_m, common_m = stub_urls() - self.assertRaises(ValueError, sess.get_endpoint, - service_type=self.IDENTITY, version=3, - min_version='2') + self.assertRaises( + ValueError, + sess.get_endpoint, + service_type=self.IDENTITY, + version=3, + min_version='2', + ) # We should make no more calls self.assertFalse(v2_m.called) @@ -2123,36 +2341,39 @@ def stub_urls(): def test_get_endpoint_data(self): common_disc = fixture.DiscoveryList(v2=False, v3=False) - common_disc.add_microversion(href=self.OTHER_URL, id='v2.1', - min_version='2.1', max_version='2.35') + common_disc.add_microversion( + href=self.OTHER_URL, + id='v2.1', + min_version='2.1', + max_version='2.35', + ) - common_m = self.stub_url('GET', - base_url=self.OTHER_URL, - status_code=200, - json=common_disc) + common_m = self.stub_url( + 'GET', base_url=self.OTHER_URL, status_code=200, json=common_disc + ) token = fixture.V2Token() service = token.add_service('network') - service.add_endpoint(public=self.OTHER_URL, - admin=self.OTHER_URL, - internal=self.OTHER_URL) + service.add_endpoint( + public=self.OTHER_URL, + admin=self.OTHER_URL, + internal=self.OTHER_URL, + ) - self.stub_url('POST', - ['tokens'], - base_url=self.V2_URL, - json=token) + self.stub_url('POST', ['tokens'], base_url=self.V2_URL, json=token) - v2_auth = identity.V2Password(self.V2_URL, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex) + v2_auth = identity.V2Password( + self.V2_URL, username=uuid.uuid4().hex, password=uuid.uuid4().hex + ) sess = session.Session(auth=v2_auth) # v2 auth with v2 url doesn't make any discovery calls. self.assertFalse(common_m.called) - data = sess.get_endpoint_data(service_type='network', - min_version='2.0', max_version='3.0') + data = sess.get_endpoint_data( + service_type='network', min_version='2.0', max_version='3.0' + ) # We should make the one call self.assertTrue(common_m.called) @@ -2165,36 +2386,36 @@ def test_get_endpoint_data(self): def test_get_endpoint_data_compute(self): common_disc = fixture.DiscoveryList(v2=False, v3=False) - common_disc.add_nova_microversion(href=self.OTHER_URL, id='v2.1', - min_version='2.1', version='2.35') + common_disc.add_nova_microversion( + href=self.OTHER_URL, id='v2.1', min_version='2.1', version='2.35' + ) - common_m = self.stub_url('GET', - base_url=self.OTHER_URL, - status_code=200, - json=common_disc) + common_m = self.stub_url( + 'GET', base_url=self.OTHER_URL, status_code=200, json=common_disc + ) token = fixture.V2Token() service = token.add_service('compute') - service.add_endpoint(public=self.OTHER_URL, - admin=self.OTHER_URL, - internal=self.OTHER_URL) + service.add_endpoint( + public=self.OTHER_URL, + admin=self.OTHER_URL, + internal=self.OTHER_URL, + ) - self.stub_url('POST', - ['tokens'], - base_url=self.V2_URL, - json=token) + self.stub_url('POST', ['tokens'], base_url=self.V2_URL, json=token) - v2_auth = identity.V2Password(self.V2_URL, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex) + v2_auth = identity.V2Password( + self.V2_URL, username=uuid.uuid4().hex, password=uuid.uuid4().hex + ) sess = session.Session(auth=v2_auth) # v2 auth with v2 url doesn't make any discovery calls. self.assertFalse(common_m.called) - data = sess.get_endpoint_data(service_type='compute', - min_version='2.0', max_version='3.0') + data = sess.get_endpoint_data( + service_type='compute', min_version='2.0', max_version='3.0' + ) # We should make the one call self.assertTrue(common_m.called) @@ -2207,31 +2428,27 @@ def test_get_endpoint_data_compute(self): def test_getting_endpoints_on_auth_interface(self): disc = fixture.DiscoveryList(href=self.BASE_URL) - self.stub_url('GET', - ['/'], - base_url=self.BASE_URL, - status_code=300, - json=disc) + self.stub_url( + 'GET', ['/'], base_url=self.BASE_URL, status_code=300, json=disc + ) token = fixture.V2Token() service = token.add_service(self.IDENTITY) - service.add_endpoint(public=self.V2_URL, - admin=self.V2_URL, - internal=self.V2_URL) + service.add_endpoint( + public=self.V2_URL, admin=self.V2_URL, internal=self.V2_URL + ) - self.stub_url('POST', - ['tokens'], - base_url=self.V2_URL, - json=token) + self.stub_url('POST', ['tokens'], base_url=self.V2_URL, json=token) - v2_auth = identity.V2Password(self.V2_URL, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex) + v2_auth = identity.V2Password( + self.V2_URL, username=uuid.uuid4().hex, password=uuid.uuid4().hex + ) sess = session.Session(auth=v2_auth) - endpoint = sess.get_endpoint(interface=plugin.AUTH_INTERFACE, - version=(3, 0)) + endpoint = sess.get_endpoint( + interface=plugin.AUTH_INTERFACE, version=(3, 0) + ) self.assertEqual(self.V3_URL, endpoint) @@ -2239,42 +2456,45 @@ def test_setting_no_discover_hack(self): v2_disc = fixture.V2Discovery(self.V2_URL) common_disc = fixture.DiscoveryList(href=self.BASE_URL) - v2_m = self.stub_url('GET', - ['v2.0'], - base_url=self.BASE_URL, - status_code=200, - json=v2_disc) + v2_m = self.stub_url( + 'GET', + ['v2.0'], + base_url=self.BASE_URL, + status_code=200, + json=v2_disc, + ) - common_m = self.stub_url('GET', - [], - base_url=self.BASE_URL, - status_code=300, - json=common_disc) + common_m = self.stub_url( + 'GET', + [], + base_url=self.BASE_URL, + status_code=300, + json=common_disc, + ) resp_text = uuid.uuid4().hex - resp_m = self.stub_url('GET', - ['v3', 'path'], - base_url=self.BASE_URL, - status_code=200, - text=resp_text) + resp_m = self.stub_url( + 'GET', + ['v3', 'path'], + base_url=self.BASE_URL, + status_code=200, + text=resp_text, + ) # it doesn't matter that we auth with v2 here, discovery hack is in # base. All identity endpoints point to v2 urls. token = fixture.V2Token() service = token.add_service(self.IDENTITY) - service.add_endpoint(public=self.V2_URL, - admin=self.V2_URL, - internal=self.V2_URL) + service.add_endpoint( + public=self.V2_URL, admin=self.V2_URL, internal=self.V2_URL + ) - self.stub_url('POST', - ['tokens'], - base_url=self.V2_URL, - json=token) + self.stub_url('POST', ['tokens'], base_url=self.V2_URL, json=token) - v2_auth = identity.V2Password(self.V2_URL, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex) + v2_auth = identity.V2Password( + self.V2_URL, username=uuid.uuid4().hex, password=uuid.uuid4().hex + ) sess = session.Session(auth=v2_auth) @@ -2283,9 +2503,9 @@ def test_setting_no_discover_hack(self): self.assertFalse(common_m.called) # v3 endpoint with hack will strip v2 suffix and call root discovery - endpoint = sess.get_endpoint(service_type=self.IDENTITY, - version=(3, 0), - allow_version_hack=True) + endpoint = sess.get_endpoint( + service_type=self.IDENTITY, version=(3, 0), allow_version_hack=True + ) # got v3 url self.assertEqual(self.V3_URL, endpoint) @@ -2295,9 +2515,11 @@ def test_setting_no_discover_hack(self): self.assertTrue(common_m.called_once) # with hack turned off it calls v2 discovery and finds nothing - endpoint = sess.get_endpoint(service_type=self.IDENTITY, - version=(3, 0), - allow_version_hack=False) + endpoint = sess.get_endpoint( + service_type=self.IDENTITY, + version=(3, 0), + allow_version_hack=False, + ) self.assertIsNone(endpoint) # this one called v2 @@ -2305,42 +2527,48 @@ def test_setting_no_discover_hack(self): self.assertTrue(common_m.called_once) # get_endpoint returning None raises EndpointNotFound when requesting - self.assertRaises(exceptions.EndpointNotFound, - sess.get, - '/path', - endpoint_filter={'service_type': 'identity', - 'version': (3, 0), - 'allow_version_hack': False}) + self.assertRaises( + exceptions.EndpointNotFound, + sess.get, + '/path', + endpoint_filter={ + 'service_type': 'identity', + 'version': (3, 0), + 'allow_version_hack': False, + }, + ) self.assertFalse(resp_m.called) # works when allow_version_hack is set - resp = sess.get('/path', - endpoint_filter={'service_type': 'identity', - 'version': (3, 0), - 'allow_version_hack': True}) + resp = sess.get( + '/path', + endpoint_filter={ + 'service_type': 'identity', + 'version': (3, 0), + 'allow_version_hack': True, + }, + ) self.assertTrue(resp_m.called_once) self.assertEqual(resp_text, resp.text) class GenericPlugin(plugin.BaseAuthPlugin): - BAD_TOKEN = uuid.uuid4().hex def __init__(self): - super(GenericPlugin, self).__init__() + super().__init__() self.endpoint = 'http://keystone.host:5000' - self.headers = {'headerA': 'valueA', - 'headerB': 'valueB'} + self.headers = {'headerA': 'valueA', 'headerB': 'valueB'} self.cert = '/path/to/cert' self.connection_params = {'cert': self.cert, 'verify': False} def url(self, prefix): - return '%s/%s' % (self.endpoint, prefix) + return f'{self.endpoint}/{prefix}' def get_token(self, session, **kwargs): # NOTE(jamielennox): by specifying get_headers this should not be used @@ -2357,12 +2585,11 @@ def get_connection_params(self, session, **kwargs): class GenericAuthPluginTests(utils.TestCase): - # filter doesn't matter to GenericPlugin, but we have to specify one ENDPOINT_FILTER = {uuid.uuid4().hex: uuid.uuid4().hex} def setUp(self): - super(GenericAuthPluginTests, self).setUp() + super().setUp() self.auth = GenericPlugin() self.session = session.Session(auth=self.auth) @@ -2378,17 +2605,16 @@ def test_setting_headers(self): self.assertRequestHeaderEqual(k, v) self.assertIsNone(self.session.get_token()) - self.assertEqual(self.auth.headers, - self.session.get_auth_headers()) - self.assertNotIn('X-Auth-Token', - self.requests_mock.last_request.headers) + self.assertEqual(self.auth.headers, self.session.get_auth_headers()) + self.assertNotIn( + 'X-Auth-Token', self.requests_mock.last_request.headers + ) def test_setting_connection_params(self): text = uuid.uuid4().hex self.stub_url('GET', base_url=self.auth.url('prefix'), text=text) - resp = self.session.get('prefix', - endpoint_filter=self.ENDPOINT_FILTER) + resp = self.session.get('prefix', endpoint_filter=self.ENDPOINT_FILTER) self.assertEqual(text, resp.text) @@ -2403,10 +2629,12 @@ def test_setting_bad_connection_params(self): name = uuid.uuid4().hex self.auth.connection_params[name] = uuid.uuid4().hex - e = self.assertRaises(exceptions.UnsupportedParameters, - self.session.get, - 'prefix', - endpoint_filter=self.ENDPOINT_FILTER) + e = self.assertRaises( + exceptions.UnsupportedParameters, + self.session.get, + 'prefix', + endpoint_filter=self.ENDPOINT_FILTER, + ) self.assertIn(name, str(e)) @@ -2415,15 +2643,17 @@ class DiscoveryFailures(utils.TestCase): TEST_ROOT_URL = 'http://127.0.0.1:5000/' def test_connection_error(self): - self.requests_mock.get(self.TEST_ROOT_URL, - exc=exceptions.ConnectionError) + self.requests_mock.get( + self.TEST_ROOT_URL, exc=exceptions.ConnectionError + ) sess = session.Session() p = identity.generic.password.Password(self.TEST_ROOT_URL) self.assertRaises(exceptions.DiscoveryFailure, p.get_auth_ref, sess) def test_client_exception(self): - self.requests_mock.get(self.TEST_ROOT_URL, - exc=exceptions.ClientException) + self.requests_mock.get( + self.TEST_ROOT_URL, exc=exceptions.ClientException + ) sess = session.Session() p = identity.generic.password.Password(self.TEST_ROOT_URL) self.assertRaises(exceptions.ClientException, p.get_auth_ref, sess) diff --git a/keystoneauth1/tests/unit/identity/test_identity_v2.py b/keystoneauth1/tests/unit/identity/test_identity_v2.py index d7b76b82..c5b3cc8a 100644 --- a/keystoneauth1/tests/unit/identity/test_identity_v2.py +++ b/keystoneauth1/tests/unit/identity/test_identity_v2.py @@ -25,78 +25,89 @@ class V2IdentityPlugin(utils.TestCase): - TEST_ROOT_URL = 'http://127.0.0.1:5000/' - TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v2.0') + TEST_URL = '{}{}'.format(TEST_ROOT_URL, 'v2.0') TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/' - TEST_ADMIN_URL = '%s%s' % (TEST_ROOT_ADMIN_URL, 'v2.0') + TEST_ADMIN_URL = '{}{}'.format(TEST_ROOT_ADMIN_URL, 'v2.0') TEST_PASS = 'password' - TEST_SERVICE_CATALOG = [{ - "endpoints": [{ - "adminURL": "http://cdn.admin-nets.local:8774/v1.0", - "region": "RegionOne", - "internalURL": "http://127.0.0.1:8774/v1.0", - "publicURL": "http://cdn.admin-nets.local:8774/v1.0/" - }], - "type": "nova_compat", - "name": "nova_compat" - }, { - "endpoints": [{ - "adminURL": "http://nova/novapi/admin", - "region": "RegionOne", - "internalURL": "http://nova/novapi/internal", - "publicURL": "http://nova/novapi/public" - }], - "type": "compute", - "name": "nova" - }, { - "endpoints": [{ - "adminURL": "http://glance/glanceapi/admin", - "region": "RegionOne", - "internalURL": "http://glance/glanceapi/internal", - "publicURL": "http://glance/glanceapi/public" - }], - "type": "image", - "name": "glance" - }, { - "endpoints": [{ - "adminURL": TEST_ADMIN_URL, - "region": "RegionOne", - "internalURL": "http://127.0.0.1:5000/v2.0", - "publicURL": "http://127.0.0.1:5000/v2.0" - }], - "type": "identity", - "name": "keystone" - }, { - "endpoints": [{ - "adminURL": "http://swift/swiftapi/admin", - "region": "RegionOne", - "internalURL": "http://swift/swiftapi/internal", - "publicURL": "http://swift/swiftapi/public" - }], - "type": "object-store", - "name": "swift" - }] + TEST_SERVICE_CATALOG = [ + { + "endpoints": [ + { + "adminURL": "http://cdn.admin-nets.local:8774/v1.0", + "region": "RegionOne", + "internalURL": "http://127.0.0.1:8774/v1.0", + "publicURL": "http://cdn.admin-nets.local:8774/v1.0/", + } + ], + "type": "nova_compat", + "name": "nova_compat", + }, + { + "endpoints": [ + { + "adminURL": "http://nova/novapi/admin", + "region": "RegionOne", + "internalURL": "http://nova/novapi/internal", + "publicURL": "http://nova/novapi/public", + } + ], + "type": "compute", + "name": "nova", + }, + { + "endpoints": [ + { + "adminURL": "http://glance/glanceapi/admin", + "region": "RegionOne", + "internalURL": "http://glance/glanceapi/internal", + "publicURL": "http://glance/glanceapi/public", + } + ], + "type": "image", + "name": "glance", + }, + { + "endpoints": [ + { + "adminURL": TEST_ADMIN_URL, + "region": "RegionOne", + "internalURL": "http://127.0.0.1:5000/v2.0", + "publicURL": "http://127.0.0.1:5000/v2.0", + } + ], + "type": "identity", + "name": "keystone", + }, + { + "endpoints": [ + { + "adminURL": "http://swift/swiftapi/admin", + "region": "RegionOne", + "internalURL": "http://swift/swiftapi/internal", + "publicURL": "http://swift/swiftapi/public", + } + ], + "type": "object-store", + "name": "swift", + }, + ] def setUp(self): - super(V2IdentityPlugin, self).setUp() + super().setUp() self.TEST_RESPONSE_DICT = { "access": { "token": { - "expires": "%i-02-01T00:00:10.000123Z" % - (1 + time.gmtime().tm_year), + "expires": "%i-02-01T00:00:10.000123Z" + % (1 + time.gmtime().tm_year), "id": self.TEST_TOKEN, - "tenant": { - "id": self.TEST_TENANT_ID - }, - }, - "user": { - "id": self.TEST_USER + "tenant": {"id": self.TEST_TENANT_ID}, }, + "user": {"id": self.TEST_USER}, "serviceCatalog": self.TEST_SERVICE_CATALOG, - }, + } } def stub_auth(self, **kwargs): @@ -104,16 +115,24 @@ def stub_auth(self, **kwargs): def test_authenticate_with_username_password(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) + a = v2.Password( + self.TEST_URL, username=self.TEST_USER, password=self.TEST_PASS + ) self.assertIsNone(a.user_id) self.assertFalse(a.has_scope_parameters) s = session.Session(a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'passwordCredentials': {'username': self.TEST_USER, - 'password': self.TEST_PASS}}} + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) + + req = { + 'auth': { + 'passwordCredentials': { + 'username': self.TEST_USER, + 'password': self.TEST_PASS, + } + } + } self.assertRequestBodyIs(json=req) self.assertRequestHeaderEqual('Content-Type', 'application/json') self.assertRequestHeaderEqual('Accept', 'application/json') @@ -121,16 +140,24 @@ def test_authenticate_with_username_password(self): def test_authenticate_with_user_id_password(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v2.Password(self.TEST_URL, user_id=self.TEST_USER, - password=self.TEST_PASS) + a = v2.Password( + self.TEST_URL, user_id=self.TEST_USER, password=self.TEST_PASS + ) self.assertIsNone(a.username) self.assertFalse(a.has_scope_parameters) s = session.Session(a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'passwordCredentials': {'userId': self.TEST_USER, - 'password': self.TEST_PASS}}} + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) + + req = { + 'auth': { + 'passwordCredentials': { + 'userId': self.TEST_USER, + 'password': self.TEST_PASS, + } + } + } self.assertRequestBodyIs(json=req) self.assertRequestHeaderEqual('Content-Type', 'application/json') self.assertRequestHeaderEqual('Accept', 'application/json') @@ -138,33 +165,55 @@ def test_authenticate_with_user_id_password(self): def test_authenticate_with_username_password_scoped(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS, tenant_id=self.TEST_TENANT_ID) + a = v2.Password( + self.TEST_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + tenant_id=self.TEST_TENANT_ID, + ) self.assertTrue(a.has_scope_parameters) self.assertIsNone(a.user_id) s = session.Session(a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'passwordCredentials': {'username': self.TEST_USER, - 'password': self.TEST_PASS}, - 'tenantId': self.TEST_TENANT_ID}} + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) + + req = { + 'auth': { + 'passwordCredentials': { + 'username': self.TEST_USER, + 'password': self.TEST_PASS, + }, + 'tenantId': self.TEST_TENANT_ID, + } + } self.assertRequestBodyIs(json=req) self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) def test_authenticate_with_user_id_password_scoped(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v2.Password(self.TEST_URL, user_id=self.TEST_USER, - password=self.TEST_PASS, tenant_id=self.TEST_TENANT_ID) + a = v2.Password( + self.TEST_URL, + user_id=self.TEST_USER, + password=self.TEST_PASS, + tenant_id=self.TEST_TENANT_ID, + ) self.assertIsNone(a.username) self.assertTrue(a.has_scope_parameters) s = session.Session(a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'passwordCredentials': {'userId': self.TEST_USER, - 'password': self.TEST_PASS}, - 'tenantId': self.TEST_TENANT_ID}} + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) + + req = { + 'auth': { + 'passwordCredentials': { + 'userId': self.TEST_USER, + 'password': self.TEST_PASS, + }, + 'tenantId': self.TEST_TENANT_ID, + } + } self.assertRequestBodyIs(json=req) self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) @@ -172,8 +221,9 @@ def test_authenticate_with_token(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) a = v2.Token(self.TEST_URL, 'foo') s = session.Session(a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) req = {'auth': {'token': {'id': 'foo'}}} self.assertRequestBodyIs(json=req) @@ -184,40 +234,55 @@ def test_authenticate_with_token(self): def test_with_trust_id(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS, trust_id='trust') + a = v2.Password( + self.TEST_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + trust_id='trust', + ) self.assertTrue(a.has_scope_parameters) s = session.Session(a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) - - req = {'auth': {'passwordCredentials': {'username': self.TEST_USER, - 'password': self.TEST_PASS}, - 'trust_id': 'trust'}} + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) + + req = { + 'auth': { + 'passwordCredentials': { + 'username': self.TEST_USER, + 'password': self.TEST_PASS, + }, + 'trust_id': 'trust', + } + } self.assertRequestBodyIs(json=req) self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) def _do_service_url_test(self, base_url, endpoint_filter): self.stub_auth(json=self.TEST_RESPONSE_DICT) - self.stub_url('GET', ['path'], - base_url=base_url, - text='SUCCESS', status_code=200) + self.stub_url( + 'GET', ['path'], base_url=base_url, text='SUCCESS', status_code=200 + ) - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) + a = v2.Password( + self.TEST_URL, username=self.TEST_USER, password=self.TEST_PASS + ) s = session.Session(auth=a) resp = s.get('/path', endpoint_filter=endpoint_filter) self.assertEqual(resp.status_code, 200) - self.assertEqual(self.requests_mock.last_request.url, - base_url + '/path') + self.assertEqual( + self.requests_mock.last_request.url, base_url + '/path' + ) def test_service_url(self): - endpoint_filter = {'service_type': 'compute', - 'interface': 'admin', - 'service_name': 'nova'} + endpoint_filter = { + 'service_type': 'compute', + 'interface': 'admin', + 'service_name': 'nova', + } self._do_service_url_test('http://nova/novapi/admin', endpoint_filter) def test_service_url_defaults_to_public(self): @@ -227,47 +292,62 @@ def test_service_url_defaults_to_public(self): def test_endpoint_filter_without_service_type_fails(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) + a = v2.Password( + self.TEST_URL, username=self.TEST_USER, password=self.TEST_PASS + ) s = session.Session(auth=a) - self.assertRaises(exceptions.EndpointNotFound, s.get, '/path', - endpoint_filter={'interface': 'admin'}) + self.assertRaises( + exceptions.EndpointNotFound, + s.get, + '/path', + endpoint_filter={'interface': 'admin'}, + ) def test_full_url_overrides_endpoint_filter(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) - self.stub_url('GET', [], - base_url='http://testurl/', - text='SUCCESS', status_code=200) - - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) + self.stub_url( + 'GET', + [], + base_url='http://testurl/', + text='SUCCESS', + status_code=200, + ) + + a = v2.Password( + self.TEST_URL, username=self.TEST_USER, password=self.TEST_PASS + ) s = session.Session(auth=a) - resp = s.get('http://testurl/', - endpoint_filter={'service_type': 'compute'}) + resp = s.get( + 'http://testurl/', endpoint_filter={'service_type': 'compute'} + ) self.assertEqual(resp.status_code, 200) self.assertEqual(resp.text, 'SUCCESS') def test_invalid_auth_response_dict(self): self.stub_auth(json={'hello': 'world'}) - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) + a = v2.Password( + self.TEST_URL, username=self.TEST_USER, password=self.TEST_PASS + ) s = session.Session(auth=a) - self.assertRaises(exceptions.InvalidResponse, s.get, 'http://any', - authenticated=True) + self.assertRaises( + exceptions.InvalidResponse, s.get, 'http://any', authenticated=True + ) def test_invalid_auth_response_type(self): self.stub_url('POST', ['tokens'], text='testdata') - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) + a = v2.Password( + self.TEST_URL, username=self.TEST_USER, password=self.TEST_PASS + ) s = session.Session(auth=a) - self.assertRaises(exceptions.InvalidResponse, s.get, 'http://any', - authenticated=True) + self.assertRaises( + exceptions.InvalidResponse, s.get, 'http://any', authenticated=True + ) def test_invalidate_response(self): resp_data1 = copy.deepcopy(self.TEST_RESPONSE_DICT) @@ -279,8 +359,9 @@ def test_invalidate_response(self): auth_responses = [{'json': resp_data1}, {'json': resp_data2}] self.stub_auth(response_list=auth_responses) - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) + a = v2.Password( + self.TEST_URL, username=self.TEST_USER, password=self.TEST_PASS + ) s = session.Session(auth=a) self.assertEqual('token1', s.get_token()) @@ -294,41 +375,50 @@ def test_doesnt_log_password(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) password = uuid.uuid4().hex - a = v2.Password(self.TEST_URL, username=self.TEST_USER, - password=password) + a = v2.Password( + self.TEST_URL, username=self.TEST_USER, password=password + ) s = session.Session(auth=a) self.assertEqual(self.TEST_TOKEN, s.get_token()) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) self.assertNotIn(password, self.logger.output) def test_password_with_no_user_id_or_name(self): - self.assertRaises(TypeError, - v2.Password, self.TEST_URL, password=self.TEST_PASS) + self.assertRaises( + TypeError, v2.Password, self.TEST_URL, password=self.TEST_PASS + ) def test_password_cache_id(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) trust_id = uuid.uuid4().hex - a = v2.Password(self.TEST_URL, - username=self.TEST_USER, - password=self.TEST_PASS, - trust_id=trust_id) + a = v2.Password( + self.TEST_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + trust_id=trust_id, + ) - b = v2.Password(self.TEST_URL, - username=self.TEST_USER, - password=self.TEST_PASS, - trust_id=trust_id) + b = v2.Password( + self.TEST_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + trust_id=trust_id, + ) a_id = a.get_cache_id() b_id = b.get_cache_id() self.assertEqual(a_id, b_id) - c = v2.Password(self.TEST_URL, - username=self.TEST_USER, - password=self.TEST_PASS, - tenant_id=trust_id) # same value different param + c = v2.Password( + self.TEST_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + tenant_id=trust_id, + ) # same value different param c_id = c.get_cache_id() @@ -350,18 +440,21 @@ def test_password_change_auth_state(self): auth_ref = access.create(body=token) - a = v2.Password(self.TEST_URL, - username=self.TEST_USER, - password=self.TEST_PASS, - tenant_id=uuid.uuid4().hex) + a = v2.Password( + self.TEST_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + tenant_id=uuid.uuid4().hex, + ) initial_cache_id = a.get_cache_id() state = a.get_auth_state() self.assertIsNone(state) - state = json.dumps({'auth_token': auth_ref.auth_token, - 'body': auth_ref._data}) + state = json.dumps( + {'auth_token': auth_ref.auth_token, 'body': auth_ref._data} + ) a.set_auth_state(state) self.assertEqual(token.token_id, a.auth_ref.auth_token) diff --git a/keystoneauth1/tests/unit/identity/test_identity_v3.py b/keystoneauth1/tests/unit/identity/test_identity_v3.py index 321a0c77..1273af43 100644 --- a/keystoneauth1/tests/unit/identity/test_identity_v3.py +++ b/keystoneauth1/tests/unit/identity/test_identity_v3.py @@ -28,11 +28,10 @@ class V3IdentityPlugin(utils.TestCase): - TEST_ROOT_URL = 'http://127.0.0.1:5000/' - TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v3') + TEST_URL = '{}{}'.format(TEST_ROOT_URL, 'v3') TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/' - TEST_ADMIN_URL = '%s%s' % (TEST_ROOT_ADMIN_URL, 'v3') + TEST_ADMIN_URL = '{}{}'.format(TEST_ROOT_ADMIN_URL, 'v3') TEST_PASS = 'password' @@ -42,134 +41,158 @@ class V3IdentityPlugin(utils.TestCase): TEST_CLIENT_CRED_ID = 'clientcredid' TEST_CLIENT_CRED_SECRET = 'secret' - TEST_SERVICE_CATALOG = [{ - "endpoints": [{ - "url": "http://cdn.admin-nets.local:8774/v1.0/", - "region": "RegionOne", - "interface": "public" - }, { - "url": "http://127.0.0.1:8774/v1.0", - "region": "RegionOne", - "interface": "internal" - }, { - "url": "http://cdn.admin-nets.local:8774/v1.0", - "region": "RegionOne", - "interface": "admin" - }], - "type": "nova_compat" - }, { - "endpoints": [{ - "url": "http://nova/novapi/public", - "region": "RegionOne", - "interface": "public" - }, { - "url": "http://nova/novapi/internal", - "region": "RegionOne", - "interface": "internal" - }, { - "url": "http://nova/novapi/admin", - "region": "RegionOne", - "interface": "admin" - }], - "type": "compute", - "name": "nova", - }, { - "endpoints": [{ - "url": "http://glance/glanceapi/public", - "region": "RegionOne", - "interface": "public" - }, { - "url": "http://glance/glanceapi/internal", - "region": "RegionOne", - "interface": "internal" - }, { - "url": "http://glance/glanceapi/admin", - "region": "RegionOne", - "interface": "admin" - }], - "type": "image", - "name": "glance" - }, { - "endpoints": [{ - "url": "http://127.0.0.1:5000/v3", - "region": "RegionOne", - "interface": "public" - }, { - "url": "http://127.0.0.1:5000/v3", - "region": "RegionOne", - "interface": "internal" - }, { - "url": TEST_ADMIN_URL, - "region": "RegionOne", - "interface": "admin" - }], - "type": "identity" - }, { - "endpoints": [{ - "url": "http://swift/swiftapi/public", - "region": "RegionOne", - "interface": "public" - }, { - "url": "http://swift/swiftapi/internal", - "region": "RegionOne", - "interface": "internal" - }, { - "url": "http://swift/swiftapi/admin", - "region": "RegionOne", - "interface": "admin" - }], - "type": "object-store" - }] + TEST_SERVICE_CATALOG = [ + { + "endpoints": [ + { + "url": "http://cdn.admin-nets.local:8774/v1.0/", + "region": "RegionOne", + "interface": "public", + }, + { + "url": "http://127.0.0.1:8774/v1.0", + "region": "RegionOne", + "interface": "internal", + }, + { + "url": "http://cdn.admin-nets.local:8774/v1.0", + "region": "RegionOne", + "interface": "admin", + }, + ], + "type": "nova_compat", + }, + { + "endpoints": [ + { + "url": "http://nova/novapi/public", + "region": "RegionOne", + "interface": "public", + }, + { + "url": "http://nova/novapi/internal", + "region": "RegionOne", + "interface": "internal", + }, + { + "url": "http://nova/novapi/admin", + "region": "RegionOne", + "interface": "admin", + }, + ], + "type": "compute", + "name": "nova", + }, + { + "endpoints": [ + { + "url": "http://glance/glanceapi/public", + "region": "RegionOne", + "interface": "public", + }, + { + "url": "http://glance/glanceapi/internal", + "region": "RegionOne", + "interface": "internal", + }, + { + "url": "http://glance/glanceapi/admin", + "region": "RegionOne", + "interface": "admin", + }, + ], + "type": "image", + "name": "glance", + }, + { + "endpoints": [ + { + "url": "http://127.0.0.1:5000/v3", + "region": "RegionOne", + "interface": "public", + }, + { + "url": "http://127.0.0.1:5000/v3", + "region": "RegionOne", + "interface": "internal", + }, + { + "url": TEST_ADMIN_URL, + "region": "RegionOne", + "interface": "admin", + }, + ], + "type": "identity", + }, + { + "endpoints": [ + { + "url": "http://swift/swiftapi/public", + "region": "RegionOne", + "interface": "public", + }, + { + "url": "http://swift/swiftapi/internal", + "region": "RegionOne", + "interface": "internal", + }, + { + "url": "http://swift/swiftapi/admin", + "region": "RegionOne", + "interface": "admin", + }, + ], + "type": "object-store", + }, + ] TEST_SERVICE_PROVIDERS = [ { "auth_url": "https://sp1.com/v3/OS-FEDERATION/" - "identity_providers/acme/protocols/saml2/auth", + "identity_providers/acme/protocols/saml2/auth", "id": "sp1", - "sp_url": "https://sp1.com/Shibboleth.sso/SAML2/ECP" - }, { + "sp_url": "https://sp1.com/Shibboleth.sso/SAML2/ECP", + }, + { "auth_url": "https://sp2.com/v3/OS-FEDERATION/" - "identity_providers/acme/protocols/saml2/auth", + "identity_providers/acme/protocols/saml2/auth", "id": "sp2", - "sp_url": "https://sp2.com/Shibboleth.sso/SAML2/ECP" - } + "sp_url": "https://sp2.com/Shibboleth.sso/SAML2/ECP", + }, ] def setUp(self): - super(V3IdentityPlugin, self).setUp() + super().setUp() self.TEST_DISCOVERY_RESPONSE = { - 'versions': {'values': [fixture.V3Discovery(self.TEST_URL)]}} + 'versions': {'values': [fixture.V3Discovery(self.TEST_URL)]} + } nextyear = 1 + time.gmtime().tm_year self.TEST_RESPONSE_DICT = { "token": { - "methods": [ - "token", - "password" - ], - + "methods": ["token", "password"], "expires_at": "%i-02-01T00:00:10.000123Z" % nextyear, "project": { "domain": { "id": self.TEST_DOMAIN_ID, - "name": self.TEST_DOMAIN_NAME + "name": self.TEST_DOMAIN_NAME, }, "id": self.TEST_TENANT_ID, - "name": self.TEST_TENANT_NAME + "name": self.TEST_TENANT_NAME, }, "user": { "domain": { "id": self.TEST_DOMAIN_ID, - "name": self.TEST_DOMAIN_NAME + "name": self.TEST_DOMAIN_NAME, }, "id": self.TEST_USER, - "name": self.TEST_USER + "name": self.TEST_USER, }, "issued_at": "2013-05-29T16:55:21.468960Z", "catalog": self.TEST_SERVICE_CATALOG, - "service_providers": self.TEST_SERVICE_PROVIDERS - }, + "service_providers": self.TEST_SERVICE_PROVIDERS, + } } self.TEST_PROJECTS_RESPONSE = { "projects": [ @@ -180,7 +203,7 @@ def setUp(self): "links": { "self": "https://identity:5000/v3/projects/263fd9" }, - "name": "Dev Group A" + "name": "Dev Group A", }, { "domain_id": "1789d1", @@ -189,72 +212,64 @@ def setUp(self): "links": { "self": "https://identity:5000/v3/projects/e56ad3" }, - "name": "Dev Group B" - } + "name": "Dev Group B", + }, ], - "links": { - "self": "https://identity:5000/v3/projects", - } + "links": {"self": "https://identity:5000/v3/projects"}, } self.TEST_APP_CRED_TOKEN_RESPONSE = { "token": { - "methods": [ - "application_credential" - ], - + "methods": ["application_credential"], "expires_at": "%i-02-01T00:00:10.000123Z" % nextyear, "project": { "domain": { "id": self.TEST_DOMAIN_ID, - "name": self.TEST_DOMAIN_NAME + "name": self.TEST_DOMAIN_NAME, }, "id": self.TEST_TENANT_ID, - "name": self.TEST_TENANT_NAME + "name": self.TEST_TENANT_NAME, }, "user": { "domain": { "id": self.TEST_DOMAIN_ID, - "name": self.TEST_DOMAIN_NAME + "name": self.TEST_DOMAIN_NAME, }, "id": self.TEST_USER, - "name": self.TEST_USER + "name": self.TEST_USER, }, "issued_at": "2013-05-29T16:55:21.468960Z", "catalog": self.TEST_SERVICE_CATALOG, "service_providers": self.TEST_SERVICE_PROVIDERS, - "application_credential_restricted": True - }, + "application_credential_restricted": True, + } } self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE = { "token": { - "methods": [ - "oauth2_credential" - ], - + "methods": ["oauth2_credential"], "expires_at": "%i-02-01T00:00:10.000123Z" % nextyear, "project": { "domain": { "id": self.TEST_DOMAIN_ID, - "name": self.TEST_DOMAIN_NAME + "name": self.TEST_DOMAIN_NAME, }, "id": self.TEST_TENANT_ID, - "name": self.TEST_TENANT_NAME + "name": self.TEST_TENANT_NAME, }, "user": { "domain": { "id": self.TEST_DOMAIN_ID, - "name": self.TEST_DOMAIN_NAME + "name": self.TEST_DOMAIN_NAME, }, "id": self.TEST_USER, - "name": self.TEST_USER + "name": self.TEST_USER, }, "issued_at": "2013-05-29T16:55:21.468960Z", "catalog": self.TEST_SERVICE_CATALOG, "service_providers": self.TEST_SERVICE_PROVIDERS, "oauth2_credential": { "x5t#S256": "7UN-z4yFIm9s4jakecGoKa4rc353pDCuFUo9fsDD_1s=" - } - }, + }, + } } self.TEST_RECEIPT_RESPONSE = { "receipt": { @@ -277,8 +292,12 @@ def stub_auth(self, subject_token=None, **kwargs): if not subject_token: subject_token = self.TEST_TOKEN - self.stub_url('POST', ['auth', 'tokens'], - headers={'X-Subject-Token': subject_token}, **kwargs) + self.stub_url( + 'POST', + ['auth', 'tokens'], + headers={'X-Subject-Token': subject_token}, + **kwargs, + ) def stub_receipt(self, receipt=None, receipt_data=None, **kwargs): if not receipt: @@ -287,27 +306,40 @@ def stub_receipt(self, receipt=None, receipt_data=None, **kwargs): if not receipt_data: receipt_data = self.TEST_RECEIPT_RESPONSE - self.stub_url('POST', ['auth', 'tokens'], - headers={'Openstack-Auth-Receipt': receipt}, - status_code=401, - json=receipt_data, - **kwargs) + self.stub_url( + 'POST', + ['auth', 'tokens'], + headers={'Openstack-Auth-Receipt': receipt}, + status_code=401, + json=receipt_data, + **kwargs, + ) def test_authenticate_with_username_password(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v3.Password(self.TEST_URL, - username=self.TEST_USER, - password=self.TEST_PASS) + a = v3.Password( + self.TEST_URL, username=self.TEST_USER, password=self.TEST_PASS + ) self.assertFalse(a.has_scope_parameters) s = session.Session(auth=a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) - req = {'auth': {'identity': - {'methods': ['password'], - 'password': {'user': {'name': self.TEST_USER, - 'password': self.TEST_PASS}}}}} + req = { + 'auth': { + 'identity': { + 'methods': ['password'], + 'password': { + 'user': { + 'name': self.TEST_USER, + 'password': self.TEST_PASS, + } + }, + } + } + } self.assertRequestBodyIs(json=req) self.assertRequestHeaderEqual('Content-Type', 'application/json') @@ -316,38 +348,65 @@ def test_authenticate_with_username_password(self): def test_authenticate_with_username_password_domain_scoped(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS, domain_id=self.TEST_DOMAIN_ID) + a = v3.Password( + self.TEST_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + domain_id=self.TEST_DOMAIN_ID, + ) self.assertTrue(a.has_scope_parameters) s = session.Session(a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) - req = {'auth': {'identity': - {'methods': ['password'], - 'password': {'user': {'name': self.TEST_USER, - 'password': self.TEST_PASS}}}, - 'scope': {'domain': {'id': self.TEST_DOMAIN_ID}}}} + req = { + 'auth': { + 'identity': { + 'methods': ['password'], + 'password': { + 'user': { + 'name': self.TEST_USER, + 'password': self.TEST_PASS, + } + }, + }, + 'scope': {'domain': {'id': self.TEST_DOMAIN_ID}}, + } + } self.assertRequestBodyIs(json=req) self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) def test_authenticate_with_username_password_project_scoped(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS, - project_id=self.TEST_TENANT_ID) + a = v3.Password( + self.TEST_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + project_id=self.TEST_TENANT_ID, + ) self.assertTrue(a.has_scope_parameters) s = session.Session(a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) - req = {'auth': {'identity': - {'methods': ['password'], - 'password': {'user': {'name': self.TEST_USER, - 'password': self.TEST_PASS}}}, - 'scope': {'project': {'id': self.TEST_TENANT_ID}}}} + req = { + 'auth': { + 'identity': { + 'methods': ['password'], + 'password': { + 'user': { + 'name': self.TEST_USER, + 'password': self.TEST_PASS, + } + }, + }, + 'scope': {'project': {'id': self.TEST_TENANT_ID}}, + } + } self.assertRequestBodyIs(json=req) self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) self.assertEqual(s.auth.auth_ref.project_id, self.TEST_TENANT_ID) @@ -357,12 +416,18 @@ def test_authenticate_with_token(self): a = v3.Token(self.TEST_URL, self.TEST_TOKEN) s = session.Session(auth=a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) - req = {'auth': {'identity': - {'methods': ['token'], - 'token': {'id': self.TEST_TOKEN}}}} + req = { + 'auth': { + 'identity': { + 'methods': ['token'], + 'token': {'id': self.TEST_TOKEN}, + } + } + } self.assertRequestBodyIs(json=req) @@ -376,43 +441,63 @@ def test_with_expired(self): d = copy.deepcopy(self.TEST_RESPONSE_DICT) d['token']['expires_at'] = '2000-01-01T00:00:10.000123Z' - a = v3.Password(self.TEST_URL, username='username', - password='password') + a = v3.Password( + self.TEST_URL, username='username', password='password' + ) a.auth_ref = access.create(body=d) s = session.Session(auth=a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) - self.assertEqual(a.auth_ref._data['token']['expires_at'], - self.TEST_RESPONSE_DICT['token']['expires_at']) + self.assertEqual( + a.auth_ref._data['token']['expires_at'], + self.TEST_RESPONSE_DICT['token']['expires_at'], + ) def test_with_domain_and_project_scoping(self): - a = v3.Password(self.TEST_URL, username='username', - password='password', project_id='project', - domain_id='domain') + a = v3.Password( + self.TEST_URL, + username='username', + password='password', + project_id='project', + domain_id='domain', + ) self.assertTrue(a.has_scope_parameters) - self.assertRaises(exceptions.AuthorizationFailure, - a.get_token, None) - self.assertRaises(exceptions.AuthorizationFailure, - a.get_headers, None) + self.assertRaises(exceptions.AuthorizationFailure, a.get_token, None) + self.assertRaises(exceptions.AuthorizationFailure, a.get_headers, None) def test_with_trust_id(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS, trust_id='trust') + a = v3.Password( + self.TEST_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + trust_id='trust', + ) self.assertTrue(a.has_scope_parameters) s = session.Session(a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) - req = {'auth': {'identity': - {'methods': ['password'], - 'password': {'user': {'name': self.TEST_USER, - 'password': self.TEST_PASS}}}, - 'scope': {'OS-TRUST:trust': {'id': 'trust'}}}} + req = { + 'auth': { + 'identity': { + 'methods': ['password'], + 'password': { + 'user': { + 'name': self.TEST_USER, + 'password': self.TEST_PASS, + } + }, + }, + 'scope': {'OS-TRUST:trust': {'id': 'trust'}}, + } + } self.assertRequestBodyIs(json=req) self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) @@ -423,88 +508,128 @@ def test_with_multiple_mechanisms_factory(self): a = v3.Auth(self.TEST_URL, [p, t], trust_id='trust') s = session.Session(a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) - req = {'auth': {'identity': - {'methods': ['password', 'token'], - 'password': {'user': {'name': self.TEST_USER, - 'password': self.TEST_PASS}}, - 'token': {'id': 'foo'}}, - 'scope': {'OS-TRUST:trust': {'id': 'trust'}}}} + req = { + 'auth': { + 'identity': { + 'methods': ['password', 'token'], + 'password': { + 'user': { + 'name': self.TEST_USER, + 'password': self.TEST_PASS, + } + }, + 'token': {'id': 'foo'}, + }, + 'scope': {'OS-TRUST:trust': {'id': 'trust'}}, + } + } self.assertRequestBodyIs(json=req) self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) def test_with_multiple_mechanisms(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) - p = v3.PasswordMethod(username=self.TEST_USER, - password=self.TEST_PASS) + p = v3.PasswordMethod(username=self.TEST_USER, password=self.TEST_PASS) t = v3.TokenMethod(token='foo') a = v3.Auth(self.TEST_URL, [p, t], trust_id='trust') self.assertTrue(a.has_scope_parameters) s = session.Session(auth=a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) - req = {'auth': {'identity': - {'methods': ['password', 'token'], - 'password': {'user': {'name': self.TEST_USER, - 'password': self.TEST_PASS}}, - 'token': {'id': 'foo'}}, - 'scope': {'OS-TRUST:trust': {'id': 'trust'}}}} + req = { + 'auth': { + 'identity': { + 'methods': ['password', 'token'], + 'password': { + 'user': { + 'name': self.TEST_USER, + 'password': self.TEST_PASS, + } + }, + 'token': {'id': 'foo'}, + }, + 'scope': {'OS-TRUST:trust': {'id': 'trust'}}, + } + } self.assertRequestBodyIs(json=req) self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) def test_with_multiple_scopes(self): s = session.Session() - a = v3.Password(self.TEST_URL, - username=self.TEST_USER, password=self.TEST_PASS, - domain_id='x', project_id='x') + a = v3.Password( + self.TEST_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + domain_id='x', + project_id='x', + ) self.assertRaises(exceptions.AuthorizationFailure, a.get_auth_ref, s) - a = v3.Password(self.TEST_URL, - username=self.TEST_USER, password=self.TEST_PASS, - domain_id='x', trust_id='x') + a = v3.Password( + self.TEST_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + domain_id='x', + trust_id='x', + ) self.assertRaises(exceptions.AuthorizationFailure, a.get_auth_ref, s) def test_application_credential_method(self): self.stub_auth(json=self.TEST_APP_CRED_TOKEN_RESPONSE) ac = v3.ApplicationCredential( - self.TEST_URL, application_credential_id=self.TEST_APP_CRED_ID, - application_credential_secret=self.TEST_APP_CRED_SECRET) - req = {'auth': {'identity': - {'methods': ['application_credential'], - 'application_credential': { - 'id': self.TEST_APP_CRED_ID, - 'secret': self.TEST_APP_CRED_SECRET}}}} + self.TEST_URL, + application_credential_id=self.TEST_APP_CRED_ID, + application_credential_secret=self.TEST_APP_CRED_SECRET, + ) + req = { + 'auth': { + 'identity': { + 'methods': ['application_credential'], + 'application_credential': { + 'id': self.TEST_APP_CRED_ID, + 'secret': self.TEST_APP_CRED_SECRET, + }, + } + } + } s = session.Session(auth=ac) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) self.assertRequestBodyIs(json=req) self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) def _do_service_url_test(self, base_url, endpoint_filter): self.stub_auth(json=self.TEST_RESPONSE_DICT) - self.stub_url('GET', ['path'], - base_url=base_url, - text='SUCCESS', status_code=200) + self.stub_url( + 'GET', ['path'], base_url=base_url, text='SUCCESS', status_code=200 + ) - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) + a = v3.Password( + self.TEST_URL, username=self.TEST_USER, password=self.TEST_PASS + ) s = session.Session(auth=a) resp = s.get('/path', endpoint_filter=endpoint_filter) self.assertEqual(resp.status_code, 200) - self.assertEqual(self.requests_mock.last_request.url, - base_url + '/path') + self.assertEqual( + self.requests_mock.last_request.url, base_url + '/path' + ) def test_service_url(self): - endpoint_filter = {'service_type': 'compute', - 'interface': 'admin', - 'service_name': 'nova'} + endpoint_filter = { + 'service_type': 'compute', + 'interface': 'admin', + 'service_name': 'nova', + } self._do_service_url_test('http://nova/novapi/admin', endpoint_filter) def test_service_url_defaults_to_public(self): @@ -514,92 +639,127 @@ def test_service_url_defaults_to_public(self): def test_endpoint_filter_without_service_type_fails(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) + a = v3.Password( + self.TEST_URL, username=self.TEST_USER, password=self.TEST_PASS + ) s = session.Session(auth=a) - self.assertRaises(exceptions.EndpointNotFound, s.get, '/path', - endpoint_filter={'interface': 'admin'}) + self.assertRaises( + exceptions.EndpointNotFound, + s.get, + '/path', + endpoint_filter={'interface': 'admin'}, + ) def test_full_url_overrides_endpoint_filter(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) - self.stub_url('GET', [], - base_url='http://testurl/', - text='SUCCESS', status_code=200) + self.stub_url( + 'GET', + [], + base_url='http://testurl/', + text='SUCCESS', + status_code=200, + ) - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) + a = v3.Password( + self.TEST_URL, username=self.TEST_USER, password=self.TEST_PASS + ) s = session.Session(auth=a) - resp = s.get('http://testurl/', - endpoint_filter={'service_type': 'compute'}) + resp = s.get( + 'http://testurl/', endpoint_filter={'service_type': 'compute'} + ) self.assertEqual(resp.status_code, 200) self.assertEqual(resp.text, 'SUCCESS') def test_service_providers_urls(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) + a = v3.Password( + self.TEST_URL, username=self.TEST_USER, password=self.TEST_PASS + ) s = session.Session() auth_ref = a.get_auth_ref(s) service_providers = auth_ref.service_providers - self.assertEqual('https://sp1.com/v3/OS-FEDERATION/' - 'identity_providers/acme/protocols/saml2/auth', - service_providers.get_auth_url('sp1')) - self.assertEqual('https://sp1.com/Shibboleth.sso/SAML2/ECP', - service_providers.get_sp_url('sp1')) - self.assertEqual('https://sp2.com/v3/OS-FEDERATION/' - 'identity_providers/acme/protocols/saml2/auth', - service_providers.get_auth_url('sp2')) - self.assertEqual('https://sp2.com/Shibboleth.sso/SAML2/ECP', - service_providers.get_sp_url('sp2')) + self.assertEqual( + 'https://sp1.com/v3/OS-FEDERATION/' + 'identity_providers/acme/protocols/saml2/auth', + service_providers.get_auth_url('sp1'), + ) + self.assertEqual( + 'https://sp1.com/Shibboleth.sso/SAML2/ECP', + service_providers.get_sp_url('sp1'), + ) + self.assertEqual( + 'https://sp2.com/v3/OS-FEDERATION/' + 'identity_providers/acme/protocols/saml2/auth', + service_providers.get_auth_url('sp2'), + ) + self.assertEqual( + 'https://sp2.com/Shibboleth.sso/SAML2/ECP', + service_providers.get_sp_url('sp2'), + ) def test_handle_missing_service_provider(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) + a = v3.Password( + self.TEST_URL, username=self.TEST_USER, password=self.TEST_PASS + ) s = session.Session() auth_ref = a.get_auth_ref(s) service_providers = auth_ref.service_providers - self.assertRaises(exceptions.ServiceProviderNotFound, - service_providers._get_service_provider, - uuid.uuid4().hex) + self.assertRaises( + exceptions.ServiceProviderNotFound, + service_providers._get_service_provider, + uuid.uuid4().hex, + ) def test_invalid_auth_response_dict(self): self.stub_auth(json={'hello': 'world'}) - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) + a = v3.Password( + self.TEST_URL, username=self.TEST_USER, password=self.TEST_PASS + ) s = session.Session(auth=a) - self.assertRaises(exceptions.InvalidResponse, s.get, 'http://any', - authenticated=True) + self.assertRaises( + exceptions.InvalidResponse, s.get, 'http://any', authenticated=True + ) def test_invalid_auth_response_type(self): self.stub_url('POST', ['auth', 'tokens'], text='testdata') - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) + a = v3.Password( + self.TEST_URL, username=self.TEST_USER, password=self.TEST_PASS + ) s = session.Session(auth=a) - self.assertRaises(exceptions.InvalidResponse, s.get, 'http://any', - authenticated=True) + self.assertRaises( + exceptions.InvalidResponse, s.get, 'http://any', authenticated=True + ) def test_invalidate_response(self): - auth_responses = [{'status_code': 200, 'json': self.TEST_RESPONSE_DICT, - 'headers': {'X-Subject-Token': 'token1'}}, - {'status_code': 200, 'json': self.TEST_RESPONSE_DICT, - 'headers': {'X-Subject-Token': 'token2'}}] + auth_responses = [ + { + 'status_code': 200, + 'json': self.TEST_RESPONSE_DICT, + 'headers': {'X-Subject-Token': 'token1'}, + }, + { + 'status_code': 200, + 'json': self.TEST_RESPONSE_DICT, + 'headers': {'X-Subject-Token': 'token2'}, + }, + ] - self.requests_mock.post('%s/auth/tokens' % self.TEST_URL, - auth_responses) + self.requests_mock.post(f'{self.TEST_URL}/auth/tokens', auth_responses) - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=self.TEST_PASS) + a = v3.Password( + self.TEST_URL, username=self.TEST_USER, password=self.TEST_PASS + ) s = session.Session(auth=a) self.assertEqual('token1', s.get_token()) @@ -612,12 +772,14 @@ def test_doesnt_log_password(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) password = uuid.uuid4().hex - a = v3.Password(self.TEST_URL, username=self.TEST_USER, - password=password) + a = v3.Password( + self.TEST_URL, username=self.TEST_USER, password=password + ) s = session.Session(a) self.assertEqual(self.TEST_TOKEN, s.get_token()) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) self.assertNotIn(password, self.logger.output) @@ -625,18 +787,21 @@ def test_sends_nocatalog(self): del self.TEST_RESPONSE_DICT['token']['catalog'] self.stub_auth(json=self.TEST_RESPONSE_DICT) - a = v3.Password(self.TEST_URL, - username=self.TEST_USER, - password=self.TEST_PASS, - include_catalog=False) + a = v3.Password( + self.TEST_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + include_catalog=False, + ) s = session.Session(auth=a) s.get_token() auth_url = self.TEST_URL + '/auth/tokens' self.assertEqual(auth_url, a.token_url) - self.assertEqual(auth_url + '?nocatalog', - self.requests_mock.last_request.url) + self.assertEqual( + auth_url + '?nocatalog', self.requests_mock.last_request.url + ) def test_symbols(self): self.assertIs(v3.AuthMethod, v3_base.AuthMethod) @@ -648,10 +813,12 @@ def test_unscoped_request(self): self.stub_auth(json=token) password = uuid.uuid4().hex - a = v3.Password(self.TEST_URL, - user_id=token.user_id, - password=password, - unscoped=True) + a = v3.Password( + self.TEST_URL, + user_id=token.user_id, + password=password, + unscoped=True, + ) s = session.Session() auth_ref = a.get_access(s) @@ -668,11 +835,13 @@ def test_unscoped_request(self): self.assertEqual('unscoped', body['auth']['scope']) def test_unscoped_with_scope_data(self): - a = v3.Password(self.TEST_URL, - user_id=uuid.uuid4().hex, - password=uuid.uuid4().hex, - unscoped=True, - project_id=uuid.uuid4().hex) + a = v3.Password( + self.TEST_URL, + user_id=uuid.uuid4().hex, + password=uuid.uuid4().hex, + unscoped=True, + project_id=uuid.uuid4().hex, + ) s = session.Session() @@ -682,31 +851,37 @@ def test_password_cache_id(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) project_name = uuid.uuid4().hex - a = v3.Password(self.TEST_URL, - username=self.TEST_USER, - password=self.TEST_PASS, - user_domain_id=self.TEST_DOMAIN_ID, - project_domain_name=self.TEST_DOMAIN_NAME, - project_name=project_name) + a = v3.Password( + self.TEST_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + user_domain_id=self.TEST_DOMAIN_ID, + project_domain_name=self.TEST_DOMAIN_NAME, + project_name=project_name, + ) - b = v3.Password(self.TEST_URL, - username=self.TEST_USER, - password=self.TEST_PASS, - user_domain_id=self.TEST_DOMAIN_ID, - project_domain_name=self.TEST_DOMAIN_NAME, - project_name=project_name) + b = v3.Password( + self.TEST_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + user_domain_id=self.TEST_DOMAIN_ID, + project_domain_name=self.TEST_DOMAIN_NAME, + project_name=project_name, + ) a_id = a.get_cache_id() b_id = b.get_cache_id() self.assertEqual(a_id, b_id) - c = v3.Password(self.TEST_URL, - username=self.TEST_USER, - password=self.TEST_PASS, - user_domain_id=self.TEST_DOMAIN_ID, - project_domain_name=self.TEST_DOMAIN_NAME, - project_id=project_name) # same value different param + c = v3.Password( + self.TEST_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + user_domain_id=self.TEST_DOMAIN_ID, + project_domain_name=self.TEST_DOMAIN_NAME, + project_id=project_name, + ) # same value different param c_id = c.get_cache_id() @@ -729,11 +904,13 @@ def test_password_change_auth_state(self): state = json.dumps({'auth_token': token_id, 'body': token}) - a = v3.Password(self.TEST_URL, - username=self.TEST_USER, - password=self.TEST_PASS, - user_domain_id=self.TEST_DOMAIN_ID, - project_id=uuid.uuid4().hex) + a = v3.Password( + self.TEST_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + user_domain_id=self.TEST_DOMAIN_ID, + project_id=uuid.uuid4().hex, + ) initial_cache_id = a.get_cache_id() @@ -758,23 +935,23 @@ def test_receipt_response_is_handled(self): ) s = session.Session(a) - self.assertRaises(exceptions.MissingAuthMethods, - s.get_auth_headers, None) + self.assertRaises( + exceptions.MissingAuthMethods, s.get_auth_headers, None + ) def test_authenticate_with_receipt_and_totp(self): self.stub_auth(json=self.TEST_RESPONSE_DICT) passcode = "123456" auth = v3.TOTP( - self.TEST_URL, - username=self.TEST_USER, - passcode=passcode + self.TEST_URL, username=self.TEST_USER, passcode=passcode ) auth.add_method(v3.ReceiptMethod(receipt=self.TEST_RECEIPT)) self.assertFalse(auth.has_scope_parameters) s = session.Session(auth=auth) - self.assertEqual({"X-Auth-Token": self.TEST_TOKEN}, - s.get_auth_headers()) + self.assertEqual( + {"X-Auth-Token": self.TEST_TOKEN}, s.get_auth_headers() + ) # NOTE(adriant): Here we are confirming the receipt data isn't in the # body or listed as a method @@ -782,15 +959,17 @@ def test_authenticate_with_receipt_and_totp(self): "auth": { "identity": { "methods": ["totp"], - "totp": {"user": { - "name": self.TEST_USER, "passcode": passcode}}, + "totp": { + "user": {"name": self.TEST_USER, "passcode": passcode} + }, } } } self.assertRequestBodyIs(json=req) - self.assertRequestHeaderEqual("Openstack-Auth-Receipt", - self.TEST_RECEIPT) + self.assertRequestHeaderEqual( + "Openstack-Auth-Receipt", self.TEST_RECEIPT + ) self.assertRequestHeaderEqual("Content-Type", "application/json") self.assertRequestHeaderEqual("Accept", "application/json") self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN) @@ -810,23 +989,30 @@ def test_authenticate_with_multi_factor(self): self.assertTrue(auth.has_scope_parameters) s = session.Session(auth=auth) - self.assertEqual({"X-Auth-Token": self.TEST_TOKEN}, - s.get_auth_headers()) + self.assertEqual( + {"X-Auth-Token": self.TEST_TOKEN}, s.get_auth_headers() + ) req = { "auth": { "identity": { "methods": ["password", "totp"], - "totp": {"user": { - "name": self.TEST_USER, "passcode": passcode, - 'domain': {'id': self.TEST_DOMAIN_ID} - }}, - 'password': {'user': { - 'name': self.TEST_USER, 'password': self.TEST_PASS, - 'domain': {'id': self.TEST_DOMAIN_ID} - }}, + "totp": { + "user": { + "name": self.TEST_USER, + "passcode": passcode, + 'domain': {'id': self.TEST_DOMAIN_ID}, + } + }, + 'password': { + 'user': { + 'name': self.TEST_USER, + 'password': self.TEST_PASS, + 'domain': {'id': self.TEST_DOMAIN_ID}, + } + }, }, - 'scope': {'project': {'id': self.TEST_TENANT_ID}} + 'scope': {'project': {'id': self.TEST_TENANT_ID}}, } } @@ -840,19 +1026,31 @@ def test_authenticate_with_unversioned_endpoint(self): # We use the root url here because it doesn't reference the API version # (e.g., '/v3'). We want to make sure the authentication plugin handles # this and appends /v3 if it's not present. - a = v3.Password(self.TEST_ROOT_URL, - username=self.TEST_USER, - password=self.TEST_PASS) + a = v3.Password( + self.TEST_ROOT_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + ) self.assertFalse(a.has_scope_parameters) s = session.Session(auth=a) - self.assertEqual({'X-Auth-Token': self.TEST_TOKEN}, - s.get_auth_headers()) + self.assertEqual( + {'X-Auth-Token': self.TEST_TOKEN}, s.get_auth_headers() + ) - req = {'auth': {'identity': - {'methods': ['password'], - 'password': {'user': {'name': self.TEST_USER, - 'password': self.TEST_PASS}}}}} + req = { + 'auth': { + 'identity': { + 'methods': ['password'], + 'password': { + 'user': { + 'name': self.TEST_USER, + 'password': self.TEST_PASS, + } + }, + } + } + } self.assertRequestBodyIs(json=req) self.assertRequestHeaderEqual('Content-Type', 'application/json') @@ -868,18 +1066,17 @@ def test_oauth2_client_credential_method_http(self): base_http, oauth2_endpoint=oauth2_endpoint, oauth2_client_id=self.TEST_CLIENT_CRED_ID, - oauth2_client_secret=self.TEST_CLIENT_CRED_SECRET + oauth2_client_secret=self.TEST_CLIENT_CRED_SECRET, ) oauth2_resp = { 'status_code': 200, 'json': { 'access_token': oauth2_token, 'expires_in': 3600, - 'token_type': 'Bearer' - } + 'token_type': 'Bearer', + }, } - self.requests_mock.post(oauth2_endpoint, - [oauth2_resp]) + self.requests_mock.post(oauth2_endpoint, [oauth2_resp]) sess = session.Session(auth=client_cre) initial_cache_id = client_cre.get_cache_id() @@ -891,14 +1088,12 @@ def test_oauth2_client_credential_method_http(self): self.assertEqual(sess.auth.auth_ref.auth_token, self.TEST_TOKEN) self.assertEqual(initial_cache_id, client_cre.get_cache_id()) - resp_ok = { - 'status_code': 200 - } - self.requests_mock.post(f'{base_http}/test_api', - [resp_ok]) + resp_ok = {'status_code': 200} + self.requests_mock.post(f'{base_http}/test_api', [resp_ok]) resp = sess.post(f'{base_http}/test_api', authenticated=True) - self.assertRequestHeaderEqual('Authorization', - f'Bearer {oauth2_token}') + self.assertRequestHeaderEqual( + 'Authorization', f'Bearer {oauth2_token}' + ) self.assertRequestHeaderEqual('X-Auth-Token', self.TEST_TOKEN) self.assertEqual(200, resp.status_code) @@ -912,18 +1107,17 @@ def test_oauth2_client_credential_method_https(self): base_https, oauth2_endpoint=oauth2_endpoint, oauth2_client_id=self.TEST_CLIENT_CRED_ID, - oauth2_client_secret=self.TEST_CLIENT_CRED_SECRET + oauth2_client_secret=self.TEST_CLIENT_CRED_SECRET, ) oauth2_resp = { 'status_code': 200, 'json': { 'access_token': oauth2_token, 'expires_in': 3600, - 'token_type': 'Bearer' - } + 'token_type': 'Bearer', + }, } - self.requests_mock.post(oauth2_endpoint, - [oauth2_resp]) + self.requests_mock.post(oauth2_endpoint, [oauth2_resp]) sess = session.Session(auth=client_cre) initial_cache_id = client_cre.get_cache_id() @@ -935,14 +1129,12 @@ def test_oauth2_client_credential_method_https(self): self.assertEqual(sess.auth.auth_ref.auth_token, self.TEST_TOKEN) self.assertEqual(initial_cache_id, client_cre.get_cache_id()) - resp_ok = { - 'status_code': 200 - } - self.requests_mock.post(f'{base_https}/test_api', - [resp_ok]) + resp_ok = {'status_code': 200} + self.requests_mock.post(f'{base_https}/test_api', [resp_ok]) resp = sess.post(f'{base_https}/test_api', authenticated=True) - self.assertRequestHeaderEqual('Authorization', - f'Bearer {oauth2_token}') + self.assertRequestHeaderEqual( + 'Authorization', f'Bearer {oauth2_token}' + ) self.assertRequestHeaderEqual('X-Auth-Token', self.TEST_TOKEN) self.assertEqual(200, resp.status_code) @@ -951,31 +1143,31 @@ def test_oauth2_client_credential_method_base_header_none(self): oauth2_endpoint = f'{base_https}/oauth_token' oauth2_token = 'HW9bB6oYWJywz6mAN_KyIBXlof15Pk' with unittest.mock.patch( - 'keystoneauth1.plugin.BaseAuthPlugin.' - 'get_headers') as co_mock: + 'keystoneauth1.plugin.BaseAuthPlugin.get_headers' + ) as co_mock: co_mock.return_value = None client_cre = v3.OAuth2ClientCredential( base_https, oauth2_endpoint=oauth2_endpoint, oauth2_client_id=self.TEST_CLIENT_CRED_ID, - oauth2_client_secret=self.TEST_CLIENT_CRED_SECRET + oauth2_client_secret=self.TEST_CLIENT_CRED_SECRET, ) oauth2_resp = { 'status_code': 200, 'json': { 'access_token': oauth2_token, 'expires_in': 3600, - 'token_type': 'Bearer' - } + 'token_type': 'Bearer', + }, } - self.requests_mock.post(oauth2_endpoint, - [oauth2_resp]) + self.requests_mock.post(oauth2_endpoint, [oauth2_resp]) sess = session.Session(auth=client_cre) auth_head = sess.get_auth_headers() self.assertNotIn('X-Auth-Token', auth_head) - self.assertEqual(f'Bearer {oauth2_token}', - auth_head['Authorization']) + self.assertEqual( + f'Bearer {oauth2_token}', auth_head['Authorization'] + ) def test_oauth2_client_credential_method_rm_auth(self): base_https = self.TEST_URL.replace('http:', 'https:') @@ -987,18 +1179,17 @@ def test_oauth2_client_credential_method_rm_auth(self): base_http, oauth2_endpoint=oauth2_endpoint, oauth2_client_id=self.TEST_CLIENT_CRED_ID, - oauth2_client_secret=self.TEST_CLIENT_CRED_SECRET + oauth2_client_secret=self.TEST_CLIENT_CRED_SECRET, ) oauth2_resp = { 'status_code': 200, 'json': { 'access_token': oauth2_token, 'expires_in': 3600, - 'token_type': 'Bearer' - } + 'token_type': 'Bearer', + }, } - self.requests_mock.post(oauth2_endpoint, - [oauth2_resp]) + self.requests_mock.post(oauth2_endpoint, [oauth2_resp]) sess = session.Session(auth=client_cre) initial_cache_id = client_cre.get_cache_id() @@ -1010,14 +1201,12 @@ def test_oauth2_client_credential_method_rm_auth(self): self.assertEqual(sess.auth.auth_ref.auth_token, self.TEST_TOKEN) self.assertEqual(initial_cache_id, client_cre.get_cache_id()) - resp_ok = { - 'status_code': 200 - } - self.requests_mock.post(f'{base_http}/test_api', - [resp_ok]) + resp_ok = {'status_code': 200} + self.requests_mock.post(f'{base_http}/test_api', [resp_ok]) resp = sess.post(f'{base_http}/test_api', authenticated=True) - self.assertRequestHeaderEqual('Authorization', - f'Bearer {oauth2_token}') + self.assertRequestHeaderEqual( + 'Authorization', f'Bearer {oauth2_token}' + ) self.assertRequestHeaderEqual('X-Auth-Token', self.TEST_TOKEN) self.assertEqual(200, resp.status_code) @@ -1026,22 +1215,22 @@ def test_oauth2_client_credential_method_other_not_rm_auth(self): other_auth_token = 'HW9bB6oYWJywz6mAN_KyIBXlof15Pk' self.stub_auth(json=self.TEST_APP_CRED_TOKEN_RESPONSE) with unittest.mock.patch( - 'keystoneauth1.identity.v3.Password.get_headers') as co_mock: + 'keystoneauth1.identity.v3.Password.get_headers' + ) as co_mock: co_mock.return_value = { 'X-Auth-Token': self.TEST_TOKEN, - 'Authorization': other_auth_token + 'Authorization': other_auth_token, } - pass_auth = v3.Password(base_https, - username=self.TEST_USER, - password=self.TEST_PASS, - include_catalog=False) + pass_auth = v3.Password( + base_https, + username=self.TEST_USER, + password=self.TEST_PASS, + include_catalog=False, + ) sess = session.Session(auth=pass_auth) - resp_ok = { - 'status_code': 200 - } - self.requests_mock.post(f'{base_https}/test_api', - [resp_ok]) + resp_ok = {'status_code': 200} + self.requests_mock.post(f'{base_https}/test_api', [resp_ok]) resp = sess.post(f'{base_https}/test_api', authenticated=True) self.assertRequestHeaderEqual('Authorization', other_auth_token) self.assertRequestHeaderEqual('X-Auth-Token', self.TEST_TOKEN) @@ -1056,23 +1245,20 @@ def test_oauth2_client_credential_method_500(self): base_https, oauth2_endpoint=oauth2_endpoint, oauth2_client_id=self.TEST_CLIENT_CRED_ID, - oauth2_client_secret=self.TEST_CLIENT_CRED_SECRET + oauth2_client_secret=self.TEST_CLIENT_CRED_SECRET, ) oauth2_resp = { 'status_code': 500, 'json': { 'error': 'other_error', - 'error_description': - 'Unknown error is occur.' - } + 'error_description': 'Unknown error is occur.', + }, } - self.requests_mock.post(oauth2_endpoint, - [oauth2_resp]) + self.requests_mock.post(oauth2_endpoint, [oauth2_resp]) sess = session.Session(auth=client_cre) err = self.assertRaises(ClientException, sess.get_auth_headers) - self.assertEqual('Unknown error is occur.', - str(err)) + self.assertEqual('Unknown error is occur.', str(err)) def test_oauth2_client_credential_reauth_called_https(self): base_https = self.TEST_URL.replace('http:', 'https:') @@ -1082,18 +1268,17 @@ def test_oauth2_client_credential_reauth_called_https(self): base_https, oauth2_endpoint=oauth2_endpoint, oauth2_client_id='clientcredid', - oauth2_client_secret='secret' + oauth2_client_secret='secret', ) oauth2_resp = { 'status_code': 200, 'json': { 'access_token': oauth2_token, 'expires_in': 3600, - 'token_type': 'Bearer' - } + 'token_type': 'Bearer', + }, } - self.requests_mock.post(oauth2_endpoint, - [oauth2_resp]) + self.requests_mock.post(oauth2_endpoint, [oauth2_resp]) sess = session.Session(auth=auth) @@ -1102,18 +1287,19 @@ def test_oauth2_client_credential_reauth_called_https(self): 'status_code': 200, 'headers': { 'Content-Type': 'application/json', - 'x-subject-token': self.TEST_TOKEN + 'x-subject-token': self.TEST_TOKEN, }, - 'text': resp_text + 'text': resp_text, } - self.requests_mock.post(f'{base_https}/auth/tokens', - [resp_ok, - {'text': 'Failed', 'status_code': 401}, - resp_ok]) + self.requests_mock.post( + f'{base_https}/auth/tokens', + [resp_ok, {'text': 'Failed', 'status_code': 401}, resp_ok], + ) resp = sess.post(f'{base_https}/auth/tokens', authenticated=True) - self.assertRequestHeaderEqual('Authorization', - f'Bearer {oauth2_token}') + self.assertRequestHeaderEqual( + 'Authorization', f'Bearer {oauth2_token}' + ) self.assertEqual(200, resp.status_code) self.assertEqual(resp_text, resp.text) @@ -1125,7 +1311,7 @@ def test_oauth2_mtls_client_credential_method(self): a = v3.OAuth2mTlsClientCredential( self.TEST_URL, oauth2_endpoint=oauth2_endpoint, - oauth2_client_id=self.TEST_CLIENT_CRED_ID + oauth2_client_id=self.TEST_CLIENT_CRED_ID, ) oauth2_post_resp = { @@ -1133,36 +1319,38 @@ def test_oauth2_mtls_client_credential_method(self): 'json': { 'access_token': oauth2_token, 'expires_in': 3600, - 'token_type': 'Bearer' - } + 'token_type': 'Bearer', + }, } self.requests_mock.post(oauth2_endpoint, [oauth2_post_resp]) token_verify_resp = { 'status_code': 200, - 'json': { - **self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE - } + 'json': {**self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE}, } self.requests_mock.get(token_endpoint, [token_verify_resp]) sess = session.Session(auth=a) auth_ref = a.get_auth_ref(sess) self.assertEqual(auth_ref.auth_token, oauth2_token) - self.assertEqual(auth_ref._data, - self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE) + self.assertEqual(auth_ref._data, self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE) self.assertEqual( auth_ref.project_id, - self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE.get( - 'token', {}).get('project', {}).get('id')) + self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE.get('token', {}) + .get('project', {}) + .get('id'), + ) self.assertIsNone(auth_ref.domain_id) self.assertEqual( auth_ref.oauth2_credential, - self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE.get( - 'token', {}).get('oauth2_credential')) + self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE.get('token', {}).get( + 'oauth2_credential' + ), + ) self.assertEqual( auth_ref.oauth2_credential_thumbprint, - self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE.get( - 'token', {}).get('oauth2_credential', {}).get('x5t#S256') + self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE.get('token', {}) + .get('oauth2_credential', {}) + .get('x5t#S256'), ) auth_head = sess.get_auth_headers() @@ -1177,7 +1365,7 @@ def test_oauth2_mtls_client_credential_method_without_v3(self): a = v3.OAuth2mTlsClientCredential( self.TEST_URL.replace('v3', ''), oauth2_endpoint=oauth2_endpoint, - oauth2_client_id=self.TEST_CLIENT_CRED_ID + oauth2_client_id=self.TEST_CLIENT_CRED_ID, ) oauth2_post_resp = { @@ -1185,31 +1373,31 @@ def test_oauth2_mtls_client_credential_method_without_v3(self): 'json': { 'access_token': oauth2_token, 'expires_in': 3600, - 'token_type': 'Bearer' - } + 'token_type': 'Bearer', + }, } self.requests_mock.post(oauth2_endpoint, [oauth2_post_resp]) token_verify_resp = { 'status_code': 200, - 'json': { - **self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE - } + 'json': {**self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE}, } self.requests_mock.get(token_endpoint, [token_verify_resp]) sess = session.Session(auth=a) auth_ref = a.get_auth_ref(sess) self.assertEqual(auth_ref.auth_token, oauth2_token) - self.assertEqual(auth_ref._data, - self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE) + self.assertEqual(auth_ref._data, self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE) self.assertEqual( auth_ref.oauth2_credential, - self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE.get( - 'token', {}).get('oauth2_credential')) + self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE.get('token', {}).get( + 'oauth2_credential' + ), + ) self.assertEqual( auth_ref.oauth2_credential_thumbprint, - self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE.get( - 'token', {}).get('oauth2_credential', {}).get('x5t#S256') + self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE.get('token', {}) + .get('oauth2_credential', {}) + .get('x5t#S256'), ) auth_head = sess.get_auth_headers() self.assertEqual(f'Bearer {oauth2_token}', auth_head['Authorization']) @@ -1223,7 +1411,7 @@ def test_oauth2_mtls_client_credential_method_resp_invalid_json(self): a = v3.OAuth2mTlsClientCredential( self.TEST_URL, oauth2_endpoint=oauth2_endpoint, - oauth2_client_id=self.TEST_CLIENT_CRED_ID + oauth2_client_id=self.TEST_CLIENT_CRED_ID, ) oauth2_post_resp = { @@ -1231,14 +1419,11 @@ def test_oauth2_mtls_client_credential_method_resp_invalid_json(self): 'json': { 'access_token': oauth2_token, 'expires_in': 3600, - 'token_type': 'Bearer' - } + 'token_type': 'Bearer', + }, } self.requests_mock.post(oauth2_endpoint, [oauth2_post_resp]) - token_verify_resp = { - 'status_code': 200, - 'text': 'invalid json' - } + token_verify_resp = {'status_code': 200, 'text': 'invalid json'} self.requests_mock.get(token_endpoint, [token_verify_resp]) sess = session.Session(auth=a) @@ -1252,7 +1437,7 @@ def test_oauth2_mtls_client_credential_method_resp_without_token(self): a = v3.OAuth2mTlsClientCredential( self.TEST_URL, oauth2_endpoint=oauth2_endpoint, - oauth2_client_id=self.TEST_CLIENT_CRED_ID + oauth2_client_id=self.TEST_CLIENT_CRED_ID, ) oauth2_post_resp = { @@ -1260,16 +1445,11 @@ def test_oauth2_mtls_client_credential_method_resp_without_token(self): 'json': { 'access_token': oauth2_token, 'expires_in': 3600, - 'token_type': 'Bearer' - } + 'token_type': 'Bearer', + }, } self.requests_mock.post(oauth2_endpoint, [oauth2_post_resp]) - token_verify_resp = { - 'status_code': 200, - 'json': { - 'without_token': {} - } - } + token_verify_resp = {'status_code': 200, 'json': {'without_token': {}}} self.requests_mock.get(token_endpoint, [token_verify_resp]) sess = session.Session(auth=a) @@ -1281,13 +1461,10 @@ def test_oauth2_mtls_client_credential_method_client_exception(self): a = v3.OAuth2mTlsClientCredential( self.TEST_URL, oauth2_endpoint=oauth2_endpoint, - oauth2_client_id=self.TEST_CLIENT_CRED_ID + oauth2_client_id=self.TEST_CLIENT_CRED_ID, ) - oauth2_post_resp = { - 'status_code': 400, - 'json': {} - } + oauth2_post_resp = {'status_code': 400, 'json': {}} self.requests_mock.post(oauth2_endpoint, [oauth2_post_resp]) sess = session.Session(auth=a) @@ -1301,30 +1478,27 @@ def test_oauth2_mtls_client_credential_method_base_header_none(self): a = v3.OAuth2mTlsClientCredential( self.TEST_URL, oauth2_endpoint=oauth2_endpoint, - oauth2_client_id=self.TEST_CLIENT_CRED_ID + oauth2_client_id=self.TEST_CLIENT_CRED_ID, ) oauth2_post_resp = { 'status_code': 200, 'json': { 'access_token': oauth2_token, 'expires_in': 3600, - 'token_type': 'Bearer' - } + 'token_type': 'Bearer', + }, } - self.requests_mock.post(oauth2_endpoint, - [oauth2_post_resp]) + self.requests_mock.post(oauth2_endpoint, [oauth2_post_resp]) token_verify_resp = { 'status_code': 200, - 'json': { - **self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE - } + 'json': {**self.TEST_OAUTH2_MTLS_TOKEN_RESPONSE}, } self.requests_mock.get(token_endpoint, [token_verify_resp]) sess = session.Session(auth=a) with unittest.mock.patch( - 'keystoneauth1.plugin.BaseAuthPlugin.' - 'get_headers') as co_mock: + 'keystoneauth1.plugin.BaseAuthPlugin.get_headers' + ) as co_mock: co_mock.return_value = None auth_head = sess.get_auth_headers() self.assertEqual('Bearer None', auth_head['Authorization']) diff --git a/keystoneauth1/tests/unit/identity/test_identity_v3_federation.py b/keystoneauth1/tests/unit/identity/test_identity_v3_federation.py index 34fa60a5..c104f545 100644 --- a/keystoneauth1/tests/unit/identity/test_identity_v3_federation.py +++ b/keystoneauth1/tests/unit/identity/test_identity_v3_federation.py @@ -24,7 +24,6 @@ class TesterFederationPlugin(v3.FederationBaseAuth): - def get_unscoped_auth_ref(self, sess, **kwargs): # This would go and talk to an idp or something resp = sess.post(self.federated_token_url, authenticated=False) @@ -32,11 +31,10 @@ def get_unscoped_auth_ref(self, sess, **kwargs): class V3FederatedPlugin(utils.TestCase): - AUTH_URL = 'http://keystone/v3' def setUp(self): - super(V3FederatedPlugin, self).setUp() + super().setUp() self.unscoped_token = fixture.V3Token() self.unscoped_token_id = uuid.uuid4().hex @@ -46,26 +44,30 @@ def setUp(self): self.scoped_token_id = uuid.uuid4().hex s = self.scoped_token.add_service('compute', name='nova') - s.add_standard_endpoints(public='http://nova/public', - admin='http://nova/admin', - internal='http://nova/internal') + s.add_standard_endpoints( + public='http://nova/public', + admin='http://nova/admin', + internal='http://nova/internal', + ) self.idp = uuid.uuid4().hex self.protocol = uuid.uuid4().hex - self.token_url = ('%s/OS-FEDERATION/identity_providers/%s/protocols/%s' - '/auth' % (self.AUTH_URL, self.idp, self.protocol)) + self.token_url = ( + f'{self.AUTH_URL}/OS-FEDERATION/identity_providers/{self.idp}/protocols/{self.protocol}' + '/auth' + ) headers = {'X-Subject-Token': self.unscoped_token_id} - self.unscoped_mock = self.requests_mock.post(self.token_url, - json=self.unscoped_token, - headers=headers) + self.unscoped_mock = self.requests_mock.post( + self.token_url, json=self.unscoped_token, headers=headers + ) headers = {'X-Subject-Token': self.scoped_token_id} auth_url = self.AUTH_URL + '/auth/tokens' - self.scoped_mock = self.requests_mock.post(auth_url, - json=self.scoped_token, - headers=headers) + self.scoped_mock = self.requests_mock.post( + auth_url, json=self.scoped_token, headers=headers + ) def get_plugin(self, **kwargs): kwargs.setdefault('auth_url', self.AUTH_URL) @@ -98,9 +100,8 @@ def test_scoped_behaviour(self): class K2KAuthPluginTest(utils.TestCase): - TEST_ROOT_URL = 'http://127.0.0.1:5000/' - TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v3') + TEST_URL = '{}{}'.format(TEST_ROOT_URL, 'v3') TEST_PASS = 'password' REQUEST_ECP_URL = TEST_URL + '/auth/OS-FEDERATION/saml2/ecp' @@ -108,39 +109,45 @@ class K2KAuthPluginTest(utils.TestCase): SP_ROOT_URL = 'https://sp1.com/v3' SP_ID = 'sp1' SP_URL = 'https://sp1.com/Shibboleth.sso/SAML2/ECP' - SP_AUTH_URL = (SP_ROOT_URL + - '/OS-FEDERATION/identity_providers' - '/testidp/protocols/saml2/auth') + SP_AUTH_URL = ( + SP_ROOT_URL + '/OS-FEDERATION/identity_providers' + '/testidp/protocols/saml2/auth' + ) SERVICE_PROVIDER_DICT = { 'id': SP_ID, 'auth_url': SP_AUTH_URL, - 'sp_url': SP_URL + 'sp_url': SP_URL, } def setUp(self): - super(K2KAuthPluginTest, self).setUp() + super().setUp() self.token_v3 = fixture.V3Token() self.token_v3.add_service_provider( - self.SP_ID, self.SP_AUTH_URL, self.SP_URL) + self.SP_ID, self.SP_AUTH_URL, self.SP_URL + ) self.session = session.Session() self.k2kplugin = self.get_plugin() def _get_base_plugin(self): - self.stub_url('POST', ['auth', 'tokens'], - headers={'X-Subject-Token': uuid.uuid4().hex}, - json=self.token_v3) - return v3.Password(self.TEST_URL, - username=self.TEST_USER, - password=self.TEST_PASS) + self.stub_url( + 'POST', + ['auth', 'tokens'], + headers={'X-Subject-Token': uuid.uuid4().hex}, + json=self.token_v3, + ) + return v3.Password( + self.TEST_URL, username=self.TEST_USER, password=self.TEST_PASS + ) def _mock_k2k_flow_urls(self, redirect_code=302): # List versions available for auth self.requests_mock.get( self.TEST_URL, json={'version': fixture.V3Discovery(self.TEST_URL)}, - headers={'Content-Type': 'application/json'}) + headers={'Content-Type': 'application/json'}, + ) # The IdP should return a ECP wrapped assertion when requested self.requests_mock.register_uri( @@ -148,7 +155,8 @@ def _mock_k2k_flow_urls(self, redirect_code=302): self.REQUEST_ECP_URL, content=bytes(k2k_fixtures.ECP_ENVELOPE, 'latin-1'), headers={'Content-Type': 'application/vnd.paos+xml'}, - status_code=200) + status_code=200, + ) # The SP should respond with a redirect (302 or 303) self.requests_mock.register_uri( @@ -156,14 +164,16 @@ def _mock_k2k_flow_urls(self, redirect_code=302): self.SP_URL, content=bytes(k2k_fixtures.TOKEN_BASED_ECP, 'latin-1'), headers={'Content-Type': 'application/vnd.paos+xml'}, - status_code=redirect_code) + status_code=redirect_code, + ) # Should not follow the redirect URL, but use the auth_url attribute self.requests_mock.register_uri( 'GET', self.SP_AUTH_URL, json=k2k_fixtures.UNSCOPED_TOKEN, - headers={'X-Subject-Token': k2k_fixtures.UNSCOPED_TOKEN_HEADER}) + headers={'X-Subject-Token': k2k_fixtures.UNSCOPED_TOKEN_HEADER}, + ) def get_plugin(self, **kwargs): kwargs.setdefault('base_plugin', self._get_base_plugin()) @@ -178,84 +188,108 @@ def test_fail_getting_ecp_assertion(self): self.requests_mock.get( self.TEST_URL, json={'version': fixture.V3Discovery(self.TEST_URL)}, - headers={'Content-Type': 'application/json'}) + headers={'Content-Type': 'application/json'}, + ) self.requests_mock.register_uri( - 'POST', self.REQUEST_ECP_URL, - status_code=401) + 'POST', self.REQUEST_ECP_URL, status_code=401 + ) - self.assertRaises(exceptions.AuthorizationFailure, - self.k2kplugin._get_ecp_assertion, - self.session) + self.assertRaises( + exceptions.AuthorizationFailure, + self.k2kplugin._get_ecp_assertion, + self.session, + ) def test_get_ecp_assertion_empty_response(self): self.requests_mock.get( self.TEST_URL, json={'version': fixture.V3Discovery(self.TEST_URL)}, - headers={'Content-Type': 'application/json'}) + headers={'Content-Type': 'application/json'}, + ) self.requests_mock.register_uri( - 'POST', self.REQUEST_ECP_URL, + 'POST', + self.REQUEST_ECP_URL, headers={'Content-Type': 'application/vnd.paos+xml'}, - content=b'', status_code=200) + content=b'', + status_code=200, + ) - self.assertRaises(exceptions.InvalidResponse, - self.k2kplugin._get_ecp_assertion, - self.session) + self.assertRaises( + exceptions.InvalidResponse, + self.k2kplugin._get_ecp_assertion, + self.session, + ) def test_get_ecp_assertion_wrong_headers(self): self.requests_mock.get( self.TEST_URL, json={'version': fixture.V3Discovery(self.TEST_URL)}, - headers={'Content-Type': 'application/json'}) + headers={'Content-Type': 'application/json'}, + ) self.requests_mock.register_uri( - 'POST', self.REQUEST_ECP_URL, + 'POST', + self.REQUEST_ECP_URL, headers={'Content-Type': uuid.uuid4().hex}, - content=b'', status_code=200) + content=b'', + status_code=200, + ) - self.assertRaises(exceptions.InvalidResponse, - self.k2kplugin._get_ecp_assertion, - self.session) + self.assertRaises( + exceptions.InvalidResponse, + self.k2kplugin._get_ecp_assertion, + self.session, + ) def test_send_ecp_authn_response(self): self._mock_k2k_flow_urls() # Perform the request response = self.k2kplugin._send_service_provider_ecp_authn_response( - self.session, self.SP_URL, self.SP_AUTH_URL) + self.session, self.SP_URL, self.SP_AUTH_URL + ) # Check the response - self.assertEqual(k2k_fixtures.UNSCOPED_TOKEN_HEADER, - response.headers['X-Subject-Token']) + self.assertEqual( + k2k_fixtures.UNSCOPED_TOKEN_HEADER, + response.headers['X-Subject-Token'], + ) def test_send_ecp_authn_response_303_redirect(self): self._mock_k2k_flow_urls(redirect_code=303) # Perform the request response = self.k2kplugin._send_service_provider_ecp_authn_response( - self.session, self.SP_URL, self.SP_AUTH_URL) + self.session, self.SP_URL, self.SP_AUTH_URL + ) # Check the response - self.assertEqual(k2k_fixtures.UNSCOPED_TOKEN_HEADER, - response.headers['X-Subject-Token']) + self.assertEqual( + k2k_fixtures.UNSCOPED_TOKEN_HEADER, + response.headers['X-Subject-Token'], + ) def test_end_to_end_workflow(self): self._mock_k2k_flow_urls() auth_ref = self.k2kplugin.get_auth_ref(self.session) - self.assertEqual(k2k_fixtures.UNSCOPED_TOKEN_HEADER, - auth_ref.auth_token) + self.assertEqual( + k2k_fixtures.UNSCOPED_TOKEN_HEADER, auth_ref.auth_token + ) def test_end_to_end_workflow_303_redirect(self): self._mock_k2k_flow_urls(redirect_code=303) auth_ref = self.k2kplugin.get_auth_ref(self.session) - self.assertEqual(k2k_fixtures.UNSCOPED_TOKEN_HEADER, - auth_ref.auth_token) + self.assertEqual( + k2k_fixtures.UNSCOPED_TOKEN_HEADER, auth_ref.auth_token + ) def test_end_to_end_with_generic_password(self): # List versions available for auth self.requests_mock.get( self.TEST_ROOT_URL, json=fixture.DiscoveryList(self.TEST_ROOT_URL), - headers={'Content-Type': 'application/json'}) + headers={'Content-Type': 'application/json'}, + ) # The IdP should return a ECP wrapped assertion when requested self.requests_mock.register_uri( @@ -263,7 +297,8 @@ def test_end_to_end_with_generic_password(self): self.REQUEST_ECP_URL, content=bytes(k2k_fixtures.ECP_ENVELOPE, 'latin-1'), headers={'Content-Type': 'application/vnd.paos+xml'}, - status_code=200) + status_code=200, + ) # The SP should respond with a redirect (302 or 303) self.requests_mock.register_uri( @@ -271,24 +306,33 @@ def test_end_to_end_with_generic_password(self): self.SP_URL, content=bytes(k2k_fixtures.TOKEN_BASED_ECP, 'latin-1'), headers={'Content-Type': 'application/vnd.paos+xml'}, - status_code=302) + status_code=302, + ) # Should not follow the redirect URL, but use the auth_url attribute self.requests_mock.register_uri( 'GET', self.SP_AUTH_URL, json=k2k_fixtures.UNSCOPED_TOKEN, - headers={'X-Subject-Token': k2k_fixtures.UNSCOPED_TOKEN_HEADER}) + headers={'X-Subject-Token': k2k_fixtures.UNSCOPED_TOKEN_HEADER}, + ) - self.stub_url('POST', ['auth', 'tokens'], - headers={'X-Subject-Token': uuid.uuid4().hex}, - json=self.token_v3) + self.stub_url( + 'POST', + ['auth', 'tokens'], + headers={'X-Subject-Token': uuid.uuid4().hex}, + json=self.token_v3, + ) - plugin = identity.Password(self.TEST_ROOT_URL, - username=self.TEST_USER, - password=self.TEST_PASS, - user_domain_id='default') + plugin = identity.Password( + self.TEST_ROOT_URL, + username=self.TEST_USER, + password=self.TEST_PASS, + user_domain_id='default', + ) k2kplugin = self.get_plugin(base_plugin=plugin) - self.assertEqual(k2k_fixtures.UNSCOPED_TOKEN_HEADER, - k2kplugin.get_token(self.session)) + self.assertEqual( + k2k_fixtures.UNSCOPED_TOKEN_HEADER, + k2kplugin.get_token(self.session), + ) diff --git a/keystoneauth1/tests/unit/identity/test_identity_v3_oidc.py b/keystoneauth1/tests/unit/identity/test_identity_v3_oidc.py index 254ef3b2..d55afe43 100644 --- a/keystoneauth1/tests/unit/identity/test_identity_v3_oidc.py +++ b/keystoneauth1/tests/unit/identity/test_identity_v3_oidc.py @@ -28,10 +28,9 @@ BUILTIN_INPUT = "builtins.input" -class BaseOIDCTests(object): - +class BaseOIDCTests: def setUp(self): - super(BaseOIDCTests, self).setUp() + super().setUp() self.session = session.Session() self.AUTH_URL = 'http://keystone:5000/v3' @@ -44,14 +43,16 @@ def setUp(self): self.CLIENT_SECRET = uuid.uuid4().hex self.ACCESS_TOKEN = uuid.uuid4().hex self.ACCESS_TOKEN_ENDPOINT = 'https://localhost:8020/oidc/token' - self.FEDERATION_AUTH_URL = '%s/%s' % ( + self.FEDERATION_AUTH_URL = '{}/{}'.format( self.AUTH_URL, - 'OS-FEDERATION/identity_providers/bluepages/protocols/oidc/auth') + 'OS-FEDERATION/identity_providers/bluepages/protocols/oidc/auth', + ) self.REDIRECT_URL = 'urn:ietf:wg:oauth:2.0:oob' self.CODE = '4/M9TNz2G9WVwYxSjx0w9AgA1bOmryJltQvOhQMq0czJs.cnLNVAfqwG' - self.DISCOVERY_URL = ('https://localhost:8020/oidc/.well-known/' - 'openid-configuration') + self.DISCOVERY_URL = ( + 'https://localhost:8020/oidc/.well-known/openid-configuration' + ) self.GRANT_TYPE = None def test_grant_type_and_plugin_missmatch(self): @@ -63,7 +64,7 @@ def test_grant_type_and_plugin_missmatch(self): self.PROTOCOL, client_id=self.CLIENT_ID, client_secret=self.CLIENT_SECRET, - grant_type=uuid.uuid4().hex + grant_type=uuid.uuid4().hex, ) def test_can_pass_grant_type_but_warning_is_issued(self): @@ -75,14 +76,14 @@ def test_can_pass_grant_type_but_warning_is_issued(self): self.PROTOCOL, client_id=self.CLIENT_ID, client_secret=self.CLIENT_SECRET, - grant_type=self.GRANT_TYPE) + grant_type=self.GRANT_TYPE, + ) assert len(w) == 1 assert issubclass(w[-1].category, DeprecationWarning) assert "grant_type" in str(w[-1].message) def test_discovery_not_found(self): - self.requests_mock.get("http://not.found", - status_code=404) + self.requests_mock.get("http://not.found", status_code=404) plugin = self.plugin.__class__( self.AUTH_URL, @@ -90,14 +91,16 @@ def test_discovery_not_found(self): self.PROTOCOL, client_id=self.CLIENT_ID, client_secret=self.CLIENT_SECRET, - discovery_endpoint="http://not.found") + discovery_endpoint="http://not.found", + ) - self.assertRaises(exceptions.http.NotFound, - plugin._get_discovery_document, - self.session) + self.assertRaises( + exceptions.http.NotFound, + plugin._get_discovery_document, + self.session, + ) def test_no_discovery(self): - plugin = self.plugin.__class__( self.AUTH_URL, self.IDENTITY_PROVIDER, @@ -106,53 +109,65 @@ def test_no_discovery(self): client_secret=self.CLIENT_SECRET, access_token_endpoint=self.ACCESS_TOKEN_ENDPOINT, ) - self.assertEqual(self.ACCESS_TOKEN_ENDPOINT, - plugin.access_token_endpoint) + self.assertEqual( + self.ACCESS_TOKEN_ENDPOINT, plugin.access_token_endpoint + ) def test_load_discovery(self): - self.requests_mock.get(self.DISCOVERY_URL, - json=oidc_fixtures.DISCOVERY_DOCUMENT) - - plugin = self.plugin.__class__(self.AUTH_URL, - self.IDENTITY_PROVIDER, - self.PROTOCOL, - client_id=self.CLIENT_ID, - client_secret=self.CLIENT_SECRET, - discovery_endpoint=self.DISCOVERY_URL) + self.requests_mock.get( + self.DISCOVERY_URL, json=oidc_fixtures.DISCOVERY_DOCUMENT + ) + + plugin = self.plugin.__class__( + self.AUTH_URL, + self.IDENTITY_PROVIDER, + self.PROTOCOL, + client_id=self.CLIENT_ID, + client_secret=self.CLIENT_SECRET, + discovery_endpoint=self.DISCOVERY_URL, + ) self.assertEqual( oidc_fixtures.DISCOVERY_DOCUMENT["token_endpoint"], - plugin._get_access_token_endpoint(self.session) + plugin._get_access_token_endpoint(self.session), ) def test_no_access_token_endpoint(self): - plugin = self.plugin.__class__(self.AUTH_URL, - self.IDENTITY_PROVIDER, - self.PROTOCOL, - client_id=self.CLIENT_ID, - client_secret=self.CLIENT_SECRET) + plugin = self.plugin.__class__( + self.AUTH_URL, + self.IDENTITY_PROVIDER, + self.PROTOCOL, + client_id=self.CLIENT_ID, + client_secret=self.CLIENT_SECRET, + ) - self.assertRaises(exceptions.OidcAccessTokenEndpointNotFound, - plugin._get_access_token_endpoint, - self.session) + self.assertRaises( + exceptions.OidcAccessTokenEndpointNotFound, + plugin._get_access_token_endpoint, + self.session, + ) def test_invalid_discovery_document(self): - self.requests_mock.get(self.DISCOVERY_URL, - json={}) + self.requests_mock.get(self.DISCOVERY_URL, json={}) - plugin = self.plugin.__class__(self.AUTH_URL, - self.IDENTITY_PROVIDER, - self.PROTOCOL, - client_id=self.CLIENT_ID, - client_secret=self.CLIENT_SECRET, - discovery_endpoint=self.DISCOVERY_URL) + plugin = self.plugin.__class__( + self.AUTH_URL, + self.IDENTITY_PROVIDER, + self.PROTOCOL, + client_id=self.CLIENT_ID, + client_secret=self.CLIENT_SECRET, + discovery_endpoint=self.DISCOVERY_URL, + ) - self.assertRaises(exceptions.InvalidOidcDiscoveryDocument, - plugin._get_discovery_document, - self.session) + self.assertRaises( + exceptions.InvalidOidcDiscoveryDocument, + plugin._get_discovery_document, + self.session, + ) def test_load_discovery_override_by_endpoints(self): - self.requests_mock.get(self.DISCOVERY_URL, - json=oidc_fixtures.DISCOVERY_DOCUMENT) + self.requests_mock.get( + self.DISCOVERY_URL, json=oidc_fixtures.DISCOVERY_DOCUMENT + ) access_token_endpoint = uuid.uuid4().hex plugin = self.plugin.__class__( @@ -162,30 +177,37 @@ def test_load_discovery_override_by_endpoints(self): client_id=self.CLIENT_ID, client_secret=self.CLIENT_SECRET, discovery_endpoint=self.DISCOVERY_URL, - access_token_endpoint=access_token_endpoint + access_token_endpoint=access_token_endpoint, + ) + self.assertEqual( + access_token_endpoint, + plugin._get_access_token_endpoint(self.session), ) - self.assertEqual(access_token_endpoint, - plugin._get_access_token_endpoint(self.session)) def test_wrong_grant_type(self): - self.requests_mock.get(self.DISCOVERY_URL, - json={"grant_types_supported": ["foo", "bar"]}) + self.requests_mock.get( + self.DISCOVERY_URL, json={"grant_types_supported": ["foo", "bar"]} + ) - plugin = self.plugin.__class__(self.AUTH_URL, - self.IDENTITY_PROVIDER, - self.PROTOCOL, - client_id=self.CLIENT_ID, - client_secret=self.CLIENT_SECRET, - discovery_endpoint=self.DISCOVERY_URL) + plugin = self.plugin.__class__( + self.AUTH_URL, + self.IDENTITY_PROVIDER, + self.PROTOCOL, + client_id=self.CLIENT_ID, + client_secret=self.CLIENT_SECRET, + discovery_endpoint=self.DISCOVERY_URL, + ) - self.assertRaises(exceptions.OidcPluginNotSupported, - plugin.get_unscoped_auth_ref, - self.session) + self.assertRaises( + exceptions.OidcPluginNotSupported, + plugin.get_unscoped_auth_ref, + self.session, + ) class OIDCClientCredentialsTests(BaseOIDCTests, utils.TestCase): def setUp(self): - super(OIDCClientCredentialsTests, self).setUp() + super().setUp() self.GRANT_TYPE = 'client_credentials' @@ -196,14 +218,16 @@ def setUp(self): client_id=self.CLIENT_ID, client_secret=self.CLIENT_SECRET, access_token_endpoint=self.ACCESS_TOKEN_ENDPOINT, - project_name=self.PROJECT_NAME) + project_name=self.PROJECT_NAME, + ) def test_initial_call_to_get_access_token(self): """Test initial call, expect JSON access token.""" # Mock the output that creates the access token self.requests_mock.post( self.ACCESS_TOKEN_ENDPOINT, - json=oidc_fixtures.ACCESS_TOKEN_VIA_PASSWORD_RESP) + json=oidc_fixtures.ACCESS_TOKEN_VIA_PASSWORD_RESP, + ) # Prep all the values and send the request scope = 'profile email' @@ -223,31 +247,34 @@ def test_second_call_to_protected_url(self): self.requests_mock.post( self.FEDERATION_AUTH_URL, json=oidc_fixtures.UNSCOPED_TOKEN, - headers={'X-Subject-Token': KEYSTONE_TOKEN_VALUE}) + headers={'X-Subject-Token': KEYSTONE_TOKEN_VALUE}, + ) - res = self.plugin._get_keystone_token(self.session, - self.ACCESS_TOKEN) + res = self.plugin._get_keystone_token(self.session, self.ACCESS_TOKEN) # Verify the request matches the expected structure self.assertEqual(self.FEDERATION_AUTH_URL, res.request.url) self.assertEqual('POST', res.request.method) headers = {'Authorization': 'Bearer ' + self.ACCESS_TOKEN} - self.assertEqual(headers['Authorization'], - res.request.headers['Authorization']) + self.assertEqual( + headers['Authorization'], res.request.headers['Authorization'] + ) def test_end_to_end_workflow(self): """Test full OpenID Connect workflow.""" # Mock the output that creates the access token self.requests_mock.post( self.ACCESS_TOKEN_ENDPOINT, - json=oidc_fixtures.ACCESS_TOKEN_VIA_PASSWORD_RESP) + json=oidc_fixtures.ACCESS_TOKEN_VIA_PASSWORD_RESP, + ) # Mock the output that creates the keystone token self.requests_mock.post( self.FEDERATION_AUTH_URL, json=oidc_fixtures.UNSCOPED_TOKEN, - headers={'X-Subject-Token': KEYSTONE_TOKEN_VALUE}) + headers={'X-Subject-Token': KEYSTONE_TOKEN_VALUE}, + ) response = self.plugin.get_unscoped_auth_ref(self.session) self.assertEqual(KEYSTONE_TOKEN_VALUE, response.auth_token) @@ -255,7 +282,7 @@ def test_end_to_end_workflow(self): class OIDCPasswordTests(BaseOIDCTests, utils.TestCase): def setUp(self): - super(OIDCPasswordTests, self).setUp() + super().setUp() self.GRANT_TYPE = 'password' @@ -268,20 +295,26 @@ def setUp(self): access_token_endpoint=self.ACCESS_TOKEN_ENDPOINT, project_name=self.PROJECT_NAME, username=self.USER_NAME, - password=self.PASSWORD) + password=self.PASSWORD, + ) def test_initial_call_to_get_access_token(self): """Test initial call, expect JSON access token.""" # Mock the output that creates the access token self.requests_mock.post( self.ACCESS_TOKEN_ENDPOINT, - json=oidc_fixtures.ACCESS_TOKEN_VIA_PASSWORD_RESP) + json=oidc_fixtures.ACCESS_TOKEN_VIA_PASSWORD_RESP, + ) # Prep all the values and send the request grant_type = 'password' scope = 'profile email' - payload = {'grant_type': grant_type, 'username': self.USER_NAME, - 'password': self.PASSWORD, 'scope': scope} + payload = { + 'grant_type': grant_type, + 'username': self.USER_NAME, + 'password': self.PASSWORD, + 'scope': scope, + } self.plugin._get_access_token(self.session, payload) # Verify the request matches the expected structure @@ -297,31 +330,34 @@ def test_second_call_to_protected_url(self): self.requests_mock.post( self.FEDERATION_AUTH_URL, json=oidc_fixtures.UNSCOPED_TOKEN, - headers={'X-Subject-Token': KEYSTONE_TOKEN_VALUE}) + headers={'X-Subject-Token': KEYSTONE_TOKEN_VALUE}, + ) - res = self.plugin._get_keystone_token(self.session, - self.ACCESS_TOKEN) + res = self.plugin._get_keystone_token(self.session, self.ACCESS_TOKEN) # Verify the request matches the expected structure self.assertEqual(self.FEDERATION_AUTH_URL, res.request.url) self.assertEqual('POST', res.request.method) headers = {'Authorization': 'Bearer ' + self.ACCESS_TOKEN} - self.assertEqual(headers['Authorization'], - res.request.headers['Authorization']) + self.assertEqual( + headers['Authorization'], res.request.headers['Authorization'] + ) def test_end_to_end_workflow(self): """Test full OpenID Connect workflow.""" # Mock the output that creates the access token self.requests_mock.post( self.ACCESS_TOKEN_ENDPOINT, - json=oidc_fixtures.ACCESS_TOKEN_VIA_PASSWORD_RESP) + json=oidc_fixtures.ACCESS_TOKEN_VIA_PASSWORD_RESP, + ) # Mock the output that creates the keystone token self.requests_mock.post( self.FEDERATION_AUTH_URL, json=oidc_fixtures.UNSCOPED_TOKEN, - headers={'X-Subject-Token': KEYSTONE_TOKEN_VALUE}) + headers={'X-Subject-Token': KEYSTONE_TOKEN_VALUE}, + ) response = self.plugin.get_unscoped_auth_ref(self.session) self.assertEqual(KEYSTONE_TOKEN_VALUE, response.auth_token) @@ -332,14 +368,16 @@ def test_otp_while_generating_the_access_token(self, mock_input): self.plugin.idp_otp_key = "totp" otp = 123 new_otp = 111 - access_token = \ - oidc_fixtures.ACCESS_TOKEN_VIA_PASSWORD_RESP["access_token"] + access_token = oidc_fixtures.ACCESS_TOKEN_VIA_PASSWORD_RESP[ + "access_token" + ] mock_input.return_value = otp self.requests_mock.post( self.ACCESS_TOKEN_ENDPOINT, - json=oidc_fixtures.ACCESS_TOKEN_VIA_PASSWORD_RESP) + json=oidc_fixtures.ACCESS_TOKEN_VIA_PASSWORD_RESP, + ) # Verify if the OTP is set in the session and if the request is OK payload = self.plugin.get_payload(self.session) @@ -355,7 +393,7 @@ def test_otp_while_generating_the_access_token(self, mock_input): class OIDCAuthorizationGrantTests(BaseOIDCTests, utils.TestCase): def setUp(self): - super(OIDCAuthorizationGrantTests, self).setUp() + super().setUp() self.GRANT_TYPE = 'authorization_code' @@ -368,20 +406,24 @@ def setUp(self): access_token_endpoint=self.ACCESS_TOKEN_ENDPOINT, redirect_uri=self.REDIRECT_URL, project_name=self.PROJECT_NAME, - code=self.CODE) + code=self.CODE, + ) def test_initial_call_to_get_access_token(self): """Test initial call, expect JSON access token.""" # Mock the output that creates the access token self.requests_mock.post( self.ACCESS_TOKEN_ENDPOINT, - json=oidc_fixtures.ACCESS_TOKEN_VIA_AUTH_GRANT_RESP) + json=oidc_fixtures.ACCESS_TOKEN_VIA_AUTH_GRANT_RESP, + ) # Prep all the values and send the request grant_type = 'authorization_code' - payload = {'grant_type': grant_type, - 'redirect_uri': self.REDIRECT_URL, - 'code': self.CODE} + payload = { + 'grant_type': grant_type, + 'redirect_uri': self.REDIRECT_URL, + 'code': self.CODE, + } self.plugin._get_access_token(self.session, payload) # Verify the request matches the expected structure @@ -398,7 +440,7 @@ def test_initial_call_to_get_access_token(self): # TestCase class OIDCTokenTests(utils.TestCase): def setUp(self): - super(OIDCTokenTests, self).setUp() + super().setUp() self.session = session.Session() @@ -408,16 +450,18 @@ def setUp(self): self.PROJECT_NAME = 'foo project' self.ACCESS_TOKEN = uuid.uuid4().hex - self.FEDERATION_AUTH_URL = '%s/%s' % ( + self.FEDERATION_AUTH_URL = '{}/{}'.format( self.AUTH_URL, - 'OS-FEDERATION/identity_providers/bluepages/protocols/oidc/auth') + 'OS-FEDERATION/identity_providers/bluepages/protocols/oidc/auth', + ) self.plugin = oidc.OidcAccessToken( self.AUTH_URL, self.IDENTITY_PROVIDER, self.PROTOCOL, access_token=self.ACCESS_TOKEN, - project_name=self.PROJECT_NAME) + project_name=self.PROJECT_NAME, + ) def test_end_to_end_workflow(self): """Test full OpenID Connect workflow.""" @@ -425,7 +469,8 @@ def test_end_to_end_workflow(self): self.requests_mock.post( self.FEDERATION_AUTH_URL, json=oidc_fixtures.UNSCOPED_TOKEN, - headers={'X-Subject-Token': KEYSTONE_TOKEN_VALUE}) + headers={'X-Subject-Token': KEYSTONE_TOKEN_VALUE}, + ) response = self.plugin.get_unscoped_auth_ref(self.session) self.assertEqual(KEYSTONE_TOKEN_VALUE, response.auth_token) @@ -433,11 +478,12 @@ def test_end_to_end_workflow(self): class OIDCDeviceAuthorizationTest(BaseOIDCTests, utils.TestCase): def setUp(self): - super(OIDCDeviceAuthorizationTest, self).setUp() + super().setUp() self.GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:device_code' - self.DEVICE_AUTH_ENDPOINT = \ + self.DEVICE_AUTH_ENDPOINT = ( 'https://localhost:8020/oidc/authorize/device' + ) self.plugin = oidc.OidcDeviceAuthorization( self.AUTH_URL, @@ -446,14 +492,15 @@ def setUp(self): client_id=self.CLIENT_ID, client_secret=self.CLIENT_SECRET, access_token_endpoint=self.ACCESS_TOKEN_ENDPOINT, - device_authorization_endpoint=self.DEVICE_AUTH_ENDPOINT) + device_authorization_endpoint=self.DEVICE_AUTH_ENDPOINT, + ) def test_get_device_authorization_request(self): """Test device authorization request.""" # Mock the output that creates the device code self.requests_mock.post( - self.DEVICE_AUTH_ENDPOINT, - json=oidc_fixtures.DEVICE_CODE_RESP) + self.DEVICE_AUTH_ENDPOINT, json=oidc_fixtures.DEVICE_CODE_RESP + ) result = self.plugin.get_payload(self.session) @@ -463,9 +510,12 @@ def test_get_device_authorization_request(self): self.assertEqual('POST', last_req.method) self.assertEqual( self._basic_header(self.CLIENT_ID, self.CLIENT_SECRET), - last_req.headers.get('Authorization')) - self.assertEqual(oidc_fixtures.DEVICE_CODE_RESP["device_code"], - result["device_code"]) + last_req.headers.get('Authorization'), + ) + self.assertEqual( + oidc_fixtures.DEVICE_CODE_RESP["device_code"], + result["device_code"], + ) def test_get_device_authorization_request_without_client_secret(self): """Test device authorization request, without client_secret. @@ -477,8 +527,8 @@ def test_get_device_authorization_request_without_client_secret(self): # Mock the output that creates the device code self.requests_mock.post( - self.DEVICE_AUTH_ENDPOINT, - json=oidc_fixtures.DEVICE_CODE_RESP) + self.DEVICE_AUTH_ENDPOINT, json=oidc_fixtures.DEVICE_CODE_RESP + ) result = self.plugin.get_payload(self.session) payload = {'client_id': self.CLIENT_ID} @@ -489,8 +539,10 @@ def test_get_device_authorization_request_without_client_secret(self): self.assertIsNone(last_req.headers.get('Authorization')) encoded_payload = urllib.parse.urlencode(payload) self.assertEqual(encoded_payload, last_req.body) - self.assertEqual(oidc_fixtures.DEVICE_CODE_RESP["device_code"], - result["device_code"]) + self.assertEqual( + oidc_fixtures.DEVICE_CODE_RESP["device_code"], + result["device_code"], + ) def test_second_call_to_get_access_token(self): """Test Device Access Token Request.""" @@ -498,11 +550,14 @@ def test_second_call_to_get_access_token(self): # Mock the output that creates the access token self.requests_mock.post( self.ACCESS_TOKEN_ENDPOINT, - json=oidc_fixtures.ACCESS_TOKEN_VIA_PASSWORD_RESP) + json=oidc_fixtures.ACCESS_TOKEN_VIA_PASSWORD_RESP, + ) # Prep all the values and send the request - payload = {'grant_type': self.GRANT_TYPE, - 'device_code': self.plugin.device_code} + payload = { + 'grant_type': self.GRANT_TYPE, + 'device_code': self.plugin.device_code, + } self.plugin._get_access_token(self.session, payload) # Verify the request matches the expected structure @@ -511,7 +566,8 @@ def test_second_call_to_get_access_token(self): self.assertEqual('POST', last_req.method) self.assertEqual( self._basic_header(self.CLIENT_ID, self.CLIENT_SECRET), - last_req.headers.get('Authorization')) + last_req.headers.get('Authorization'), + ) encoded_payload = urllib.parse.urlencode(payload) self.assertEqual(encoded_payload, last_req.body) @@ -527,12 +583,15 @@ def test_second_call_to_get_access_token_without_client_secret(self): # Mock the output that creates the access token self.requests_mock.post( self.ACCESS_TOKEN_ENDPOINT, - json=oidc_fixtures.ACCESS_TOKEN_VIA_PASSWORD_RESP) + json=oidc_fixtures.ACCESS_TOKEN_VIA_PASSWORD_RESP, + ) # Prep all the values and send the request - payload = {'grant_type': self.GRANT_TYPE, - 'device_code': self.plugin.device_code, - 'client_id': self.CLIENT_ID} + payload = { + 'grant_type': self.GRANT_TYPE, + 'device_code': self.plugin.device_code, + 'client_id': self.CLIENT_ID, + } self.plugin._get_access_token(self.session, payload) # Verify the request matches the expected structure @@ -544,18 +603,21 @@ def test_second_call_to_get_access_token_without_client_secret(self): self.assertEqual(encoded_payload, last_req.body) def _basic_header(self, username, password): - user_pass = '{}:{}'.format(username, password).encode('utf-8') + user_pass = f'{username}:{password}'.encode() encoded_credentials = base64.b64encode(user_pass).decode('utf-8') - return 'Basic {}'.format(encoded_credentials) + return f'Basic {encoded_credentials}' def _store_device_authorization_response(self): self.plugin.expires_in = int( - oidc_fixtures.DEVICE_CODE_RESP["expires_in"]) + oidc_fixtures.DEVICE_CODE_RESP["expires_in"] + ) self.plugin.timeout = time.time() + self.plugin.expires_in self.plugin.device_code = oidc_fixtures.DEVICE_CODE_RESP["device_code"] self.plugin.interval = int(oidc_fixtures.DEVICE_CODE_RESP["interval"]) self.plugin.user_code = oidc_fixtures.DEVICE_CODE_RESP["user_code"] - self.plugin.verification_uri = \ - oidc_fixtures.DEVICE_CODE_RESP["verification_uri"] - self.plugin.verification_uri_complete = \ - oidc_fixtures.DEVICE_CODE_RESP["verification_uri_complete"] + self.plugin.verification_uri = oidc_fixtures.DEVICE_CODE_RESP[ + "verification_uri" + ] + self.plugin.verification_uri_complete = oidc_fixtures.DEVICE_CODE_RESP[ + "verification_uri_complete" + ] diff --git a/keystoneauth1/tests/unit/identity/test_password.py b/keystoneauth1/tests/unit/identity/test_password.py index 7c910186..8b1e3bfd 100644 --- a/keystoneauth1/tests/unit/identity/test_password.py +++ b/keystoneauth1/tests/unit/identity/test_password.py @@ -20,7 +20,6 @@ class PasswordTests(utils.GenericPluginTestCase): - PLUGIN_CLASS = password.Password V2_PLUGIN_CLASS = v2.Password V3_PLUGIN_CLASS = v3.Password @@ -28,13 +27,14 @@ class PasswordTests(utils.GenericPluginTestCase): def new_plugin(self, **kwargs): kwargs.setdefault('username', uuid.uuid4().hex) kwargs.setdefault('password', uuid.uuid4().hex) - return super(PasswordTests, self).new_plugin(**kwargs) + return super().new_plugin(**kwargs) def test_with_user_domain_params(self): self.stub_discovery() - self.assertCreateV3(domain_id=uuid.uuid4().hex, - user_domain_id=uuid.uuid4().hex) + self.assertCreateV3( + domain_id=uuid.uuid4().hex, user_domain_id=uuid.uuid4().hex + ) def test_v3_user_params_v2_url(self): self.stub_discovery(v3=False) @@ -47,8 +47,9 @@ def test_v3_domain_params_v2_url(self): def test_v3_disocovery_failure_v2_url(self): auth_url = self.TEST_URL + 'v2.0' self.stub_url('GET', json={}, base_url='/v2.0', status_code=500) - self.assertDiscoveryFailure(domain_id=uuid.uuid4().hex, - auth_url=auth_url) + self.assertDiscoveryFailure( + domain_id=uuid.uuid4().hex, auth_url=auth_url + ) def test_symbols(self): self.assertIs(v3.Password, v3_password.Password) @@ -57,20 +58,24 @@ def test_symbols(self): def test_default_domain_id_with_v3(self): default_domain_id = uuid.uuid4().hex - p = super(PasswordTests, self).test_default_domain_id_with_v3( - default_domain_id=default_domain_id) + p = super().test_default_domain_id_with_v3( + default_domain_id=default_domain_id + ) - self.assertEqual(default_domain_id, - p._plugin.auth_methods[0].user_domain_id) + self.assertEqual( + default_domain_id, p._plugin.auth_methods[0].user_domain_id + ) def test_default_domain_name_with_v3(self): default_domain_name = uuid.uuid4().hex - p = super(PasswordTests, self).test_default_domain_name_with_v3( - default_domain_name=default_domain_name) + p = super().test_default_domain_name_with_v3( + default_domain_name=default_domain_name + ) - self.assertEqual(default_domain_name, - p._plugin.auth_methods[0].user_domain_name) + self.assertEqual( + default_domain_name, p._plugin.auth_methods[0].user_domain_name + ) def test_password_cache_id(self): username = uuid.uuid4().hex @@ -78,28 +83,34 @@ def test_password_cache_id(self): project_name = uuid.uuid4().hex default_domain_id = uuid.uuid4().hex - a = password.Password(self.TEST_URL, - username=username, - password=the_password, - project_name=project_name, - default_domain_id=default_domain_id) - - b = password.Password(self.TEST_URL, - username=username, - password=the_password, - project_name=project_name, - default_domain_id=default_domain_id) + a = password.Password( + self.TEST_URL, + username=username, + password=the_password, + project_name=project_name, + default_domain_id=default_domain_id, + ) + + b = password.Password( + self.TEST_URL, + username=username, + password=the_password, + project_name=project_name, + default_domain_id=default_domain_id, + ) a_id = a.get_cache_id() b_id = b.get_cache_id() self.assertEqual(a_id, b_id) - c = password.Password(self.TEST_URL, - username=username, - password=uuid.uuid4().hex, # different - project_name=project_name, - default_domain_id=default_domain_id) + c = password.Password( + self.TEST_URL, + username=username, + password=uuid.uuid4().hex, # different + project_name=project_name, + default_domain_id=default_domain_id, + ) c_id = c.get_cache_id() diff --git a/keystoneauth1/tests/unit/identity/test_token.py b/keystoneauth1/tests/unit/identity/test_token.py index 0303fb15..ea39cff3 100644 --- a/keystoneauth1/tests/unit/identity/test_token.py +++ b/keystoneauth1/tests/unit/identity/test_token.py @@ -20,14 +20,13 @@ class TokenTests(utils.GenericPluginTestCase): - PLUGIN_CLASS = token.Token V2_PLUGIN_CLASS = v2.Token V3_PLUGIN_CLASS = v3.Token def new_plugin(self, **kwargs): kwargs.setdefault('token', uuid.uuid4().hex) - return super(TokenTests, self).new_plugin(**kwargs) + return super().new_plugin(**kwargs) def test_symbols(self): self.assertIs(v3.Token, v3_token.Token) @@ -38,25 +37,31 @@ def test_token_cache_id(self): project_name = uuid.uuid4().hex default_domain_id = uuid.uuid4().hex - a = token.Token(self.TEST_URL, - token=the_token, - project_name=project_name, - default_domain_id=default_domain_id) + a = token.Token( + self.TEST_URL, + token=the_token, + project_name=project_name, + default_domain_id=default_domain_id, + ) - b = token.Token(self.TEST_URL, - token=the_token, - project_name=project_name, - default_domain_id=default_domain_id) + b = token.Token( + self.TEST_URL, + token=the_token, + project_name=project_name, + default_domain_id=default_domain_id, + ) a_id = a.get_cache_id() b_id = b.get_cache_id() self.assertEqual(a_id, b_id) - c = token.Token(self.TEST_URL, - token=the_token, - project_name=uuid.uuid4().hex, # different - default_domain_id=default_domain_id) + c = token.Token( + self.TEST_URL, + token=the_token, + project_name=uuid.uuid4().hex, # different + default_domain_id=default_domain_id, + ) c_id = c.get_cache_id() diff --git a/keystoneauth1/tests/unit/identity/test_tokenless_auth.py b/keystoneauth1/tests/unit/identity/test_tokenless_auth.py index 160291fb..0187934a 100644 --- a/keystoneauth1/tests/unit/identity/test_tokenless_auth.py +++ b/keystoneauth1/tests/unit/identity/test_tokenless_auth.py @@ -19,16 +19,18 @@ class TokenlessAuthTest(utils.TestCase): - TEST_URL = 'http://server/prefix' - def create(self, auth_url, - domain_id=None, - domain_name=None, - project_id=None, - project_name=None, - project_domain_id=None, - project_domain_name=None): + def create( + self, + auth_url, + domain_id=None, + domain_name=None, + project_id=None, + project_name=None, + project_domain_id=None, + project_domain_name=None, + ): self.requests_mock.get(self.TEST_URL) auth = tokenless_auth.TokenlessAuth( auth_url=self.TEST_URL, @@ -37,36 +39,42 @@ def create(self, auth_url, project_id=project_id, project_name=project_name, project_domain_id=project_domain_id, - project_domain_name=project_domain_name) + project_domain_name=project_domain_name, + ) return auth, session.Session(auth=auth) def test_domain_id_scope_header_pass(self): domain_id = uuid.uuid4().hex - auth, session = self.create(auth_url=self.TEST_URL, - domain_id=domain_id) + auth, session = self.create( + auth_url=self.TEST_URL, domain_id=domain_id + ) session.get(self.TEST_URL, authenticated=True) self.assertRequestHeaderEqual('X-Domain-Id', domain_id) def test_domain_name_scope_header_pass(self): domain_name = uuid.uuid4().hex - auth, session = self.create(auth_url=self.TEST_URL, - domain_name=domain_name) + auth, session = self.create( + auth_url=self.TEST_URL, domain_name=domain_name + ) session.get(self.TEST_URL, authenticated=True) self.assertRequestHeaderEqual('X-Domain-Name', domain_name) def test_project_id_scope_header_pass(self): project_id = uuid.uuid4().hex - auth, session = self.create(auth_url=self.TEST_URL, - project_id=project_id) + auth, session = self.create( + auth_url=self.TEST_URL, project_id=project_id + ) session.get(self.TEST_URL, authenticated=True) self.assertRequestHeaderEqual('X-Project-Id', project_id) def test_project_of_domain_id_scope_header_pass(self): project_name = uuid.uuid4().hex project_domain_id = uuid.uuid4().hex - auth, session = self.create(auth_url=self.TEST_URL, - project_name=project_name, - project_domain_id=project_domain_id) + auth, session = self.create( + auth_url=self.TEST_URL, + project_name=project_name, + project_domain_id=project_domain_id, + ) session.get(self.TEST_URL, authenticated=True) self.assertRequestHeaderEqual('X-Project-Name', project_name) self.assertRequestHeaderEqual('X-Project-Domain-Id', project_domain_id) @@ -74,32 +82,40 @@ def test_project_of_domain_id_scope_header_pass(self): def test_project_of_domain__name_scope_header_pass(self): project_name = uuid.uuid4().hex project_domain_name = uuid.uuid4().hex - auth, session = self.create(auth_url=self.TEST_URL, - project_name=project_name, - project_domain_name=project_domain_name) + auth, session = self.create( + auth_url=self.TEST_URL, + project_name=project_name, + project_domain_name=project_domain_name, + ) session.get(self.TEST_URL, authenticated=True) self.assertRequestHeaderEqual('X-Project-Name', project_name) - self.assertRequestHeaderEqual('X-Project-Domain-Name', - project_domain_name) + self.assertRequestHeaderEqual( + 'X-Project-Domain-Name', project_domain_name + ) def test_no_scope_header_fail(self): auth, session = self.create(auth_url=self.TEST_URL) self.assertIsNone(auth.get_headers(session)) msg = 'No valid authentication is available' - self.assertRaisesRegex(exceptions.AuthorizationFailure, - msg, - session.get, - self.TEST_URL, - authenticated=True) + self.assertRaisesRegex( + exceptions.AuthorizationFailure, + msg, + session.get, + self.TEST_URL, + authenticated=True, + ) def test_project_name_scope_only_header_fail(self): project_name = uuid.uuid4().hex - auth, session = self.create(auth_url=self.TEST_URL, - project_name=project_name) + auth, session = self.create( + auth_url=self.TEST_URL, project_name=project_name + ) self.assertIsNone(auth.get_headers(session)) msg = 'No valid authentication is available' - self.assertRaisesRegex(exceptions.AuthorizationFailure, - msg, - session.get, - self.TEST_URL, - authenticated=True) + self.assertRaisesRegex( + exceptions.AuthorizationFailure, + msg, + session.get, + self.TEST_URL, + authenticated=True, + ) diff --git a/keystoneauth1/tests/unit/identity/utils.py b/keystoneauth1/tests/unit/identity/utils.py index 89883b5b..5d61d0a9 100644 --- a/keystoneauth1/tests/unit/identity/utils.py +++ b/keystoneauth1/tests/unit/identity/utils.py @@ -20,7 +20,6 @@ class GenericPluginTestCase(utils.TestCase): - TEST_URL = 'http://keystone.host:5000/' # OVERRIDE THESE IN SUB CLASSES @@ -29,7 +28,7 @@ class GenericPluginTestCase(utils.TestCase): V3_PLUGIN_CLASS = None def setUp(self): - super(GenericPluginTestCase, self).setUp() + super().setUp() self.token_v2 = fixture.V2Token() self.token_v3 = fixture.V3Token() @@ -37,9 +36,12 @@ def setUp(self): self.session = session.Session() self.stub_url('POST', ['v2.0', 'tokens'], json=self.token_v2) - self.stub_url('POST', ['v3', 'auth', 'tokens'], - headers={'X-Subject-Token': self.token_v3_id}, - json=self.token_v3) + self.stub_url( + 'POST', + ['v3', 'auth', 'tokens'], + headers={'X-Subject-Token': self.token_v3_id}, + json=self.token_v3, + ) def new_plugin(self, **kwargs): kwargs.setdefault('auth_url', self.TEST_URL) @@ -55,8 +57,10 @@ def assertCreateV3(self, **kwargs): auth = self.new_plugin(**kwargs) auth_ref = auth.get_auth_ref(self.session) self.assertIsInstance(auth_ref, access.AccessInfoV3) - self.assertEqual(self.TEST_URL + 'v3/auth/tokens', - self.requests_mock.last_request.url) + self.assertEqual( + self.TEST_URL + 'v3/auth/tokens', + self.requests_mock.last_request.url, + ) self.assertIsInstance(auth._plugin, self.V3_PLUGIN_CLASS) return auth @@ -64,26 +68,29 @@ def assertCreateV2(self, **kwargs): auth = self.new_plugin(**kwargs) auth_ref = auth.get_auth_ref(self.session) self.assertIsInstance(auth_ref, access.AccessInfoV2) - self.assertEqual(self.TEST_URL + 'v2.0/tokens', - self.requests_mock.last_request.url) + self.assertEqual( + self.TEST_URL + 'v2.0/tokens', self.requests_mock.last_request.url + ) self.assertIsInstance(auth._plugin, self.V2_PLUGIN_CLASS) return auth def assertDiscoveryFailure(self, **kwargs): plugin = self.new_plugin(**kwargs) - self.assertRaises(exceptions.DiscoveryFailure, - plugin.get_auth_ref, - self.session) + self.assertRaises( + exceptions.DiscoveryFailure, plugin.get_auth_ref, self.session + ) def test_create_v3_if_domain_params(self): self.stub_discovery() self.assertCreateV3(domain_id=uuid.uuid4().hex) self.assertCreateV3(domain_name=uuid.uuid4().hex) - self.assertCreateV3(project_name=uuid.uuid4().hex, - project_domain_name=uuid.uuid4().hex) - self.assertCreateV3(project_name=uuid.uuid4().hex, - project_domain_id=uuid.uuid4().hex) + self.assertCreateV3( + project_name=uuid.uuid4().hex, project_domain_name=uuid.uuid4().hex + ) + self.assertCreateV3( + project_name=uuid.uuid4().hex, project_domain_id=uuid.uuid4().hex + ) def test_create_v2_if_no_domain_params(self): self.stub_discovery() @@ -136,8 +143,9 @@ def test_unknown_discovery_version(self): def test_default_domain_id_with_v3(self, **kwargs): self.stub_discovery() project_name = uuid.uuid4().hex - default_domain_id = kwargs.setdefault('default_domain_id', - uuid.uuid4().hex) + default_domain_id = kwargs.setdefault( + 'default_domain_id', uuid.uuid4().hex + ) p = self.assertCreateV3(project_name=project_name, **kwargs) @@ -151,16 +159,18 @@ def test_default_domain_id_no_v3(self): project_name = uuid.uuid4().hex default_domain_id = uuid.uuid4().hex - p = self.assertCreateV2(project_name=project_name, - default_domain_id=default_domain_id) + p = self.assertCreateV2( + project_name=project_name, default_domain_id=default_domain_id + ) self.assertEqual(project_name, p._plugin.tenant_name) def test_default_domain_name_with_v3(self, **kwargs): self.stub_discovery() project_name = uuid.uuid4().hex - default_domain_name = kwargs.setdefault('default_domain_name', - uuid.uuid4().hex) + default_domain_name = kwargs.setdefault( + 'default_domain_name', uuid.uuid4().hex + ) p = self.assertCreateV3(project_name=project_name, **kwargs) @@ -174,7 +184,8 @@ def test_default_domain_name_no_v3(self): project_name = uuid.uuid4().hex default_domain_name = uuid.uuid4().hex - p = self.assertCreateV2(project_name=project_name, - default_domain_name=default_domain_name) + p = self.assertCreateV2( + project_name=project_name, default_domain_name=default_domain_name + ) self.assertEqual(project_name, p._plugin.tenant_name) diff --git a/keystoneauth1/tests/unit/k2k_fixtures.py b/keystoneauth1/tests/unit/k2k_fixtures.py index f78cb0ef..d7234453 100644 --- a/keystoneauth1/tests/unit/k2k_fixtures.py +++ b/keystoneauth1/tests/unit/k2k_fixtures.py @@ -20,19 +20,13 @@ "expires_at": "2014-06-09T10:48:59.643375Z", "user": { "OS-FEDERATION": { - "identity_provider": { - "id": "testshib" - }, - "protocol": { - "id": "saml2" - }, - "groups": [ - {"id": "1764fa5cf69a49a4918131de5ce4af9a"} - ] + "identity_provider": {"id": "testshib"}, + "protocol": {"id": "saml2"}, + "groups": [{"id": "1764fa5cf69a49a4918131de5ce4af9a"}], }, "id": "testhib%20user", - "name": "testhib user" - } + "name": "testhib user", + }, } } @@ -124,7 +118,7 @@ TOKEN_BASED_SAML = ''.join([SAML_ENCODING, TOKEN_SAML_RESPONSE]) -ECP_ENVELOPE = """ +ECP_ENVELOPE = f""" - {0} + {TOKEN_SAML_RESPONSE} -""".format(TOKEN_SAML_RESPONSE) +""" TOKEN_BASED_ECP = ''.join([SAML_ENCODING, ECP_ENVELOPE]) diff --git a/keystoneauth1/tests/unit/loading/test_adapter.py b/keystoneauth1/tests/unit/loading/test_adapter.py index 26220a3c..37a9f24a 100644 --- a/keystoneauth1/tests/unit/loading/test_adapter.py +++ b/keystoneauth1/tests/unit/loading/test_adapter.py @@ -20,24 +20,29 @@ class ConfLoadingTests(utils.TestCase): - GROUP = 'adaptergroup' def setUp(self): - super(ConfLoadingTests, self).setUp() + super().setUp() self.conf_fx = self.useFixture(config.Config()) - loading.register_adapter_conf_options(self.conf_fx.conf, self.GROUP, - include_deprecated=False) + loading.register_adapter_conf_options( + self.conf_fx.conf, self.GROUP, include_deprecated=False + ) def test_load(self): self.conf_fx.config( - service_type='type', service_name='name', + service_type='type', + service_name='name', valid_interfaces='internal', - region_name='region', endpoint_override='endpoint', - version='2.0', group=self.GROUP) + region_name='region', + endpoint_override='endpoint', + version='2.0', + group=self.GROUP, + ) adap = loading.load_adapter_from_conf_options( - self.conf_fx.conf, self.GROUP, session='session', auth='auth') + self.conf_fx.conf, self.GROUP, session='session', auth='auth' + ) self.assertEqual('type', adap.service_type) self.assertEqual('name', adap.service_name) self.assertEqual(['internal'], adap.interface) @@ -51,12 +56,17 @@ def test_load(self): def test_load_valid_interfaces_list(self): self.conf_fx.config( - service_type='type', service_name='name', + service_type='type', + service_name='name', valid_interfaces=['internal', 'public'], - region_name='region', endpoint_override='endpoint', - version='2.0', group=self.GROUP) + region_name='region', + endpoint_override='endpoint', + version='2.0', + group=self.GROUP, + ) adap = loading.load_adapter_from_conf_options( - self.conf_fx.conf, self.GROUP, session='session', auth='auth') + self.conf_fx.conf, self.GROUP, session='session', auth='auth' + ) self.assertEqual('type', adap.service_type) self.assertEqual('name', adap.service_name) self.assertEqual(['internal', 'public'], adap.interface) @@ -70,12 +80,17 @@ def test_load_valid_interfaces_list(self): def test_load_valid_interfaces_comma_list(self): self.conf_fx.config( - service_type='type', service_name='name', + service_type='type', + service_name='name', valid_interfaces='internal,public', - region_name='region', endpoint_override='endpoint', - version='2.0', group=self.GROUP) + region_name='region', + endpoint_override='endpoint', + version='2.0', + group=self.GROUP, + ) adap = loading.load_adapter_from_conf_options( - self.conf_fx.conf, self.GROUP, session='session', auth='auth') + self.conf_fx.conf, self.GROUP, session='session', auth='auth' + ) self.assertEqual('type', adap.service_type) self.assertEqual('name', adap.service_name) self.assertEqual(['internal', 'public'], adap.interface) @@ -89,23 +104,37 @@ def test_load_valid_interfaces_comma_list(self): def test_load_bad_valid_interfaces_value(self): self.conf_fx.config( - service_type='type', service_name='name', + service_type='type', + service_name='name', valid_interfaces='bad', - region_name='region', endpoint_override='endpoint', - version='2.0', group=self.GROUP) + region_name='region', + endpoint_override='endpoint', + version='2.0', + group=self.GROUP, + ) self.assertRaises( TypeError, loading.load_adapter_from_conf_options, - self.conf_fx.conf, self.GROUP, session='session', auth='auth') + self.conf_fx.conf, + self.GROUP, + session='session', + auth='auth', + ) def test_load_version_range(self): self.conf_fx.config( - service_type='type', service_name='name', + service_type='type', + service_name='name', valid_interfaces='internal', - region_name='region', endpoint_override='endpoint', - min_version='2.0', max_version='3.0', group=self.GROUP) + region_name='region', + endpoint_override='endpoint', + min_version='2.0', + max_version='3.0', + group=self.GROUP, + ) adap = loading.load_adapter_from_conf_options( - self.conf_fx.conf, self.GROUP, session='session', auth='auth') + self.conf_fx.conf, self.GROUP, session='session', auth='auth' + ) self.assertEqual('type', adap.service_type) self.assertEqual('name', adap.service_name) self.assertEqual(['internal'], adap.interface) @@ -119,49 +148,82 @@ def test_load_version_range(self): def test_version_mutex_min(self): self.conf_fx.config( - service_type='type', service_name='name', + service_type='type', + service_name='name', valid_interfaces='iface', - region_name='region', endpoint_override='endpoint', - version='2.0', min_version='2.0', group=self.GROUP) + region_name='region', + endpoint_override='endpoint', + version='2.0', + min_version='2.0', + group=self.GROUP, + ) self.assertRaises( TypeError, loading.load_adapter_from_conf_options, - self.conf_fx.conf, self.GROUP, session='session', auth='auth') + self.conf_fx.conf, + self.GROUP, + session='session', + auth='auth', + ) def test_version_mutex_max(self): self.conf_fx.config( - service_type='type', service_name='name', + service_type='type', + service_name='name', valid_interfaces='iface', - region_name='region', endpoint_override='endpoint', - version='2.0', max_version='3.0', group=self.GROUP) + region_name='region', + endpoint_override='endpoint', + version='2.0', + max_version='3.0', + group=self.GROUP, + ) self.assertRaises( TypeError, loading.load_adapter_from_conf_options, - self.conf_fx.conf, self.GROUP, session='session', auth='auth') + self.conf_fx.conf, + self.GROUP, + session='session', + auth='auth', + ) def test_version_mutex_minmax(self): self.conf_fx.config( - service_type='type', service_name='name', + service_type='type', + service_name='name', valid_interfaces='iface', - region_name='region', endpoint_override='endpoint', - version='2.0', min_version='2.0', max_version='3.0', - group=self.GROUP) + region_name='region', + endpoint_override='endpoint', + version='2.0', + min_version='2.0', + max_version='3.0', + group=self.GROUP, + ) self.assertRaises( TypeError, loading.load_adapter_from_conf_options, - self.conf_fx.conf, self.GROUP, session='session', auth='auth') + self.conf_fx.conf, + self.GROUP, + session='session', + auth='auth', + ) def test_load_retries(self): self.conf_fx.config( - service_type='type', service_name='name', - connect_retries=3, status_code_retries=5, - connect_retry_delay=0.5, status_code_retry_delay=2.0, - retriable_status_codes=[503], group=self.GROUP) + service_type='type', + service_name='name', + connect_retries=3, + status_code_retries=5, + connect_retry_delay=0.5, + status_code_retry_delay=2.0, + retriable_status_codes=[503], + group=self.GROUP, + ) adap = loading.load_adapter_from_conf_options( - self.conf_fx.conf, self.GROUP, session='session', auth='auth') + self.conf_fx.conf, self.GROUP, session='session', auth='auth' + ) self.assertEqual('type', adap.service_type) self.assertEqual('name', adap.service_name) self.assertEqual(3, adap.connect_retries) @@ -183,13 +245,25 @@ def test_get_conf_options(self): self.assertIsInstance(opt, cfg.StrOpt) else: self.assertIsInstance(opt, cfg.ListOpt) - self.assertEqual({'service-type', 'service-name', - 'interface', 'valid-interfaces', - 'region-name', 'endpoint-override', 'version', - 'min-version', 'max-version', 'connect-retries', - 'status-code-retries', 'connect-retry-delay', - 'status-code-retry-delay', 'retriable-status-codes'}, - {opt.name for opt in opts}) + self.assertEqual( + { + 'service-type', + 'service-name', + 'interface', + 'valid-interfaces', + 'region-name', + 'endpoint-override', + 'version', + 'min-version', + 'max-version', + 'connect-retries', + 'status-code-retries', + 'connect-retry-delay', + 'status-code-retry-delay', + 'retriable-status-codes', + }, + {opt.name for opt in opts}, + ) def test_get_conf_options_undeprecated(self): opts = loading.get_adapter_conf_options(include_deprecated=False) @@ -204,12 +278,24 @@ def test_get_conf_options_undeprecated(self): self.assertIsInstance(opt, cfg.StrOpt) else: self.assertIsInstance(opt, cfg.ListOpt) - self.assertEqual({'service-type', 'service-name', 'valid-interfaces', - 'region-name', 'endpoint-override', 'version', - 'min-version', 'max-version', 'connect-retries', - 'status-code-retries', 'connect-retry-delay', - 'status-code-retry-delay', 'retriable-status-codes'}, - {opt.name for opt in opts}) + self.assertEqual( + { + 'service-type', + 'service-name', + 'valid-interfaces', + 'region-name', + 'endpoint-override', + 'version', + 'min-version', + 'max-version', + 'connect-retries', + 'status-code-retries', + 'connect-retry-delay', + 'status-code-retry-delay', + 'retriable-status-codes', + }, + {opt.name for opt in opts}, + ) def test_deprecated(self): """Test external options that are deprecated by Adapter options. @@ -217,11 +303,12 @@ def test_deprecated(self): Not to be confused with ConfLoadingDeprecatedTests, which tests conf options in Adapter which are themselves deprecated. """ + def new_deprecated(): return cfg.DeprecatedOpt(uuid.uuid4().hex, group=uuid.uuid4().hex) opt_names = ['service-type', 'valid-interfaces', 'endpoint-override'] - depr = dict([(n, [new_deprecated()]) for n in opt_names]) + depr = {n: [new_deprecated()] for n in opt_names} opts = loading.get_adapter_conf_options(deprecated_opts=depr) for opt in opts: @@ -239,19 +326,24 @@ class ConfLoadingLegacyTests(ConfLoadingTests): GROUP = 'adaptergroup' def setUp(self): - super(ConfLoadingLegacyTests, self).setUp() + super().setUp() self.conf_fx = self.useFixture(config.Config()) loading.register_adapter_conf_options(self.conf_fx.conf, self.GROUP) def test_load_old_interface(self): self.conf_fx.config( - service_type='type', service_name='name', + service_type='type', + service_name='name', interface='internal', - region_name='region', endpoint_override='endpoint', - version='2.0', group=self.GROUP) + region_name='region', + endpoint_override='endpoint', + version='2.0', + group=self.GROUP, + ) adap = loading.load_adapter_from_conf_options( - self.conf_fx.conf, self.GROUP, session='session', auth='auth') + self.conf_fx.conf, self.GROUP, session='session', auth='auth' + ) self.assertEqual('type', adap.service_type) self.assertEqual('name', adap.service_name) self.assertEqual('internal', adap.interface) @@ -265,12 +357,20 @@ def test_load_old_interface(self): def test_interface_conflict(self): self.conf_fx.config( - service_type='type', service_name='name', interface='iface', + service_type='type', + service_name='name', + interface='iface', valid_interfaces='internal,public', - region_name='region', endpoint_override='endpoint', - group=self.GROUP) + region_name='region', + endpoint_override='endpoint', + group=self.GROUP, + ) self.assertRaises( TypeError, loading.load_adapter_from_conf_options, - self.conf_fx.conf, self.GROUP, session='session', auth='auth') + self.conf_fx.conf, + self.GROUP, + session='session', + auth='auth', + ) diff --git a/keystoneauth1/tests/unit/loading/test_cli.py b/keystoneauth1/tests/unit/loading/test_cli.py index 51635336..52a720af 100644 --- a/keystoneauth1/tests/unit/loading/test_cli.py +++ b/keystoneauth1/tests/unit/loading/test_cli.py @@ -23,17 +23,16 @@ TesterPlugin, TesterLoader = utils.create_plugin( opts=[ - loading.Opt('test-opt', - help='tester', - deprecated=[loading.Opt('test-other')]) + loading.Opt( + 'test-opt', help='tester', deprecated=[loading.Opt('test-other')] + ) ] ) class CliTests(utils.TestCase): - def setUp(self): - super(CliTests, self).setUp() + super().setUp() self.p = argparse.ArgumentParser() def env(self, name, value=None): @@ -68,10 +67,16 @@ def test_basic_params_added(self, m): @utils.mock_plugin() def test_param_loading(self, m): name = uuid.uuid4().hex - argv = ['--os-auth-type', name, - '--os-a-int', str(self.a_int), - '--os-a-float', str(self.a_float), - '--os-a-bool', str(self.a_bool)] + argv = [ + '--os-auth-type', + name, + '--os-a-int', + str(self.a_int), + '--os-a-float', + str(self.a_float), + '--os-a-bool', + str(self.a_bool), + ] klass = loading.register_auth_argparse_arguments(self.p, argv) self.assertIsInstance(klass, utils.MockLoader) @@ -90,8 +95,7 @@ def test_param_loading(self, m): @utils.mock_plugin() def test_default_options(self, m): name = uuid.uuid4().hex - argv = ['--os-auth-type', name, - '--os-a-float', str(self.a_float)] + argv = ['--os-auth-type', name, '--os-a-float', str(self.a_float)] klass = loading.register_auth_argparse_arguments(self.p, argv) self.assertIsInstance(klass, utils.MockLoader) @@ -107,9 +111,9 @@ def test_default_options(self, m): @utils.mock_plugin() def test_with_default_string_value(self, m): name = uuid.uuid4().hex - klass = loading.register_auth_argparse_arguments(self.p, - [], - default=name) + klass = loading.register_auth_argparse_arguments( + self.p, [], default=name + ) self.assertIsInstance(klass, utils.MockLoader) m.assert_called_once_with(name) @@ -118,18 +122,18 @@ def test_overrides_default_string_value(self, m): name = uuid.uuid4().hex default = uuid.uuid4().hex argv = ['--os-auth-type', name] - klass = loading.register_auth_argparse_arguments(self.p, - argv, - default=default) + klass = loading.register_auth_argparse_arguments( + self.p, argv, default=default + ) self.assertIsInstance(klass, utils.MockLoader) m.assert_called_once_with(name) @utils.mock_plugin() def test_with_default_type_value(self, m): default = utils.MockLoader() - klass = loading.register_auth_argparse_arguments(self.p, - [], - default=default) + klass = loading.register_auth_argparse_arguments( + self.p, [], default=default + ) self.assertIsInstance(klass, utils.MockLoader) self.assertEqual(0, m.call_count) @@ -137,13 +141,14 @@ def test_with_default_type_value(self, m): def test_overrides_default_type_value(self, m): # using this test plugin would fail if called because there # is no get_options() function - class TestLoader(object): + class TestLoader: pass + name = uuid.uuid4().hex argv = ['--os-auth-type', name] - klass = loading.register_auth_argparse_arguments(self.p, - argv, - default=TestLoader) + klass = loading.register_auth_argparse_arguments( + self.p, argv, default=TestLoader + ) self.assertIsInstance(klass, utils.MockLoader) m.assert_called_once_with(name) @@ -153,9 +158,9 @@ def test_env_overrides_default_opt(self, m): val = uuid.uuid4().hex self.env('OS_A_STR', val) - klass = loading.register_auth_argparse_arguments(self.p, - [], - default=name) + klass = loading.register_auth_argparse_arguments( + self.p, [], default=name + ) self.assertIsInstance(klass, utils.MockLoader) opts = self.p.parse_args([]) a = loading.load_auth_from_argparse_arguments(opts) @@ -173,8 +178,9 @@ def test_deprecated_multi_cli_options(self): val1 = uuid.uuid4().hex val2 = uuid.uuid4().hex # argarse rules say that the last specified wins. - opts = self.p.parse_args(['--os-test-other', val2, - '--os-test-opt', val1]) + opts = self.p.parse_args( + ['--os-test-other', val2, '--os-test-opt', val1] + ) self.assertEqual(val1, opts.os_test_opt) def test_deprecated_env_options(self): @@ -190,8 +196,9 @@ def test_deprecated_env_multi_options(self): val1 = uuid.uuid4().hex val2 = uuid.uuid4().hex - with mock.patch.dict('os.environ', {'OS_TEST_OPT': val1, - 'OS_TEST_OTHER': val2}): + with mock.patch.dict( + 'os.environ', {'OS_TEST_OPT': val1, 'OS_TEST_OTHER': val2} + ): cli._register_plugin_argparse_arguments(self.p, TesterLoader()) opts = self.p.parse_args([]) diff --git a/keystoneauth1/tests/unit/loading/test_conf.py b/keystoneauth1/tests/unit/loading/test_conf.py index ccea2b95..4b3270c2 100644 --- a/keystoneauth1/tests/unit/loading/test_conf.py +++ b/keystoneauth1/tests/unit/loading/test_conf.py @@ -25,17 +25,17 @@ class ConfTests(utils.TestCase): - def setUp(self): - super(ConfTests, self).setUp() + super().setUp() self.conf_fixture = self.useFixture(config.Config()) # NOTE(jamielennox): we register the basic config options first because # we need them in place before we can stub them. We will need to run # the register again after we stub the auth section and auth plugin so # it can load the plugin specific options. - loading.register_auth_conf_options(self.conf_fixture.conf, - group=self.GROUP) + loading.register_auth_conf_options( + self.conf_fixture.conf, group=self.GROUP + ) def test_loading_v2(self): section = uuid.uuid4().hex @@ -46,22 +46,26 @@ def test_loading_v2(self): tenant_id = uuid.uuid4().hex self.conf_fixture.config(auth_section=section, group=self.GROUP) - loading.register_auth_conf_options(self.conf_fixture.conf, - group=self.GROUP) + loading.register_auth_conf_options( + self.conf_fixture.conf, group=self.GROUP + ) opts = loading.get_auth_plugin_conf_options(v2.Password()) self.conf_fixture.register_opts(opts, group=section) - self.conf_fixture.config(auth_type=self.V2PASS, - auth_url=auth_url, - username=username, - password=password, - trust_id=trust_id, - tenant_id=tenant_id, - group=section) + self.conf_fixture.config( + auth_type=self.V2PASS, + auth_url=auth_url, + username=username, + password=password, + trust_id=trust_id, + tenant_id=tenant_id, + group=section, + ) - a = loading.load_auth_from_conf_options(self.conf_fixture.conf, - self.GROUP) + a = loading.load_auth_from_conf_options( + self.conf_fixture.conf, self.GROUP + ) self.assertEqual(auth_url, a.auth_url) self.assertEqual(username, a.username) @@ -71,29 +75,33 @@ def test_loading_v2(self): def test_loading_v3(self): section = uuid.uuid4().hex - auth_url = uuid.uuid4().hex, + auth_url = (uuid.uuid4().hex,) token = uuid.uuid4().hex trust_id = uuid.uuid4().hex project_id = uuid.uuid4().hex project_domain_name = uuid.uuid4().hex self.conf_fixture.config(auth_section=section, group=self.GROUP) - loading.register_auth_conf_options(self.conf_fixture.conf, - group=self.GROUP) + loading.register_auth_conf_options( + self.conf_fixture.conf, group=self.GROUP + ) opts = loading.get_auth_plugin_conf_options(v3.Token()) self.conf_fixture.register_opts(opts, group=section) - self.conf_fixture.config(auth_type=self.V3TOKEN, - auth_url=auth_url, - token=token, - trust_id=trust_id, - project_id=project_id, - project_domain_name=project_domain_name, - group=section) + self.conf_fixture.config( + auth_type=self.V3TOKEN, + auth_url=auth_url, + token=token, + trust_id=trust_id, + project_id=project_id, + project_domain_name=project_domain_name, + group=section, + ) - a = loading.load_auth_from_conf_options(self.conf_fixture.conf, - self.GROUP) + a = loading.load_auth_from_conf_options( + self.conf_fixture.conf, self.GROUP + ) self.assertEqual(token, a.auth_methods[0].token) self.assertEqual(trust_id, a.trust_id) @@ -102,19 +110,21 @@ def test_loading_v3(self): def test_loading_invalid_plugin(self): auth_type = uuid.uuid4().hex - self.conf_fixture.config(auth_type=auth_type, - group=self.GROUP) + self.conf_fixture.config(auth_type=auth_type, group=self.GROUP) - e = self.assertRaises(exceptions.NoMatchingPlugin, - loading.load_auth_from_conf_options, - self.conf_fixture.conf, - self.GROUP) + e = self.assertRaises( + exceptions.NoMatchingPlugin, + loading.load_auth_from_conf_options, + self.conf_fixture.conf, + self.GROUP, + ) self.assertEqual(auth_type, e.name) def test_loading_with_no_data(self): - lo = loading.load_auth_from_conf_options(self.conf_fixture.conf, - self.GROUP) + lo = loading.load_auth_from_conf_options( + self.conf_fixture.conf, self.GROUP + ) self.assertIsNone(lo) @mock.patch('stevedore.DriverManager') @@ -124,31 +134,36 @@ def test_other_params(self, m): opts = loading.get_auth_plugin_conf_options(utils.MockLoader()) self.conf_fixture.register_opts(opts, group=self.GROUP) - self.conf_fixture.config(auth_type=driver_name, - group=self.GROUP, - **self.TEST_VALS) + self.conf_fixture.config( + auth_type=driver_name, group=self.GROUP, **self.TEST_VALS + ) - a = loading.load_auth_from_conf_options(self.conf_fixture.conf, - self.GROUP) + a = loading.load_auth_from_conf_options( + self.conf_fixture.conf, self.GROUP + ) self.assertTestVals(a) - m.assert_called_once_with(namespace=loading.PLUGIN_NAMESPACE, - name=driver_name, - invoke_on_load=True) + m.assert_called_once_with( + namespace=loading.PLUGIN_NAMESPACE, + name=driver_name, + invoke_on_load=True, + ) @utils.mock_plugin() def test_same_section(self, m): opts = loading.get_auth_plugin_conf_options(utils.MockLoader()) self.conf_fixture.register_opts(opts, group=self.GROUP) - loading.register_auth_conf_options(self.conf_fixture.conf, - group=self.GROUP) - self.conf_fixture.config(auth_type=uuid.uuid4().hex, - group=self.GROUP, - **self.TEST_VALS) + loading.register_auth_conf_options( + self.conf_fixture.conf, group=self.GROUP + ) + self.conf_fixture.config( + auth_type=uuid.uuid4().hex, group=self.GROUP, **self.TEST_VALS + ) - a = loading.load_auth_from_conf_options(self.conf_fixture.conf, - self.GROUP) + a = loading.load_auth_from_conf_options( + self.conf_fixture.conf, self.GROUP + ) self.assertTestVals(a) @utils.mock_plugin() @@ -156,22 +171,25 @@ def test_diff_section(self, m): section = uuid.uuid4().hex self.conf_fixture.config(auth_section=section, group=self.GROUP) - loading.register_auth_conf_options(self.conf_fixture.conf, - group=self.GROUP) + loading.register_auth_conf_options( + self.conf_fixture.conf, group=self.GROUP + ) opts = loading.get_auth_plugin_conf_options(utils.MockLoader()) self.conf_fixture.register_opts(opts, group=section) - self.conf_fixture.config(group=section, - auth_type=uuid.uuid4().hex, - **self.TEST_VALS) + self.conf_fixture.config( + group=section, auth_type=uuid.uuid4().hex, **self.TEST_VALS + ) - a = loading.load_auth_from_conf_options(self.conf_fixture.conf, - self.GROUP) + a = loading.load_auth_from_conf_options( + self.conf_fixture.conf, self.GROUP + ) self.assertTestVals(a) def test_plugins_are_all_opts(self): - manager = stevedore.ExtensionManager(loading.PLUGIN_NAMESPACE, - propagate_map_exceptions=True) + manager = stevedore.ExtensionManager( + loading.PLUGIN_NAMESPACE, propagate_map_exceptions=True + ) def inner(driver): for p in driver.plugin().get_options(): @@ -189,14 +207,15 @@ def test_get_named(self): loaded_opts = loading.get_plugin_options('v2password') plugin_opts = v2.Password().get_options() - loaded_names = set([o.name for o in loaded_opts]) - plugin_names = set([o.name for o in plugin_opts]) + loaded_names = {o.name for o in loaded_opts} + plugin_names = {o.name for o in plugin_opts} self.assertEqual(plugin_names, loaded_names) def test_register_cfg(self): - loading.register_auth_conf_options(self.conf_fixture.conf, - group=self.GROUP) + loading.register_auth_conf_options( + self.conf_fixture.conf, group=self.GROUP + ) def test_common_conf_options(self): opts = loading.get_auth_common_conf_options() diff --git a/keystoneauth1/tests/unit/loading/test_entry_points.py b/keystoneauth1/tests/unit/loading/test_entry_points.py index 49968ef2..959411e5 100644 --- a/keystoneauth1/tests/unit/loading/test_entry_points.py +++ b/keystoneauth1/tests/unit/loading/test_entry_points.py @@ -23,13 +23,12 @@ def test_all_entry_points_are_valid(self): errors = [] def raise_exception_callback(manager, entrypoint, exc): - error = ("Cannot load '%(entrypoint)s' entry_point: %(error)s'" % - {"entrypoint": entrypoint, "error": exc}) + error = f"Cannot load '{entrypoint}' entry_point: {exc}'" errors.append(error) stevedore.ExtensionManager( namespace=loading.PLUGIN_NAMESPACE, - on_load_failure_callback=raise_exception_callback + on_load_failure_callback=raise_exception_callback, ) self.assertEqual([], errors) diff --git a/keystoneauth1/tests/unit/loading/test_fixtures.py b/keystoneauth1/tests/unit/loading/test_fixtures.py index e54dd805..c21e1574 100644 --- a/keystoneauth1/tests/unit/loading/test_fixtures.py +++ b/keystoneauth1/tests/unit/loading/test_fixtures.py @@ -21,12 +21,11 @@ class FixturesTests(utils.TestCase): - GROUP = uuid.uuid4().hex AUTH_TYPE = uuid.uuid4().hex def setUp(self): - super(FixturesTests, self).setUp() + super().setUp() self.conf_fixture = self.useFixture(config.Config()) # conf loading will still try to read the auth_type from the config @@ -35,8 +34,9 @@ def setUp(self): # but it could be a useful differentiator and it also ensures that the # application has called register_auth_conf_options before simply # returning a fake plugin. - loading.register_auth_conf_options(self.conf_fixture.conf, - group=self.GROUP) + loading.register_auth_conf_options( + self.conf_fixture.conf, group=self.GROUP + ) self.conf_fixture.config(auth_type=self.AUTH_TYPE, group=self.GROUP) @@ -47,13 +47,16 @@ def test_endpoint_resolve(self): endpoint = "http://%(service_type)s/%(version)s/%(interface)s" loader = self.useLoadingFixture(endpoint=endpoint) - endpoint_filter = {'service_type': 'compute', - 'service_name': 'nova', - 'version': (2, 1), - 'interface': 'public'} + endpoint_filter = { + 'service_type': 'compute', + 'service_name': 'nova', + 'version': (2, 1), + 'interface': 'public', + } - auth = loading.load_auth_from_conf_options(self.conf_fixture.conf, - self.GROUP) + auth = loading.load_auth_from_conf_options( + self.conf_fixture.conf, self.GROUP + ) sess = session.Session(auth=auth) loader_endpoint = loader.get_endpoint(**endpoint_filter) @@ -64,9 +67,11 @@ def test_endpoint_resolve(self): def test_conf_loaded(self): token = uuid.uuid4().hex - endpoint_filter = {'service_type': 'compute', - 'service_name': 'nova', - 'version': (2, 1)} + endpoint_filter = { + 'service_type': 'compute', + 'service_name': 'nova', + 'version': (2, 1), + } loader = self.useLoadingFixture(token=token) @@ -74,8 +79,9 @@ def test_conf_loaded(self): m = self.requests_mock.get(url) - auth = loading.load_auth_from_conf_options(self.conf_fixture.conf, - self.GROUP) + auth = loading.load_auth_from_conf_options( + self.conf_fixture.conf, self.GROUP + ) sess = session.Session(auth=auth) self.assertEqual(self.AUTH_TYPE, auth.auth_type) diff --git a/keystoneauth1/tests/unit/loading/test_generic.py b/keystoneauth1/tests/unit/loading/test_generic.py index 687d9b78..9aca1f1f 100644 --- a/keystoneauth1/tests/unit/loading/test_generic.py +++ b/keystoneauth1/tests/unit/loading/test_generic.py @@ -20,28 +20,27 @@ class PasswordTests(utils.TestCase): - def test_options(self): opts = [o.name for o in generic.Password().get_options()] - allowed_opts = ['username', - 'user-domain-id', - 'user-domain-name', - 'user-id', - 'password', - - 'system-scope', - 'domain-id', - 'domain-name', - 'project-id', - 'project-name', - 'project-domain-id', - 'project-domain-name', - 'trust-id', - 'auth-url', - 'default-domain-id', - 'default-domain-name', - ] + allowed_opts = [ + 'username', + 'user-domain-id', + 'user-domain-name', + 'user-id', + 'password', + 'system-scope', + 'domain-id', + 'domain-name', + 'project-id', + 'project-name', + 'project-domain-id', + 'project-domain-name', + 'trust-id', + 'auth-url', + 'default-domain-id', + 'default-domain-name', + ] self.assertEqual(set(allowed_opts), set(opts)) self.assertEqual(len(allowed_opts), len(opts)) @@ -57,7 +56,8 @@ def test_loads_v3_with_user_domain(self): user_id=uuid.uuid4().hex, password=uuid.uuid4().hex, project_id=uuid.uuid4().hex, - user_domain_id=uuid.uuid4().hex) + user_domain_id=uuid.uuid4().hex, + ) inner_plugin = plugin._do_create_plugin(sess) @@ -66,23 +66,23 @@ def test_loads_v3_with_user_domain(self): class TokenTests(utils.TestCase): - def test_options(self): opts = [o.name for o in generic.Token().get_options()] - allowed_opts = ['token', - 'system-scope', - 'domain-id', - 'domain-name', - 'project-id', - 'project-name', - 'project-domain-id', - 'project-domain-name', - 'trust-id', - 'auth-url', - 'default-domain-id', - 'default-domain-name', - ] + allowed_opts = [ + 'token', + 'system-scope', + 'domain-id', + 'domain-name', + 'project-id', + 'project-name', + 'project-domain-id', + 'project-domain-name', + 'trust-id', + 'auth-url', + 'default-domain-id', + 'default-domain-name', + ] self.assertEqual(set(allowed_opts), set(opts)) self.assertEqual(len(allowed_opts), len(opts)) diff --git a/keystoneauth1/tests/unit/loading/test_loading.py b/keystoneauth1/tests/unit/loading/test_loading.py index 3694379d..339018c5 100644 --- a/keystoneauth1/tests/unit/loading/test_loading.py +++ b/keystoneauth1/tests/unit/loading/test_loading.py @@ -19,22 +19,19 @@ from keystoneauth1.tests.unit.loading import utils -class PluginA(object): - +class PluginA: def __init__(self, a): self.val = a -class PluginB(object): - +class PluginB: def __init__(self, b): self.val = b class TestSplitLoader(loading.BaseLoader): - def get_options(self): - opts = super(TestSplitLoader, self).get_options() + opts = super().get_options() opts += [loading.Opt('a'), loading.Opt('b')] return opts @@ -48,10 +45,11 @@ def create_plugin(self, a=None, b=None, **kwargs): class LoadingTests(utils.TestCase): - def test_required_values(self): - opts = [loading.Opt('a', required=False), - loading.Opt('b', required=True)] + opts = [ + loading.Opt('a', required=False), + loading.Opt('b', required=True), + ] Plugin, Loader = utils.create_plugin(opts=opts) @@ -61,9 +59,9 @@ def test_required_values(self): p1 = lo.load_from_options(b=v) self.assertEqual(v, p1['b']) - e = self.assertRaises(exceptions.MissingRequiredOptions, - lo.load_from_options, - a=v) + e = self.assertRaises( + exceptions.MissingRequiredOptions, lo.load_from_options, a=v + ) self.assertEqual(1, len(e.options)) @@ -80,13 +78,14 @@ def test_loaders(self): self.assertIsInstance(loader, loading.BaseLoader) def test_loading_getter(self): - called_opts = [] - vals = {'a-int': 44, - 'a-bool': False, - 'a-float': 99.99, - 'a-str': 'value'} + vals = { + 'a-int': 44, + 'a-bool': False, + 'a-float': 99.99, + 'a-str': 'value', + } val = uuid.uuid4().hex @@ -109,20 +108,19 @@ def _getter(opt): def test_loading_getter_with_kwargs(self): called_opts = set() - vals = {'a-bool': False, - 'a-float': 99.99} + vals = {'a-bool': False, 'a-float': 99.99} def _getter(opt): called_opts.add(opt.name) # return str because oslo.config should convert them back return str(vals[opt.name]) - p = utils.MockLoader().load_from_options_getter(_getter, - a_int=66, - a_str='another') + p = utils.MockLoader().load_from_options_getter( + _getter, a_int=66, a_str='another' + ) # only the options not passed by kwargs should get passed to getter - self.assertEqual(set(('a-bool', 'a-float')), called_opts) + self.assertEqual({'a-bool', 'a-float'}, called_opts) self.assertFalse(p['a_bool']) self.assertEqual(99.99, p['a_float']) diff --git a/keystoneauth1/tests/unit/loading/test_session.py b/keystoneauth1/tests/unit/loading/test_session.py index c3f773ec..db48e8c3 100644 --- a/keystoneauth1/tests/unit/loading/test_session.py +++ b/keystoneauth1/tests/unit/loading/test_session.py @@ -22,24 +22,24 @@ class ConfLoadingTests(utils.TestCase): - GROUP = 'sessiongroup' def setUp(self): - super(ConfLoadingTests, self).setUp() + super().setUp() self.conf_fixture = self.useFixture(config.Config()) - loading.register_session_conf_options(self.conf_fixture.conf, - self.GROUP) + loading.register_session_conf_options( + self.conf_fixture.conf, self.GROUP + ) def config(self, **kwargs): kwargs['group'] = self.GROUP self.conf_fixture.config(**kwargs) def get_session(self, **kwargs): - return loading.load_session_from_conf_options(self.conf_fixture.conf, - self.GROUP, - **kwargs) + return loading.load_session_from_conf_options( + self.conf_fixture.conf, self.GROUP, **kwargs + ) def test_insecure_timeout(self): self.config(insecure=True, timeout=5) @@ -79,7 +79,7 @@ def new_deprecated(): 'collect-timing', 'split-loggers', ] - depr = dict([(n, [new_deprecated()]) for n in opt_names]) + depr = {n: [new_deprecated()] for n in opt_names} opts = loading.get_session_conf_options(deprecated_opts=depr) self.assertThat(opt_names, matchers.HasLength(len(opts))) @@ -88,9 +88,8 @@ def new_deprecated(): class CliLoadingTests(utils.TestCase): - def setUp(self): - super(CliLoadingTests, self).setUp() + super().setUp() self.parser = argparse.ArgumentParser() loading.register_session_argparse_arguments(self.parser) @@ -109,7 +108,7 @@ def test_client_certs(self): cert = '/path/to/certfile' key = '/path/to/keyfile' - s = self.get_session('--os-cert %s --os-key %s' % (cert, key)) + s = self.get_session(f'--os-cert {cert} --os-key {key}') self.assertTrue(s.verify) self.assertEqual((cert, key), s.cert) @@ -117,6 +116,6 @@ def test_client_certs(self): def test_cacert(self): cacert = '/path/to/cacert' - s = self.get_session('--os-cacert %s' % cacert) + s = self.get_session(f'--os-cacert {cacert}') self.assertEqual(cacert, s.verify) diff --git a/keystoneauth1/tests/unit/loading/test_v3.py b/keystoneauth1/tests/unit/loading/test_v3.py index 792db62e..a7f4b5b8 100644 --- a/keystoneauth1/tests/unit/loading/test_v3.py +++ b/keystoneauth1/tests/unit/loading/test_v3.py @@ -19,9 +19,8 @@ class V3PasswordTests(utils.TestCase): - def setUp(self): - super(V3PasswordTests, self).setUp() + super().setUp() self.auth_url = uuid.uuid4().hex @@ -37,11 +36,13 @@ def test_basic(self): project_name = uuid.uuid4().hex project_domain_id = uuid.uuid4().hex - p = self.create(username=username, - user_domain_id=user_domain_id, - project_name=project_name, - project_domain_id=project_domain_id, - password=password) + p = self.create( + username=username, + user_domain_id=user_domain_id, + project_name=project_name, + project_domain_id=project_domain_id, + password=password, + ) pw_method = p.auth_methods[0] @@ -53,24 +54,27 @@ def test_basic(self): self.assertEqual(project_domain_id, p.project_domain_id) def test_without_user_domain(self): - self.assertRaises(exceptions.OptionError, - self.create, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex) + self.assertRaises( + exceptions.OptionError, + self.create, + username=uuid.uuid4().hex, + password=uuid.uuid4().hex, + ) def test_without_project_domain(self): - self.assertRaises(exceptions.OptionError, - self.create, - username=uuid.uuid4().hex, - password=uuid.uuid4().hex, - user_domain_id=uuid.uuid4().hex, - project_name=uuid.uuid4().hex) + self.assertRaises( + exceptions.OptionError, + self.create, + username=uuid.uuid4().hex, + password=uuid.uuid4().hex, + user_domain_id=uuid.uuid4().hex, + project_name=uuid.uuid4().hex, + ) class TOTPTests(utils.TestCase): - def setUp(self): - super(TOTPTests, self).setUp() + super().setUp() self.auth_url = uuid.uuid4().hex @@ -87,11 +91,13 @@ def test_basic(self): project_name = uuid.uuid4().hex project_domain_id = uuid.uuid4().hex - p = self.create(username=username, - user_domain_id=user_domain_id, - project_name=project_name, - project_domain_id=project_domain_id, - passcode=passcode) + p = self.create( + username=username, + user_domain_id=user_domain_id, + project_name=project_name, + project_domain_id=project_domain_id, + passcode=passcode, + ) totp_method = p.auth_methods[0] @@ -103,26 +109,29 @@ def test_basic(self): self.assertEqual(project_domain_id, p.project_domain_id) def test_without_user_domain(self): - self.assertRaises(exceptions.OptionError, - self.create, - username=uuid.uuid4().hex, - passcode=uuid.uuid4().hex) + self.assertRaises( + exceptions.OptionError, + self.create, + username=uuid.uuid4().hex, + passcode=uuid.uuid4().hex, + ) def test_without_project_domain(self): - self.assertRaises(exceptions.OptionError, - self.create, - username=uuid.uuid4().hex, - passcode=uuid.uuid4().hex, - user_domain_id=uuid.uuid4().hex, - project_name=uuid.uuid4().hex) - + self.assertRaises( + exceptions.OptionError, + self.create, + username=uuid.uuid4().hex, + passcode=uuid.uuid4().hex, + user_domain_id=uuid.uuid4().hex, + project_name=uuid.uuid4().hex, + ) -class OpenIDConnectBaseTests(object): +class OpenIDConnectBaseTests: plugin_name = None def setUp(self): - super(OpenIDConnectBaseTests, self).setUp() + super().setUp() self.auth_url = uuid.uuid4().hex @@ -134,26 +143,27 @@ def create(self, **kwargs): def test_base_options_are_there(self): options = loading.get_plugin_loader(self.plugin_name).get_options() self.assertTrue( - set(['client-id', 'client-secret', 'access-token-endpoint', - 'access-token-type', 'openid-scope', - 'discovery-endpoint']).issubset( - set([o.name for o in options])) + { + 'client-id', + 'client-secret', + 'access-token-endpoint', + 'access-token-type', + 'openid-scope', + 'discovery-endpoint', + }.issubset({o.name for o in options}) ) # openid-scope gets renamed into "scope" self.assertIn('scope', [o.dest for o in options]) -class OpenIDConnectClientCredentialsTests(OpenIDConnectBaseTests, - utils.TestCase): - +class OpenIDConnectClientCredentialsTests( + OpenIDConnectBaseTests, utils.TestCase +): plugin_name = "v3oidcclientcredentials" def test_options(self): options = loading.get_plugin_loader(self.plugin_name).get_options() - self.assertTrue( - set(['openid-scope']).issubset( - set([o.name for o in options])) - ) + self.assertTrue({'openid-scope'}.issubset({o.name for o in options})) def test_basic(self): access_token_endpoint = uuid.uuid4().hex @@ -164,12 +174,14 @@ def test_basic(self): client_id = uuid.uuid4().hex client_secret = uuid.uuid4().hex - oidc = self.create(identity_provider=identity_provider, - protocol=protocol, - access_token_endpoint=access_token_endpoint, - client_id=client_id, - client_secret=client_secret, - scope=scope) + oidc = self.create( + identity_provider=identity_provider, + protocol=protocol, + access_token_endpoint=access_token_endpoint, + client_id=client_id, + client_secret=client_secret, + scope=scope, + ) self.assertEqual(scope, oidc.scope) self.assertEqual(identity_provider, oidc.identity_provider) @@ -180,14 +192,14 @@ def test_basic(self): class OpenIDConnectPasswordTests(OpenIDConnectBaseTests, utils.TestCase): - plugin_name = "v3oidcpassword" def test_options(self): options = loading.get_plugin_loader(self.plugin_name).get_options() self.assertTrue( - set(['username', 'password', 'openid-scope']).issubset( - set([o.name for o in options])) + {'username', 'password', 'openid-scope'}.issubset( + {o.name for o in options} + ) ) def test_basic(self): @@ -201,14 +213,16 @@ def test_basic(self): client_id = uuid.uuid4().hex client_secret = uuid.uuid4().hex - oidc = self.create(username=username, - password=password, - identity_provider=identity_provider, - protocol=protocol, - access_token_endpoint=access_token_endpoint, - client_id=client_id, - client_secret=client_secret, - scope=scope) + oidc = self.create( + username=username, + password=password, + identity_provider=identity_provider, + protocol=protocol, + access_token_endpoint=access_token_endpoint, + client_id=client_id, + client_secret=client_secret, + scope=scope, + ) self.assertEqual(username, oidc.username) self.assertEqual(password, oidc.password) @@ -221,14 +235,12 @@ def test_basic(self): class OpenIDConnectAuthCodeTests(OpenIDConnectBaseTests, utils.TestCase): - plugin_name = "v3oidcauthcode" def test_options(self): options = loading.get_plugin_loader(self.plugin_name).get_options() self.assertTrue( - set(['redirect-uri', 'code']).issubset( - set([o.name for o in options])) + {'redirect-uri', 'code'}.issubset({o.name for o in options}) ) def test_basic(self): @@ -241,14 +253,16 @@ def test_basic(self): client_id = uuid.uuid4().hex client_secret = uuid.uuid4().hex - oidc = self.create(code=authorization_code, - redirect_uri=redirect_uri, - identity_provider=identity_provider, - protocol=protocol, - access_token_endpoint=access_token_endpoint, - client_id=client_id, - client_secret=client_secret, - scope=scope) + oidc = self.create( + code=authorization_code, + redirect_uri=redirect_uri, + identity_provider=identity_provider, + protocol=protocol, + access_token_endpoint=access_token_endpoint, + client_id=client_id, + client_secret=client_secret, + scope=scope, + ) self.assertEqual(redirect_uri, oidc.redirect_uri) self.assertEqual(authorization_code, oidc.code) @@ -261,11 +275,10 @@ def test_basic(self): class OpenIDConnectAccessToken(utils.TestCase): - plugin_name = "v3oidcaccesstoken" def setUp(self): - super(OpenIDConnectAccessToken, self).setUp() + super().setUp() self.auth_url = uuid.uuid4().hex @@ -276,19 +289,18 @@ def create(self, **kwargs): def test_options(self): options = loading.get_plugin_loader(self.plugin_name).get_options() - self.assertTrue( - set(['access-token']).issubset( - set([o.name for o in options])) - ) + self.assertTrue({'access-token'}.issubset({o.name for o in options})) def test_basic(self): access_token = uuid.uuid4().hex identity_provider = uuid.uuid4().hex protocol = uuid.uuid4().hex - oidc = self.create(access_token=access_token, - identity_provider=identity_provider, - protocol=protocol) + oidc = self.create( + access_token=access_token, + identity_provider=identity_provider, + protocol=protocol, + ) self.assertEqual(identity_provider, oidc.identity_provider) self.assertEqual(protocol, oidc.protocol) @@ -296,11 +308,10 @@ def test_basic(self): class OpenIDConnectDeviceAuthorizationTests(utils.TestCase): - plugin_name = "v3oidcdeviceauthz" def setUp(self): - super(OpenIDConnectDeviceAuthorizationTests, self).setUp() + super().setUp() self.auth_url = uuid.uuid4().hex @@ -312,10 +323,14 @@ def create(self, **kwargs): def test_options(self): options = loading.get_plugin_loader(self.plugin_name).get_options() self.assertTrue( - set(['client-id', 'client-secret', 'access-token-endpoint', - 'openid-scope', 'discovery-endpoint', - 'device-authorization-endpoint']).issubset( - set([o.name for o in options])) + { + 'client-id', + 'client-secret', + 'access-token-endpoint', + 'openid-scope', + 'discovery-endpoint', + 'device-authorization-endpoint', + }.issubset({o.name for o in options}) ) def test_basic(self): @@ -328,13 +343,15 @@ def test_basic(self): client_secret = uuid.uuid4().hex dev_authz_endpt = device_authorization_endpoint - oidc = self.create(identity_provider=identity_provider, - protocol=protocol, - access_token_endpoint=access_token_endpoint, - device_authorization_endpoint=dev_authz_endpt, - client_id=client_id, - client_secret=client_secret, - scope=scope) + oidc = self.create( + identity_provider=identity_provider, + protocol=protocol, + access_token_endpoint=access_token_endpoint, + device_authorization_endpoint=dev_authz_endpt, + client_id=client_id, + client_secret=client_secret, + scope=scope, + ) self.assertEqual(dev_authz_endpt, oidc.device_authorization_endpoint) self.assertEqual(identity_provider, oidc.identity_provider) @@ -346,9 +363,8 @@ def test_basic(self): class V3TokenlessAuthTests(utils.TestCase): - def setUp(self): - super(V3TokenlessAuthTests, self).setUp() + super().setUp() self.auth_url = uuid.uuid4().hex @@ -365,12 +381,14 @@ def test_basic(self): project_domain_id = uuid.uuid4().hex project_domain_name = uuid.uuid4().hex - tla = self.create(domain_id=domain_id, - domain_name=domain_name, - project_id=project_id, - project_name=project_name, - project_domain_id=project_domain_id, - project_domain_name=project_domain_name) + tla = self.create( + domain_id=domain_id, + domain_name=domain_name, + project_id=project_id, + project_name=project_name, + project_domain_id=project_domain_id, + project_domain_name=project_domain_name, + ) self.assertEqual(domain_id, tla.domain_id) self.assertEqual(domain_name, tla.domain_name) @@ -380,45 +398,44 @@ def test_basic(self): self.assertEqual(project_domain_name, tla.project_domain_name) def test_missing_parameters(self): - self.assertRaises(exceptions.OptionError, - self.create, - domain_id=None) - self.assertRaises(exceptions.OptionError, - self.create, - domain_name=None) - self.assertRaises(exceptions.OptionError, - self.create, - project_id=None) - self.assertRaises(exceptions.OptionError, - self.create, - project_name=None) - self.assertRaises(exceptions.OptionError, - self.create, - project_domain_id=None) - self.assertRaises(exceptions.OptionError, - self.create, - project_domain_name=None) + self.assertRaises(exceptions.OptionError, self.create, domain_id=None) + self.assertRaises( + exceptions.OptionError, self.create, domain_name=None + ) + self.assertRaises(exceptions.OptionError, self.create, project_id=None) + self.assertRaises( + exceptions.OptionError, self.create, project_name=None + ) + self.assertRaises( + exceptions.OptionError, self.create, project_domain_id=None + ) + self.assertRaises( + exceptions.OptionError, self.create, project_domain_name=None + ) # only when a project_name is provided, project_domain_id will # be use to uniquely identify the project. It's an invalid # option when it's just by itself. - self.assertRaises(exceptions.OptionError, - self.create, - project_domain_id=uuid.uuid4().hex) + self.assertRaises( + exceptions.OptionError, + self.create, + project_domain_id=uuid.uuid4().hex, + ) # only when a project_name is provided, project_domain_name will # be use to uniquely identify the project. It's an invalid # option when it's just by itself. - self.assertRaises(exceptions.OptionError, - self.create, - project_domain_name=uuid.uuid4().hex) - self.assertRaises(exceptions.OptionError, - self.create, - project_name=uuid.uuid4().hex) + self.assertRaises( + exceptions.OptionError, + self.create, + project_domain_name=uuid.uuid4().hex, + ) + self.assertRaises( + exceptions.OptionError, self.create, project_name=uuid.uuid4().hex + ) class V3ApplicationCredentialTests(utils.TestCase): - def setUp(self): - super(V3ApplicationCredentialTests, self).setUp() + super().setUp() self.auth_url = uuid.uuid4().hex @@ -431,8 +448,9 @@ def test_basic(self): id = uuid.uuid4().hex secret = uuid.uuid4().hex - app_cred = self.create(application_credential_id=id, - application_credential_secret=secret) + app_cred = self.create( + application_credential_id=id, application_credential_secret=secret + ) ac_method = app_cred.auth_methods[0] @@ -445,10 +463,12 @@ def test_with_name(self): username = uuid.uuid4().hex user_domain_id = uuid.uuid4().hex - app_cred = self.create(application_credential_name=name, - application_credential_secret=secret, - username=username, - user_domain_id=user_domain_id) + app_cred = self.create( + application_credential_name=name, + application_credential_secret=secret, + username=username, + user_domain_id=user_domain_id, + ) ac_method = app_cred.auth_methods[0] @@ -458,31 +478,36 @@ def test_with_name(self): self.assertEqual(user_domain_id, ac_method.user_domain_id) def test_without_user_domain(self): - self.assertRaises(exceptions.OptionError, - self.create, - application_credential_name=uuid.uuid4().hex, - username=uuid.uuid4().hex, - application_credential_secret=uuid.uuid4().hex) + self.assertRaises( + exceptions.OptionError, + self.create, + application_credential_name=uuid.uuid4().hex, + username=uuid.uuid4().hex, + application_credential_secret=uuid.uuid4().hex, + ) def test_without_name_or_id(self): - self.assertRaises(exceptions.OptionError, - self.create, - username=uuid.uuid4().hex, - user_domain_id=uuid.uuid4().hex, - application_credential_secret=uuid.uuid4().hex) + self.assertRaises( + exceptions.OptionError, + self.create, + username=uuid.uuid4().hex, + user_domain_id=uuid.uuid4().hex, + application_credential_secret=uuid.uuid4().hex, + ) def test_without_secret(self): - self.assertRaises(exceptions.OptionError, - self.create, - application_credential_id=uuid.uuid4().hex, - username=uuid.uuid4().hex, - user_domain_id=uuid.uuid4().hex) + self.assertRaises( + exceptions.OptionError, + self.create, + application_credential_id=uuid.uuid4().hex, + username=uuid.uuid4().hex, + user_domain_id=uuid.uuid4().hex, + ) class MultiFactorTests(utils.TestCase): - def setUp(self): - super(MultiFactorTests, self).setUp() + super().setUp() self.auth_url = uuid.uuid4().hex @@ -507,7 +532,8 @@ def test_password_and_totp(self): user_domain_id=user_domain_id, project_name=project_name, project_domain_id=project_domain_id, - passcode=passcode) + passcode=passcode, + ) password_method = p.auth_methods[0] totp_method = p.auth_methods[1] @@ -524,24 +550,27 @@ def test_password_and_totp(self): self.assertEqual(project_domain_id, p.project_domain_id) def test_without_methods(self): - self.assertRaises(exceptions.OptionError, - self.create, - username=uuid.uuid4().hex, - passcode=uuid.uuid4().hex) + self.assertRaises( + exceptions.OptionError, + self.create, + username=uuid.uuid4().hex, + passcode=uuid.uuid4().hex, + ) def test_without_user_domain_for_password(self): - self.assertRaises(exceptions.OptionError, - self.create, - methods=['v3password'], - username=uuid.uuid4().hex, - project_name=uuid.uuid4().hex, - project_domain_id=uuid.uuid4().hex) + self.assertRaises( + exceptions.OptionError, + self.create, + methods=['v3password'], + username=uuid.uuid4().hex, + project_name=uuid.uuid4().hex, + project_domain_id=uuid.uuid4().hex, + ) class V3Oauth2ClientCredentialTests(utils.TestCase): - def setUp(self): - super(V3Oauth2ClientCredentialTests, self).setUp() + super().setUp() self.auth_url = uuid.uuid4().hex @@ -555,9 +584,11 @@ def test_basic(self): secret = uuid.uuid4().hex oauth2_endpoint = "https://localhost/token" - client_cred = self.create(oauth2_endpoint=oauth2_endpoint, - oauth2_client_id=id, - oauth2_client_secret=secret) + client_cred = self.create( + oauth2_endpoint=oauth2_endpoint, + oauth2_client_id=id, + oauth2_client_secret=secret, + ) client_method = client_cred.auth_methods[0] self.assertEqual(id, client_method.oauth2_client_id) @@ -571,30 +602,35 @@ def test_basic(self): def test_without_oauth2_endpoint(self): id = uuid.uuid4().hex secret = uuid.uuid4().hex - self.assertRaises(exceptions.OptionError, - self.create, - oauth2_client_id=id, - oauth2_client_secret=secret) + self.assertRaises( + exceptions.OptionError, + self.create, + oauth2_client_id=id, + oauth2_client_secret=secret, + ) def test_without_client_id(self): oauth2_endpoint = "https://localhost/token" - self.assertRaises(exceptions.OptionError, - self.create, - oauth2_endpoint=oauth2_endpoint, - oauth2_client_secret=uuid.uuid4().hex) + self.assertRaises( + exceptions.OptionError, + self.create, + oauth2_endpoint=oauth2_endpoint, + oauth2_client_secret=uuid.uuid4().hex, + ) def test_without_secret(self): oauth2_endpoint = "https://localhost/token" - self.assertRaises(exceptions.OptionError, - self.create, - oauth2_endpoint=oauth2_endpoint, - oauth2_client_id=uuid.uuid4().hex) + self.assertRaises( + exceptions.OptionError, + self.create, + oauth2_endpoint=oauth2_endpoint, + oauth2_client_id=uuid.uuid4().hex, + ) class V3Oauth2mTlsClientCredentialTests(utils.TestCase): - def setUp(self): - super(V3Oauth2mTlsClientCredentialTests, self).setUp() + super().setUp() self.auth_url = uuid.uuid4().hex @@ -607,23 +643,24 @@ def test_basic(self): client_id = uuid.uuid4().hex oauth2_endpoint = "https://localhost/token" - client_cred = self.create(oauth2_endpoint=oauth2_endpoint, - oauth2_client_id=client_id - ) + client_cred = self.create( + oauth2_endpoint=oauth2_endpoint, oauth2_client_id=client_id + ) self.assertEqual(self.auth_url, client_cred.auth_url) self.assertEqual(client_id, client_cred.oauth2_client_id) self.assertEqual(oauth2_endpoint, client_cred.oauth2_endpoint) def test_without_oauth2_endpoint(self): client_id = uuid.uuid4().hex - self.assertRaises(exceptions.OptionError, - self.create, - oauth2_client_id=client_id, - ) + self.assertRaises( + exceptions.OptionError, self.create, oauth2_client_id=client_id + ) def test_without_client_id(self): oauth2_endpoint = "https://localhost/token" - self.assertRaises(exceptions.OptionError, - self.create, - oauth2_endpoint=oauth2_endpoint, - oauth2_client_secret=uuid.uuid4().hex) + self.assertRaises( + exceptions.OptionError, + self.create, + oauth2_endpoint=oauth2_endpoint, + oauth2_client_secret=uuid.uuid4().hex, + ) diff --git a/keystoneauth1/tests/unit/loading/utils.py b/keystoneauth1/tests/unit/loading/utils.py index ee838cf3..1cbba30d 100644 --- a/keystoneauth1/tests/unit/loading/utils.py +++ b/keystoneauth1/tests/unit/loading/utils.py @@ -22,7 +22,6 @@ class TestCase(utils.TestCase): - GROUP = 'auth' V2PASS = 'v2password' V3TOKEN = 'v3token' @@ -31,9 +30,7 @@ class TestCase(utils.TestCase): a_float = 88.8 a_bool = False - TEST_VALS = {'a_int': a_int, - 'a_float': a_float, - 'a_bool': a_bool} + TEST_VALS = {'a_int': a_int, 'a_float': a_float, 'a_bool': a_bool} def assertTestVals(self, plugin, vals=TEST_VALS): for k, v in vals.items(): @@ -41,9 +38,7 @@ def assertTestVals(self, plugin, vals=TEST_VALS): def create_plugin(opts=[], token=None, endpoint=None): - class Plugin(plugin.BaseAuthPlugin): - def __init__(self, **kwargs): self._data = kwargs @@ -57,7 +52,6 @@ def get_endpoint(self, *args, **kwargs): return endpoint class Loader(loading.BaseLoader): - @property def plugin_class(self): return Plugin @@ -68,8 +62,7 @@ def get_options(self): return Plugin, Loader -class BoolType(object): - +class BoolType: def __eq__(self, other): """Define equiality for many bool types.""" # hack around oslo.config equality comparison @@ -100,12 +93,11 @@ def __call__(self, value): loading.Opt('a-bool', type=BoolType(), help=BOOL_DESC), loading.Opt('a-float', type=float, help=FLOAT_DESC), loading.Opt('a-str', help=STR_DESC, default=STR_DEFAULT), - ] + ], ) -class MockManager(object): - +class MockManager: def __init__(self, driver): self.driver = driver @@ -120,4 +112,5 @@ def inner(*args, **kwargs): return f(*args, **kwargs) return inner + return _wrapper diff --git a/keystoneauth1/tests/unit/matchers.py b/keystoneauth1/tests/unit/matchers.py index 6322850e..e8f538a2 100644 --- a/keystoneauth1/tests/unit/matchers.py +++ b/keystoneauth1/tests/unit/matchers.py @@ -16,7 +16,7 @@ from testtools import matchers -class XMLEquals(object): +class XMLEquals: """Parses two XML documents from strings and compares the results.""" def __init__(self, expected): @@ -24,7 +24,7 @@ def __init__(self, expected): def __str__(self): """Return string representation of xml document info.""" - return "%s(%r)" % (self.__class__.__name__, self.expected) + return f"{self.__class__.__name__}({self.expected!r})" def match(self, other): def xml_element_equals(expected_doc, observed_doc): @@ -55,8 +55,9 @@ def _sorted_children(doc): if len(expected_children) != len(observed_children): return False - for expected_el, observed_el in zip(expected_children, - observed_children): + for expected_el, observed_el in zip( + expected_children, observed_children + ): if not xml_element_equals(expected_el, observed_el): return False @@ -73,7 +74,6 @@ def _sorted_children(doc): class XMLMismatch(matchers.Mismatch): - def __init__(self, expected, other): self.expected = expected self.other = other @@ -82,8 +82,8 @@ def describe(self): def pretty_xml(xml): parser = etree.XMLParser(remove_blank_text=True) doc = etree.fromstring(xml.strip(), parser) - return (etree.tostring(doc, encoding='utf-8', pretty_print=True) - .decode('utf-8')) + return etree.tostring( + doc, encoding='utf-8', pretty_print=True + ).decode('utf-8') - return 'expected =\n%s\nactual =\n%s' % ( - pretty_xml(self.expected), pretty_xml(self.other)) + return f'expected =\n{pretty_xml(self.expected)}\nactual =\n{pretty_xml(self.other)}' diff --git a/keystoneauth1/tests/unit/oidc_fixtures.py b/keystoneauth1/tests/unit/oidc_fixtures.py index 245fd887..007d59cc 100644 --- a/keystoneauth1/tests/unit/oidc_fixtures.py +++ b/keystoneauth1/tests/unit/oidc_fixtures.py @@ -18,19 +18,13 @@ "expires_at": "2014-06-09T10:48:59.643375Z", "user": { "OS-FEDERATION": { - "identity_provider": { - "id": "bluepages" - }, - "protocol": { - "id": "oidc" - }, - "groups": [ - {"id": "1764fa5cf69a49a4918131de5ce4af9a"} - ] + "identity_provider": {"id": "bluepages"}, + "protocol": {"id": "oidc"}, + "groups": [{"id": "1764fa5cf69a49a4918131de5ce4af9a"}], }, "id": "oidc_user%40example.com", - "name": "oidc_user@example.com" - } + "name": "oidc_user@example.com", + }, } } @@ -39,7 +33,7 @@ "token_type": "bearer", "expires_in": 3599, "scope": "openid profile", - "refresh_token": "DCERsh83IAhu9bhavrp" + "refresh_token": "DCERsh83IAhu9bhavrp", } ACCESS_TOKEN_VIA_AUTH_GRANT_RESP = { @@ -47,17 +41,16 @@ "token_type": "Bearer", "expires_in": 3600, "refresh_token": "1/ySXNO9XISBMIgOrJDtdun6zK6XiATCKT", - "id_token": "eyJhbGciOiJSUzI1Ni8hOYHuZT8dt_yynmJVhcU" + "id_token": "eyJhbGciOiJSUzI1Ni8hOYHuZT8dt_yynmJVhcU", } DEVICE_CODE_RESP = { 'device_code': "fRtNXLxmRy4iEzLsbAV96pMFgOMEUCPZmAMepjLrvQ", 'user_code': "ABCD-EFGH", 'verification_uri': "https://localhost:8020/oidc/authorize/device", - 'verification_uri_complete': - "https://localhost:8020/oidc/authorize/device?user_code=ABCD-EFGH", + 'verification_uri_complete': "https://localhost:8020/oidc/authorize/device?user_code=ABCD-EFGH", 'expires_in': 1800, - 'interval': 5 + 'interval': 5, } DISCOVERY_DOCUMENT = { @@ -82,7 +75,7 @@ "email_verified", "phone_number", "phone_number_verified", - "address" + "address", ], "grant_types_supported": [ "authorization_code", @@ -99,13 +92,12 @@ "service_documentation": "https://localhost:8020/oidc/about", "token_endpoint": "https://localhost:8020/oidc/token", "userinfo_endpoint": "https://localhost:8020/oidc/userinfo", - "device_authorization_endpoint": - "https://localhost:8020/oidc/authorize/device", + "device_authorization_endpoint": "https://localhost:8020/oidc/authorize/device", "token_endpoint_auth_methods_supported": [ "client_secret_post", "client_secret_basic", "client_secret_jwt", "private_key_jwt", - "none" + "none", ], } diff --git a/keystoneauth1/tests/unit/test_betamax_fixture.py b/keystoneauth1/tests/unit/test_betamax_fixture.py index fb181994..f79b8829 100644 --- a/keystoneauth1/tests/unit/test_betamax_fixture.py +++ b/keystoneauth1/tests/unit/test_betamax_fixture.py @@ -24,29 +24,32 @@ class TestBetamaxFixture(testtools.TestCase): - TEST_USERNAME = 'test_user_name' TEST_PASSWORD = 'test_password' TEST_TENANT_NAME = 'test_tenant_name' TEST_AUTH_URL = 'http://keystoneauth-betamax.test/v2.0/' - V2_TOKEN = v2Fixtures.Token(tenant_name=TEST_TENANT_NAME, - user_name=TEST_USERNAME) + V2_TOKEN = v2Fixtures.Token( + tenant_name=TEST_TENANT_NAME, user_name=TEST_USERNAME + ) def setUp(self): - super(TestBetamaxFixture, self).setUp() + super().setUp() self.ksa_betamax_fixture = self.useFixture( keystoneauth_betamax.BetamaxFixture( cassette_name='ksa_betamax_test_cassette', cassette_library_dir='keystoneauth1/tests/unit/data/', - record=False)) + record=False, + ) + ) def _replay_cassette(self): plugin = v2.Password( auth_url=self.TEST_AUTH_URL, password=self.TEST_PASSWORD, username=self.TEST_USERNAME, - tenant_name=self.TEST_TENANT_NAME) + tenant_name=self.TEST_TENANT_NAME, + ) s = session.Session() s.get_token(auth=plugin) @@ -58,7 +61,8 @@ def test_replay_of_bad_url_fails(self): auth_url='http://invalid-auth-url/v2.0/', password=self.TEST_PASSWORD, username=self.TEST_USERNAME, - tenant_name=self.TEST_TENANT_NAME) + tenant_name=self.TEST_TENANT_NAME, + ) s = session.Session() self.assertRaises(exceptions.BetamaxError, s.get_token, auth=plugin) diff --git a/keystoneauth1/tests/unit/test_betamax_hooks.py b/keystoneauth1/tests/unit/test_betamax_hooks.py index 8c5116fe..31438dbb 100644 --- a/keystoneauth1/tests/unit/test_betamax_hooks.py +++ b/keystoneauth1/tests/unit/test_betamax_hooks.py @@ -26,7 +26,6 @@ class TestBetamaxHooks(testtools.TestCase): - def test_pre_record_hook_v3(self): fixtures_path = 'keystoneauth1/tests/unit/data' @@ -34,8 +33,11 @@ def test_pre_record_hook_v3(self): config.before_record(callback=hooks.pre_record_hook) cassette = betamax.cassette.Cassette( - 'test_pre_record_hook', 'json', record_mode=None, - cassette_library_dir=fixtures_path) + 'test_pre_record_hook', + 'json', + record_mode=None, + cassette_library_dir=fixtures_path, + ) # Create a new object to serialize r = models.Response() @@ -46,9 +48,9 @@ def test_pre_record_hook_v3(self): r.url = 'http://localhost:35357/' # load request and response - with open('%s/keystone_v3_sample_response.json' % fixtures_path) as f: + with open(f'{fixtures_path}/keystone_v3_sample_response.json') as f: response_content = json.loads(f.read()) - with open('%s/keystone_v3_sample_request.json' % fixtures_path) as f: + with open(f'{fixtures_path}/keystone_v3_sample_request.json') as f: request_content = json.loads(f.read()) body_content = { @@ -59,8 +61,8 @@ def test_pre_record_hook_v3(self): } betamax.util.add_urllib3_response( - body_content, r, - HTTPHeaderDict({'Accept': 'application/json'})) + body_content, r, HTTPHeaderDict({'Accept': 'application/json'}) + ) response = r # Create an associated request @@ -70,9 +72,7 @@ def test_pre_record_hook_v3(self): r.headers = {} r.data = {} response.request = r.prepare() - response.request.headers.update( - {'User-Agent': 'betamax/test header'} - ) + response.request.headers.update({'User-Agent': 'betamax/test header'}) response.request.body = json.dumps(request_content) @@ -80,27 +80,34 @@ def test_pre_record_hook_v3(self): # check that all values have been masked response_content = json.loads( - interaction.data['response']['body']['string']) - self.assertEqual( - response_content['token']['expires_at'], - u'9999-12-31T23:59:59Z') + interaction.data['response']['body']['string'] + ) self.assertEqual( - response_content['token']['project']['domain']['id'], - u'dummy') + response_content['token']['expires_at'], '9999-12-31T23:59:59Z' + ) self.assertEqual( - response_content['token']['user']['domain']['id'], - u'dummy') + response_content['token']['project']['domain']['id'], 'dummy' + ) self.assertEqual( - response_content['token']['user']['name'], u'dummy') + response_content['token']['user']['domain']['id'], 'dummy' + ) + self.assertEqual(response_content['token']['user']['name'], 'dummy') request_content = json.loads( - interaction.data['request']['body']['string']) + interaction.data['request']['body']['string'] + ) self.assertEqual( - request_content['auth']['identity']['password'] - ['user']['domain']['id'], u'dummy') + request_content['auth']['identity']['password']['user']['domain'][ + 'id' + ], + 'dummy', + ) self.assertEqual( - request_content['auth']['identity']['password'] - ['user']['password'], u'********') + request_content['auth']['identity']['password']['user'][ + 'password' + ], + '********', + ) def test_pre_record_hook_v2(self): fixtures_path = 'keystoneauth1/tests/unit/data' @@ -109,8 +116,11 @@ def test_pre_record_hook_v2(self): config.before_record(callback=hooks.pre_record_hook) cassette = betamax.cassette.Cassette( - 'test_pre_record_hook', 'json', record_mode=None, - cassette_library_dir=fixtures_path) + 'test_pre_record_hook', + 'json', + record_mode=None, + cassette_library_dir=fixtures_path, + ) # Create a new object to serialize r = models.Response() @@ -121,9 +131,9 @@ def test_pre_record_hook_v2(self): r.url = 'http://localhost:35357/' # load request and response - with open('%s/keystone_v2_sample_response.json' % fixtures_path) as f: + with open(f'{fixtures_path}/keystone_v2_sample_response.json') as f: response_content = json.loads(f.read()) - with open('%s/keystone_v2_sample_request.json' % fixtures_path) as f: + with open(f'{fixtures_path}/keystone_v2_sample_request.json') as f: request_content = json.loads(f.read()) body_content = { @@ -134,8 +144,8 @@ def test_pre_record_hook_v2(self): } betamax.util.add_urllib3_response( - body_content, r, - HTTPHeaderDict({'Accept': 'application/json'})) + body_content, r, HTTPHeaderDict({'Accept': 'application/json'}) + ) response = r # Create an associated request @@ -145,9 +155,7 @@ def test_pre_record_hook_v2(self): r.headers = {} r.data = {} response.request = r.prepare() - response.request.headers.update( - {'User-Agent': 'betamax/test header'} - ) + response.request.headers.update({'User-Agent': 'betamax/test header'}) response.request.body = json.dumps(request_content) @@ -155,44 +163,35 @@ def test_pre_record_hook_v2(self): # check that all values have been masked response_content = json.loads( - interaction.data['response']['body']['string']) + interaction.data['response']['body']['string'] + ) self.assertEqual( response_content['access']['token']['expires'], - u'9999-12-31T23:59:59Z') - self.assertEqual( - response_content['access']['token']['tenant']['name'], - u'dummy') + '9999-12-31T23:59:59Z', + ) self.assertEqual( - response_content['access']['user']['name'], - u'dummy') + response_content['access']['token']['tenant']['name'], 'dummy' + ) + self.assertEqual(response_content['access']['user']['name'], 'dummy') request_content = json.loads( - interaction.data['request']['body']['string']) + interaction.data['request']['body']['string'] + ) self.assertEqual( request_content['auth']['passwordCredentials']['password'], - u'********') - self.assertEqual( - request_content['auth']['passwordCredentials']['username'], - u'dummy') + '********', + ) self.assertEqual( - request_content['auth']['tenantName'], u'dummy') + request_content['auth']['passwordCredentials']['username'], 'dummy' + ) + self.assertEqual(request_content['auth']['tenantName'], 'dummy') @mock.patch('keystoneauth1.fixture.hooks.mask_fixture_values') def test_pre_record_hook_empty_body(self, mask_fixture_values): interaction = mock.Mock() interaction.data = { - 'request': { - 'body': { - 'encoding': 'utf-8', - 'string': '', - }, - }, - 'response': { - 'body': { - 'encoding': 'utf-8', - 'string': '', - }, - }, + 'request': {'body': {'encoding': 'utf-8', 'string': ''}}, + 'response': {'body': {'encoding': 'utf-8', 'string': ''}}, } hooks.pre_record_hook(interaction, mock.Mock()) diff --git a/keystoneauth1/tests/unit/test_betamax_serializer.py b/keystoneauth1/tests/unit/test_betamax_serializer.py index a69318db..d90514b1 100644 --- a/keystoneauth1/tests/unit/test_betamax_serializer.py +++ b/keystoneauth1/tests/unit/test_betamax_serializer.py @@ -20,34 +20,37 @@ class TestBetamaxSerializer(testtools.TestCase): - TEST_FILE = os.path.join( os.path.dirname(os.path.abspath(__file__)), - 'data', 'ksa_betamax_test_cassette.yaml') + 'data', + 'ksa_betamax_test_cassette.yaml', + ) TEST_JSON = os.path.join( os.path.dirname(os.path.abspath(__file__)), - 'data', 'ksa_serializer_data.json') + 'data', + 'ksa_serializer_data.json', + ) def setUp(self): - super(TestBetamaxSerializer, self).setUp() + super().setUp() self.serializer = serializer.YamlJsonSerializer() def test_deserialize(self): - data = self.serializer.deserialize(open(self.TEST_FILE, 'r').read()) + data = self.serializer.deserialize(open(self.TEST_FILE).read()) request = data['http_interactions'][0]['request'] self.assertEqual( - 'http://keystoneauth-betamax.test/v2.0/tokens', - request['uri']) + 'http://keystoneauth-betamax.test/v2.0/tokens', request['uri'] + ) payload = json.loads(request['body']['string']) self.assertEqual('test_tenant_name', payload['auth']['tenantName']) def test_serialize(self): - data = json.loads(open(self.TEST_JSON, 'r').read()) + data = json.loads(open(self.TEST_JSON).read()) serialized = self.serializer.serialize(data) data = yaml.safe_load(serialized) request = data['http_interactions'][0]['request'] self.assertEqual( - 'http://keystoneauth-betamax.test/v2.0/tokens', - request['uri']) + 'http://keystoneauth-betamax.test/v2.0/tokens', request['uri'] + ) payload = json.loads(request['body']['string']) self.assertEqual('test_tenant_name', payload['auth']['tenantName']) diff --git a/keystoneauth1/tests/unit/test_discovery.py b/keystoneauth1/tests/unit/test_discovery.py index 8e8184fa..48cfbad5 100644 --- a/keystoneauth1/tests/unit/test_discovery.py +++ b/keystoneauth1/tests/unit/test_discovery.py @@ -28,108 +28,114 @@ BASE_HOST = 'http://keystone.example.com' -BASE_URL = "%s:5000/" % BASE_HOST +BASE_URL = f"{BASE_HOST}:5000/" UPDATED = '2013-03-06T00:00:00Z' -TEST_SERVICE_CATALOG = [{ - "endpoints": [{ - "adminURL": "%s:8774/v1.0" % BASE_HOST, - "region": "RegionOne", - "internalURL": "%s://127.0.0.1:8774/v1.0" % BASE_HOST, - "publicURL": "%s:8774/v1.0/" % BASE_HOST - }], - "type": "nova_compat", - "name": "nova_compat" -}, { - "endpoints": [{ - "adminURL": "http://nova/novapi/admin", - "region": "RegionOne", - "internalURL": "http://nova/novapi/internal", - "publicURL": "http://nova/novapi/public" - }], - "type": "compute", - "name": "nova" -}, { - "endpoints": [{ - "adminURL": "http://glance/glanceapi/admin", - "region": "RegionOne", - "internalURL": "http://glance/glanceapi/internal", - "publicURL": "http://glance/glanceapi/public" - }], - "type": "image", - "name": "glance" -}, { - "endpoints": [{ - "adminURL": "%s:35357/v2.0" % BASE_HOST, - "region": "RegionOne", - "internalURL": "%s:5000/v2.0" % BASE_HOST, - "publicURL": "%s:5000/v2.0" % BASE_HOST - }], - "type": "identity", - "name": "keystone" -}, { - "endpoints": [{ - "adminURL": "http://swift/swiftapi/admin", - "region": "RegionOne", - "internalURL": "http://swift/swiftapi/internal", - "publicURL": "http://swift/swiftapi/public" - }], - "type": "object-store", - "name": "swift" -}] - -V2_URL = "%sv2.0" % BASE_URL +TEST_SERVICE_CATALOG = [ + { + "endpoints": [ + { + "adminURL": f"{BASE_HOST}:8774/v1.0", + "region": "RegionOne", + "internalURL": f"{BASE_HOST}://127.0.0.1:8774/v1.0", + "publicURL": f"{BASE_HOST}:8774/v1.0/", + } + ], + "type": "nova_compat", + "name": "nova_compat", + }, + { + "endpoints": [ + { + "adminURL": "http://nova/novapi/admin", + "region": "RegionOne", + "internalURL": "http://nova/novapi/internal", + "publicURL": "http://nova/novapi/public", + } + ], + "type": "compute", + "name": "nova", + }, + { + "endpoints": [ + { + "adminURL": "http://glance/glanceapi/admin", + "region": "RegionOne", + "internalURL": "http://glance/glanceapi/internal", + "publicURL": "http://glance/glanceapi/public", + } + ], + "type": "image", + "name": "glance", + }, + { + "endpoints": [ + { + "adminURL": f"{BASE_HOST}:35357/v2.0", + "region": "RegionOne", + "internalURL": f"{BASE_HOST}:5000/v2.0", + "publicURL": f"{BASE_HOST}:5000/v2.0", + } + ], + "type": "identity", + "name": "keystone", + }, + { + "endpoints": [ + { + "adminURL": "http://swift/swiftapi/admin", + "region": "RegionOne", + "internalURL": "http://swift/swiftapi/internal", + "publicURL": "http://swift/swiftapi/public", + } + ], + "type": "object-store", + "name": "swift", + }, +] + +V2_URL = f"{BASE_URL}v2.0" V2_VERSION = fixture.V2Discovery(V2_URL) V2_VERSION.updated_str = UPDATED -V2_AUTH_RESPONSE = json.dumps({ - "access": { - "token": { - "expires": "2020-01-01T00:00:10.000123Z", - "id": 'fakeToken', - "tenant": { - "id": '1' +V2_AUTH_RESPONSE = json.dumps( + { + "access": { + "token": { + "expires": "2020-01-01T00:00:10.000123Z", + "id": 'fakeToken', + "tenant": {"id": '1'}, }, - }, - "user": { - "id": 'test' - }, - "serviceCatalog": TEST_SERVICE_CATALOG, - }, -}) + "user": {"id": 'test'}, + "serviceCatalog": TEST_SERVICE_CATALOG, + } + } +) -V3_URL = "%sv3" % BASE_URL +V3_URL = f"{BASE_URL}v3" V3_VERSION = fixture.V3Discovery(V3_URL) V3_MEDIA_TYPES = V3_VERSION.media_types V3_VERSION.updated_str = UPDATED -V3_AUTH_RESPONSE = json.dumps({ - "token": { - "methods": [ - "token", - "password" - ], - - "expires_at": "2020-01-01T00:00:10.000123Z", - "project": { - "domain": { +V3_AUTH_RESPONSE = json.dumps( + { + "token": { + "methods": ["token", "password"], + "expires_at": "2020-01-01T00:00:10.000123Z", + "project": { + "domain": {"id": '1', "name": 'test-domain'}, "id": '1', - "name": 'test-domain' + "name": 'test-project', }, - "id": '1', - "name": 'test-project' - }, - "user": { - "domain": { + "user": { + "domain": {"id": '1', "name": 'test-domain'}, "id": '1', - "name": 'test-domain' + "name": 'test-user', }, - "id": '1', - "name": 'test-user' - }, - "issued_at": "2013-05-29T16:55:21.468960Z", - }, -}) + "issued_at": "2013-05-29T16:55:21.468960Z", + } + } +) CINDER_EXAMPLES = { "versions": [ @@ -137,23 +143,13 @@ "status": discover.Status.CURRENT, "updated": "2012-01-04T11:33:21Z", "id": "v1.0", - "links": [ - { - "href": "%sv1/" % BASE_URL, - "rel": "self" - } - ] + "links": [{"href": f"{BASE_URL}v1/", "rel": "self"}], }, { "status": discover.Status.CURRENT, "updated": "2012-11-21T11:33:21Z", "id": "v2.0", - "links": [ - { - "href": "%sv2/" % BASE_URL, - "rel": "self" - } - ] + "links": [{"href": f"{BASE_URL}v2/", "rel": "self"}], }, { "status": discover.Status.CURRENT, @@ -164,16 +160,10 @@ "next_min_version": "3.4", "not_before": "2019-12-31", "links": [ - { - "href": BASE_URL, - "rel": "collection" - }, - { - "href": "%sv3/" % BASE_URL, - "rel": "self" - } - ] - } + {"href": BASE_URL, "rel": "collection"}, + {"href": f"{BASE_URL}v3/", "rel": "self"}, + ], + }, ] } @@ -182,53 +172,28 @@ { "status": discover.Status.CURRENT, "id": "v2.2", - "links": [ - { - "href": "%sv2/" % BASE_URL, - "rel": "self" - } - ] + "links": [{"href": f"{BASE_URL}v2/", "rel": "self"}], }, { "status": discover.Status.SUPPORTED, "id": "v2.1", - "links": [ - { - "href": "%sv2/" % BASE_URL, - "rel": "self" - } - ] + "links": [{"href": f"{BASE_URL}v2/", "rel": "self"}], }, { "status": discover.Status.SUPPORTED, "id": "v2.0", - "links": [ - { - "href": "%sv2/" % BASE_URL, - "rel": "self" - } - ] + "links": [{"href": f"{BASE_URL}v2/", "rel": "self"}], }, { "status": discover.Status.CURRENT, "id": "v1.1", - "links": [ - { - "href": "%sv1/" % BASE_URL, - "rel": "self" - } - ] + "links": [{"href": f"{BASE_URL}v1/", "rel": "self"}], }, { "status": discover.Status.SUPPORTED, "id": "v1.0", - "links": [ - { - "href": "%sv1/" % BASE_URL, - "rel": "self" - } - ] - } + "links": [{"href": f"{BASE_URL}v1/", "rel": "self"}], + }, ] } @@ -249,7 +214,6 @@ def _create_single_version(version): class CatalogHackTests(utils.TestCase): - TEST_URL = 'http://keystone.server:5000/v2.0' OTHER_URL = 'http://other.server:5000/path' @@ -260,40 +224,43 @@ class CatalogHackTests(utils.TestCase): V3_URL = BASE_URL + 'v3' def setUp(self): - super(CatalogHackTests, self).setUp() + super().setUp() self.hacks = discover._VersionHacks() - self.hacks.add_discover_hack(self.IDENTITY, - re.compile('/v2.0/?$'), - '/') + self.hacks.add_discover_hack( + self.IDENTITY, re.compile('/v2.0/?$'), '/' + ) def test_version_hacks(self): - self.assertEqual(self.BASE_URL, - self.hacks.get_discover_hack(self.IDENTITY, - self.V2_URL)) + self.assertEqual( + self.BASE_URL, + self.hacks.get_discover_hack(self.IDENTITY, self.V2_URL), + ) - self.assertEqual(self.BASE_URL, - self.hacks.get_discover_hack(self.IDENTITY, - self.V2_URL + '/')) + self.assertEqual( + self.BASE_URL, + self.hacks.get_discover_hack(self.IDENTITY, self.V2_URL + '/'), + ) - self.assertEqual(self.OTHER_URL, - self.hacks.get_discover_hack(self.IDENTITY, - self.OTHER_URL)) + self.assertEqual( + self.OTHER_URL, + self.hacks.get_discover_hack(self.IDENTITY, self.OTHER_URL), + ) def test_ignored_non_service_type(self): - self.assertEqual(self.V2_URL, - self.hacks.get_discover_hack('other', self.V2_URL)) + self.assertEqual( + self.V2_URL, self.hacks.get_discover_hack('other', self.V2_URL) + ) class DiscoverUtils(utils.TestCase): - def test_version_number(self): def assertVersion(out, inp): self.assertEqual(out, discover.normalize_version_number(inp)) def versionRaises(inp): - self.assertRaises(TypeError, - discover.normalize_version_number, - inp) + self.assertRaises( + TypeError, discover.normalize_version_number, inp + ) assertVersion((1, 2), 'v1.2') assertVersion((11, 0), 'v11') @@ -324,53 +291,96 @@ def versionRaises(inp): def test_version_args(self): """Validate _normalize_version_args.""" + def assert_min_max(in_ver, in_min, in_max, in_type, out_min, out_max): self.assertEqual( (out_min, out_max), discover._normalize_version_args( - in_ver, in_min, in_max, service_type=in_type)) + in_ver, in_min, in_max, service_type=in_type + ), + ) def normalize_raises(ver, min, max, in_type): self.assertRaises( ValueError, discover._normalize_version_args, - ver, min, max, service_type=in_type) - - assert_min_max(None, None, None, None, - None, None) - assert_min_max(None, None, 'v1.2', None, - None, (1, 2)) - assert_min_max(None, 'v1.2', 'latest', None, - (1, 2), (discover.LATEST, discover.LATEST)) - assert_min_max(None, 'v1.2', '1.6', None, - (1, 2), (1, 6)) - assert_min_max(None, 'v1.2', '1.latest', None, - (1, 2), (1, discover.LATEST)) - assert_min_max(None, 'latest', 'latest', None, - (discover.LATEST, discover.LATEST), - (discover.LATEST, discover.LATEST)) - assert_min_max(None, 'latest', None, None, - (discover.LATEST, discover.LATEST), - (discover.LATEST, discover.LATEST)) - assert_min_max(None, (1, 2), None, None, - (1, 2), (discover.LATEST, discover.LATEST)) - assert_min_max('', ('1', '2'), (1, 6), None, - (1, 2), (1, 6)) - assert_min_max(None, ('1', '2'), (1, discover.LATEST), None, - (1, 2), (1, discover.LATEST)) - assert_min_max('v1.2', '', None, None, - (1, 2), (1, discover.LATEST)) - assert_min_max('1.latest', None, '', None, - (1, discover.LATEST), (1, discover.LATEST)) - assert_min_max('v1', None, None, None, - (1, 0), (1, discover.LATEST)) - assert_min_max('latest', None, None, None, - (discover.LATEST, discover.LATEST), - (discover.LATEST, discover.LATEST)) - assert_min_max(None, None, 'latest', 'volumev2', - (2, 0), (2, discover.LATEST)) - assert_min_max(None, None, None, 'volumev2', - (2, 0), (2, discover.LATEST)) + ver, + min, + max, + service_type=in_type, + ) + + assert_min_max(None, None, None, None, None, None) + assert_min_max(None, None, 'v1.2', None, None, (1, 2)) + assert_min_max( + None, + 'v1.2', + 'latest', + None, + (1, 2), + (discover.LATEST, discover.LATEST), + ) + assert_min_max(None, 'v1.2', '1.6', None, (1, 2), (1, 6)) + assert_min_max( + None, 'v1.2', '1.latest', None, (1, 2), (1, discover.LATEST) + ) + assert_min_max( + None, + 'latest', + 'latest', + None, + (discover.LATEST, discover.LATEST), + (discover.LATEST, discover.LATEST), + ) + assert_min_max( + None, + 'latest', + None, + None, + (discover.LATEST, discover.LATEST), + (discover.LATEST, discover.LATEST), + ) + assert_min_max( + None, + (1, 2), + None, + None, + (1, 2), + (discover.LATEST, discover.LATEST), + ) + assert_min_max('', ('1', '2'), (1, 6), None, (1, 2), (1, 6)) + assert_min_max( + None, + ('1', '2'), + (1, discover.LATEST), + None, + (1, 2), + (1, discover.LATEST), + ) + assert_min_max('v1.2', '', None, None, (1, 2), (1, discover.LATEST)) + assert_min_max( + '1.latest', + None, + '', + None, + (1, discover.LATEST), + (1, discover.LATEST), + ) + assert_min_max('v1', None, None, None, (1, 0), (1, discover.LATEST)) + assert_min_max( + 'latest', + None, + None, + None, + (discover.LATEST, discover.LATEST), + (discover.LATEST, discover.LATEST), + ) + assert_min_max( + None, None, 'latest', 'volumev2', (2, 0), (2, discover.LATEST) + ) + assert_min_max( + None, None, None, 'volumev2', (2, 0), (2, discover.LATEST) + ) normalize_raises('v1', 'v2', None, None) normalize_raises('v1', None, 'v2', None) @@ -388,8 +398,9 @@ def assert_string(out, inp): assert_string('latest', (discover.LATEST,)) assert_string('latest', (discover.LATEST, discover.LATEST)) - assert_string('latest', - (discover.LATEST, discover.LATEST, discover.LATEST)) + assert_string( + 'latest', (discover.LATEST, discover.LATEST, discover.LATEST) + ) assert_string('1', (1,)) assert_string('1.2', (1, 2)) assert_string('1.latest', (1, discover.LATEST)) @@ -402,8 +413,9 @@ def bad(minver, maxver, cand): self.assertFalse(discover.version_between(minver, maxver, cand)) def exc(excls, minver, maxver, cand): - self.assertRaises(excls, - discover.version_between, minver, maxver, cand) + self.assertRaises( + excls, discover.version_between, minver, maxver, cand + ) # candidate required exc(ValueError, (1, 0), (1, 0), None) @@ -447,11 +459,16 @@ def exc(excls, minver, maxver, cand): good(None, None, (999, 999)) good(None, None, 'latest') # Various good 'latest' scenarios - good((discover.LATEST, discover.LATEST), - (discover.LATEST, discover.LATEST), - (discover.LATEST, discover.LATEST)) - good((discover.LATEST, discover.LATEST), None, - (discover.LATEST, discover.LATEST)) + good( + (discover.LATEST, discover.LATEST), + (discover.LATEST, discover.LATEST), + (discover.LATEST, discover.LATEST), + ) + good( + (discover.LATEST, discover.LATEST), + None, + (discover.LATEST, discover.LATEST), + ) good('', 'latest', 'latest') good('2.latest', '3.latest', '3.0') good('2.latest', None, (55, 66)) @@ -459,18 +476,19 @@ def exc(excls, minver, maxver, cand): class VersionDataTests(utils.TestCase): - def setUp(self): - super(VersionDataTests, self).setUp() + super().setUp() self.session = session.Session() def test_version_data_basics(self): - examples = {'keystone': V3_VERSION_LIST, - 'cinder': CINDER_EXAMPLES, - 'glance': GLANCE_EXAMPLES} + examples = { + 'keystone': V3_VERSION_LIST, + 'cinder': CINDER_EXAMPLES, + 'glance': GLANCE_EXAMPLES, + } for path, data in examples.items(): - url = "%s%s" % (BASE_URL, path) + url = f"{BASE_URL}{path}" mock = self.requests_mock.get(url, status_code=300, json=data) @@ -480,24 +498,28 @@ def test_version_data_basics(self): for v in raw_data: for n in ('id', 'status', 'links'): - msg = '%s missing from %s version data' % (n, path) - self.assertThat(v, matchers.Annotate(msg, - matchers.Contains(n))) + msg = f'{n} missing from {path} version data' + self.assertThat( + v, matchers.Annotate(msg, matchers.Contains(n)) + ) for v in clean_data: for n in ('version', 'url', 'raw_status'): - msg = '%s missing from %s version data' % (n, path) - self.assertThat(v, matchers.Annotate(msg, - matchers.Contains(n))) + msg = f'{n} missing from {path} version data' + self.assertThat( + v, matchers.Annotate(msg, matchers.Contains(n)) + ) self.assertTrue(mock.called_once) def test_version_data_override_version_url(self): # if the request url is versioned already, just return it. self.requests_mock.get( - V3_URL, status_code=200, - json={'version': fixture.V3Discovery('http://override/identity/v3') - } + V3_URL, + status_code=200, + json={ + 'version': fixture.V3Discovery('http://override/identity/v3') + }, ) disc = discover.Discover(self.session, V3_URL) @@ -512,9 +534,11 @@ def test_version_data_override_version_url(self): # if the request url is not versioned, just add version info to it.( # do not changed the url's netloc or path) self.requests_mock.get( - BASE_URL, status_code=200, - json={'version': fixture.V3Discovery('http://override/identity/v3') - } + BASE_URL, + status_code=200, + json={ + 'version': fixture.V3Discovery('http://override/identity/v3') + }, ) disc = discover.Discover(self.session, BASE_URL) @@ -539,9 +563,9 @@ def test_version_data_unknown(self): self.assertEqual(discover.Status.UNKNOWN, clean_data[0]['status']) def test_version_data_individual(self): - mock = self.requests_mock.get(V3_URL, - status_code=200, - json=V3_VERSION_ENTRY) + mock = self.requests_mock.get( + V3_URL, status_code=200, json=V3_VERSION_ENTRY + ) disc = discover.Discover(self.session, V3_URL) raw_data = disc.raw_version_data() @@ -565,22 +589,19 @@ def test_version_data_legacy_ironic_no_override(self): """Validate detection of legacy Ironic microversion ranges.""" ironic_url = 'https://bare-metal.example.com/v1/' self.requests_mock.get( - ironic_url, status_code=200, - json={ - 'id': 'v1', - 'links': [{ - "href": ironic_url, - "rel": "self"}]}, + ironic_url, + status_code=200, + json={'id': 'v1', 'links': [{"href": ironic_url, "rel": "self"}]}, headers={ 'X-OpenStack-Ironic-API-Minimum-Version': '1.3', 'X-OpenStack-Ironic-API-Maximum-Version': '1.21', - }) + }, + ) plugin = noauth.NoAuth() a = adapter.Adapter( - self.session, - auth=plugin, - service_type='baremetal') + self.session, auth=plugin, service_type='baremetal' + ) self.assertIsNone(a.get_api_major_version()) @@ -588,27 +609,25 @@ def test_version_data_ironic_microversions(self): """Validate detection of Ironic microversion ranges.""" ironic_url = 'https://bare-metal.example.com/v1/' self.requests_mock.get( - ironic_url, status_code=200, + ironic_url, + status_code=200, json={ 'id': 'v1', 'version': { 'id': 'v1', - 'links': [{ - "href": ironic_url, - "rel": "self"}], + 'links': [{"href": ironic_url, "rel": "self"}], 'version': '1.40', 'min_version': '1.10', 'status': 'CURRENT', }, - 'links': [{ - "href": ironic_url, - "rel": "self"}], + 'links': [{"href": ironic_url, "rel": "self"}], }, # Keep headers so we can verify that body trumps headers headers={ 'X-OpenStack-Ironic-API-Minimum-Version': '1.3', 'X-OpenStack-Ironic-API-Maximum-Version': '1.21', - }) + }, + ) self.assertEqual( [ @@ -622,24 +641,23 @@ def test_version_data_ironic_microversions(self): 'max_microversion': (1, 40), 'next_min_version': None, 'not_before': None, - }, + } ], - discover.Discover(self.session, ironic_url).version_data()) + discover.Discover(self.session, ironic_url).version_data(), + ) def test_version_data_legacy_ironic_microversions(self): """Validate detection of legacy Ironic microversion ranges.""" ironic_url = 'https://bare-metal.example.com/v1/' self.requests_mock.get( - ironic_url, status_code=200, - json={ - 'id': 'v1', - 'links': [{ - "href": ironic_url, - "rel": "self"}]}, + ironic_url, + status_code=200, + json={'id': 'v1', 'links': [{"href": ironic_url, "rel": "self"}]}, headers={ 'X-OpenStack-Ironic-API-Minimum-Version': '1.3', 'X-OpenStack-Ironic-API-Maximum-Version': '1.21', - }) + }, + ) self.assertEqual( [ @@ -653,12 +671,14 @@ def test_version_data_legacy_ironic_microversions(self): 'max_microversion': (1, 21), 'next_min_version': None, 'not_before': None, - }, + } ], - discover.Discover(self.session, ironic_url).version_data()) + discover.Discover(self.session, ironic_url).version_data(), + ) def test_version_data_microversions(self): """Validate [min_|max_]version conversion to {min|max}_microversion.""" + def setup_mock(versions_in): # Set up the test data with the input version data jsondata = { @@ -667,19 +687,13 @@ def setup_mock(versions_in): { "status": discover.Status.CURRENT, "id": "v2.2", - "links": [ - { - "href": V3_URL, - "rel": "self" - } - ] + "links": [{"href": V3_URL, "rel": "self"}], }, - **versions_in + **versions_in, ) ] } - self.requests_mock.get( - V3_URL, status_code=200, json=jsondata) + self.requests_mock.get(V3_URL, status_code=200, json=jsondata) def test_ok(versions_in, versions_out): setup_mock(versions_in) @@ -694,45 +708,80 @@ def test_ok(versions_in, versions_out): 'status': discover.Status.CURRENT, 'raw_status': discover.Status.CURRENT, }, - **versions_out + **versions_out, ) ], - discover.Discover(self.session, V3_URL).version_data()) + discover.Discover(self.session, V3_URL).version_data(), + ) def test_exc(versions_in): setup_mock(versions_in) # Ensure TypeError is raised self.assertRaises( - TypeError, - discover.Discover(self.session, V3_URL).version_data) + TypeError, discover.Discover(self.session, V3_URL).version_data + ) # no version info in input - test_ok({}, - {'min_microversion': None, 'max_microversion': None, - 'next_min_version': None, 'not_before': None}) + test_ok( + {}, + { + 'min_microversion': None, + 'max_microversion': None, + 'next_min_version': None, + 'not_before': None, + }, + ) # version => max_microversion - test_ok({'version': '2.2'}, - {'min_microversion': None, 'max_microversion': (2, 2), - 'next_min_version': None, 'not_before': None}) + test_ok( + {'version': '2.2'}, + { + 'min_microversion': None, + 'max_microversion': (2, 2), + 'next_min_version': None, + 'not_before': None, + }, + ) # max_version supersedes version (even if malformed). min_version & # normalization. - test_ok({'min_version': '2', 'version': 'foo', 'max_version': '2.2'}, - {'min_microversion': (2, 0), 'max_microversion': (2, 2), - 'next_min_version': None, 'not_before': None}) + test_ok( + {'min_version': '2', 'version': 'foo', 'max_version': '2.2'}, + { + 'min_microversion': (2, 0), + 'max_microversion': (2, 2), + 'next_min_version': None, + 'not_before': None, + }, + ) # Edge case: min/max_version ignored if present but "empty"; version # used for max_microversion. - test_ok({'min_version': '', 'version': '2.1', 'max_version': ''}, - {'min_microversion': None, 'max_microversion': (2, 1), - 'next_min_version': None, 'not_before': None}) + test_ok( + {'min_version': '', 'version': '2.1', 'max_version': ''}, + { + 'min_microversion': None, + 'max_microversion': (2, 1), + 'next_min_version': None, + 'not_before': None, + }, + ) # next_min_version set - test_ok({'min_version': '2', 'max_version': '2.2', - 'next_min_version': '2.1', 'not_before': '2019-07-01'}, - {'min_microversion': (2, 0), 'max_microversion': (2, 2), - 'next_min_version': (2, 1), 'not_before': '2019-07-01'}) + test_ok( + { + 'min_version': '2', + 'max_version': '2.2', + 'next_min_version': '2.1', + 'not_before': '2019-07-01', + }, + { + 'min_microversion': (2, 0), + 'max_microversion': (2, 2), + 'next_min_version': (2, 1), + 'not_before': '2019-07-01', + }, + ) # Badly-formatted min_version test_exc({'min_version': 'foo', 'max_version': '2.1'}) @@ -748,9 +797,9 @@ def test_exc(versions_in): def test_endpoint_data_noauth_discover(self): mock = self.requests_mock.get( - BASE_URL, status_code=200, json=V3_VERSION_LIST) - self.requests_mock.get( - V3_URL, status_code=200, json=V3_VERSION_ENTRY) + BASE_URL, status_code=200, json=V3_VERSION_LIST + ) + self.requests_mock.get(V3_URL, status_code=200, json=V3_VERSION_ENTRY) plugin = noauth.NoAuth(endpoint=BASE_URL) data = plugin.get_endpoint_data(self.session) @@ -763,10 +812,8 @@ def test_endpoint_data_noauth_discover(self): self.assertTrue(mock.called_once) def test_endpoint_data_noauth_versioned_discover(self): - self.requests_mock.get( - BASE_URL, status_code=200, json=V3_VERSION_LIST) - self.requests_mock.get( - V3_URL, status_code=200, json=V3_VERSION_ENTRY) + self.requests_mock.get(BASE_URL, status_code=200, json=V3_VERSION_LIST) + self.requests_mock.get(V3_URL, status_code=200, json=V3_VERSION_ENTRY) plugin = noauth.NoAuth(endpoint=V3_URL) data = plugin.get_endpoint_data(self.session) @@ -778,8 +825,7 @@ def test_endpoint_data_noauth_versioned_discover(self): def test_endpoint_data_noauth_no_discover(self): plugin = noauth.NoAuth(endpoint=V3_URL) - data = plugin.get_endpoint_data( - self.session, discover_versions=False) + data = plugin.get_endpoint_data(self.session, discover_versions=False) self.assertEqual(data.api_version, (3, 0)) self.assertEqual(data.url, V3_URL) @@ -789,19 +835,18 @@ def test_endpoint_data_noauth_no_discover(self): def test_endpoint_data_noauth_override_no_discover(self): plugin = noauth.NoAuth() data = plugin.get_endpoint_data( - self.session, endpoint_override=V3_URL, discover_versions=False) + self.session, endpoint_override=V3_URL, discover_versions=False + ) self.assertEqual(data.api_version, (3, 0)) self.assertEqual(data.url, V3_URL) self.assertEqual( - plugin.get_endpoint(self.session, endpoint_override=V3_URL), - V3_URL) + plugin.get_endpoint(self.session, endpoint_override=V3_URL), V3_URL + ) def test_endpoint_data_http_basic_discover(self): - self.requests_mock.get( - BASE_URL, status_code=200, json=V3_VERSION_LIST) - self.requests_mock.get( - V3_URL, status_code=200, json=V3_VERSION_ENTRY) + self.requests_mock.get(BASE_URL, status_code=200, json=V3_VERSION_LIST) + self.requests_mock.get(V3_URL, status_code=200, json=V3_VERSION_ENTRY) plugin = http_basic.HTTPBasicAuth(endpoint=V3_URL) data = plugin.get_endpoint_data(self.session) @@ -813,8 +858,7 @@ def test_endpoint_data_http_basic_discover(self): def test_endpoint_data_http_basic_no_discover(self): plugin = http_basic.HTTPBasicAuth(endpoint=V3_URL) - data = plugin.get_endpoint_data( - self.session, discover_versions=False) + data = plugin.get_endpoint_data(self.session, discover_versions=False) self.assertEqual(data.api_version, (3, 0)) self.assertEqual(data.url, V3_URL) @@ -824,27 +868,28 @@ def test_endpoint_data_http_basic_no_discover(self): def test_endpoint_data_http_basic_override_no_discover(self): plugin = http_basic.HTTPBasicAuth() data = plugin.get_endpoint_data( - self.session, endpoint_override=V3_URL, discover_versions=False) + self.session, endpoint_override=V3_URL, discover_versions=False + ) self.assertEqual(data.api_version, (3, 0)) self.assertEqual(data.url, V3_URL) self.assertEqual( plugin.get_api_major_version( - self.session, endpoint_override=V3_URL), - (3, 0)) + self.session, endpoint_override=V3_URL + ), + (3, 0), + ) self.assertEqual( - plugin.get_endpoint(self.session, endpoint_override=V3_URL), - V3_URL) + plugin.get_endpoint(self.session, endpoint_override=V3_URL), V3_URL + ) def test_endpoint_data_noauth_adapter(self): - self.requests_mock.get( - BASE_URL, status_code=200, json=V3_VERSION_LIST) - self.requests_mock.get( - V3_URL, status_code=200, json=V3_VERSION_ENTRY) + self.requests_mock.get(BASE_URL, status_code=200, json=V3_VERSION_LIST) + self.requests_mock.get(V3_URL, status_code=200, json=V3_VERSION_ENTRY) client = adapter.Adapter( - session.Session(noauth.NoAuth()), - endpoint_override=BASE_URL) + session.Session(noauth.NoAuth()), endpoint_override=BASE_URL + ) data = client.get_endpoint_data() self.assertEqual(data.api_version, (3, 0)) @@ -854,11 +899,12 @@ def test_endpoint_data_noauth_adapter(self): def test_endpoint_data_noauth_versioned_adapter(self): mock = self.requests_mock.get( - V3_URL, status_code=200, json=V3_VERSION_ENTRY) + V3_URL, status_code=200, json=V3_VERSION_ENTRY + ) client = adapter.Adapter( - session.Session(noauth.NoAuth()), - endpoint_override=V3_URL) + session.Session(noauth.NoAuth()), endpoint_override=V3_URL + ) data = client.get_endpoint_data() self.assertEqual(data.api_version, (3, 0)) @@ -870,7 +916,8 @@ def test_endpoint_data_noauth_versioned_adapter(self): def test_endpoint_data_token_endpoint_discover(self): mock = self.requests_mock.get( - V3_URL, status_code=200, json=V3_VERSION_ENTRY) + V3_URL, status_code=200, json=V3_VERSION_ENTRY + ) plugin = token_endpoint.Token(endpoint=V3_URL, token='bogus') data = plugin.get_endpoint_data(self.session) @@ -892,7 +939,8 @@ def test_endpoint_data_token_endpoint_no_discover(self): def test_endpoint_data_token_endpoint_adapter(self): mock = self.requests_mock.get( - V3_URL, status_code=200, json=V3_VERSION_ENTRY) + V3_URL, status_code=200, json=V3_VERSION_ENTRY + ) plugin = token_endpoint.Token(endpoint=V3_URL, token='bogus') client = adapter.Adapter(session.Session(plugin)) @@ -906,9 +954,9 @@ def test_endpoint_data_token_endpoint_adapter(self): self.assertTrue(mock.called_once) def test_data_for_url(self): - mock = self.requests_mock.get(V3_URL, - status_code=200, - json=V3_VERSION_ENTRY) + mock = self.requests_mock.get( + V3_URL, status_code=200, json=V3_VERSION_ENTRY + ) disc = discover.Discover(self.session, V3_URL) for url in (V3_URL, V3_URL + '/'): @@ -920,9 +968,9 @@ def test_data_for_url(self): self.assertTrue(mock.called_once) def test_data_for_no_version(self): - mock = self.requests_mock.get(V3_URL, - status_code=200, - json=V3_VERSION_ENTRY) + mock = self.requests_mock.get( + V3_URL, status_code=200, json=V3_VERSION_ENTRY + ) disc = discover.Discover(self.session, V3_URL) @@ -935,9 +983,9 @@ def test_data_for_no_version(self): self.assertTrue(mock.called_once) def test_keystone_version_data(self): - mock = self.requests_mock.get(BASE_URL, - status_code=300, - json=V3_VERSION_LIST) + mock = self.requests_mock.get( + BASE_URL, status_code=300, json=V3_VERSION_LIST + ) disc = discover.Discover(self.session, BASE_URL) raw_data = disc.raw_version_data() @@ -962,17 +1010,21 @@ def test_keystone_version_data(self): disc.data_for('v3.0'), disc.data_for('3.latest'), disc.data_for('latest'), - disc.versioned_data_for(min_version='v3.0', - max_version='v3.latest'), + disc.versioned_data_for( + min_version='v3.0', max_version='v3.latest' + ), disc.versioned_data_for(min_version='3'), disc.versioned_data_for(min_version='3.latest'), disc.versioned_data_for(min_version='latest'), - disc.versioned_data_for(min_version='3.latest', - max_version='latest'), - disc.versioned_data_for(min_version='latest', - max_version='latest'), + disc.versioned_data_for( + min_version='3.latest', max_version='latest' + ), + disc.versioned_data_for( + min_version='latest', max_version='latest' + ), disc.versioned_data_for(min_version=2), - disc.versioned_data_for(min_version='2.latest')) + disc.versioned_data_for(min_version='2.latest'), + ) for version in valid_v3_versions: self.assertEqual((3, 0), version['version']) self.assertEqual('stable', version['raw_status']) @@ -981,31 +1033,39 @@ def test_keystone_version_data(self): valid_v2_versions = ( disc.data_for(2), disc.data_for('2.latest'), - disc.versioned_data_for(min_version=2, - max_version=(2, discover.LATEST)), - disc.versioned_data_for(min_version='2.latest', - max_version='2.latest')) + disc.versioned_data_for( + min_version=2, max_version=(2, discover.LATEST) + ), + disc.versioned_data_for( + min_version='2.latest', max_version='2.latest' + ), + ) for version in valid_v2_versions: self.assertEqual((2, 0), version['version']) self.assertEqual('stable', version['raw_status']) self.assertEqual(V2_URL, version['url']) self.assertIsNone(disc.url_for('v4')) - self.assertIsNone(disc.versioned_url_for( - min_version='v4', max_version='v4.latest')) + self.assertIsNone( + disc.versioned_url_for(min_version='v4', max_version='v4.latest') + ) self.assertEqual(V3_URL, disc.url_for('v3')) - self.assertEqual(V3_URL, disc.versioned_url_for( - min_version='v3', max_version='v3.latest')) + self.assertEqual( + V3_URL, + disc.versioned_url_for(min_version='v3', max_version='v3.latest'), + ) self.assertEqual(V2_URL, disc.url_for('v2')) - self.assertEqual(V2_URL, disc.versioned_url_for( - min_version='v2', max_version='v2.latest')) + self.assertEqual( + V2_URL, + disc.versioned_url_for(min_version='v2', max_version='v2.latest'), + ) self.assertTrue(mock.called_once) def test_cinder_version_data(self): - mock = self.requests_mock.get(BASE_URL, - status_code=300, - json=CINDER_EXAMPLES) + mock = self.requests_mock.get( + BASE_URL, status_code=300, json=CINDER_EXAMPLES + ) disc = discover.Discover(self.session, BASE_URL) raw_data = disc.raw_version_data() @@ -1024,80 +1084,95 @@ def test_cinder_version_data(self): else: self.fail("Invalid version found") - v1_url = "%sv1/" % BASE_URL - v2_url = "%sv2/" % BASE_URL - v3_url = "%sv3/" % BASE_URL + v1_url = f"{BASE_URL}v1/" + v2_url = f"{BASE_URL}v2/" + v3_url = f"{BASE_URL}v3/" - self.assertEqual(clean_data, [ - { - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'version': (1, 0), - 'url': v1_url, - 'status': discover.Status.CURRENT, - 'raw_status': discover.Status.CURRENT, - }, - { - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'version': (2, 0), - 'url': v2_url, - 'status': discover.Status.CURRENT, - 'raw_status': discover.Status.CURRENT, - }, - { - 'collection': BASE_URL, - 'max_microversion': (3, 27), - 'min_microversion': (3, 0), - 'next_min_version': (3, 4), - 'not_before': u'2019-12-31', - 'version': (3, 0), - 'url': v3_url, - 'status': discover.Status.CURRENT, - 'raw_status': discover.Status.CURRENT, - }, - ]) + self.assertEqual( + clean_data, + [ + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'version': (1, 0), + 'url': v1_url, + 'status': discover.Status.CURRENT, + 'raw_status': discover.Status.CURRENT, + }, + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'version': (2, 0), + 'url': v2_url, + 'status': discover.Status.CURRENT, + 'raw_status': discover.Status.CURRENT, + }, + { + 'collection': BASE_URL, + 'max_microversion': (3, 27), + 'min_microversion': (3, 0), + 'next_min_version': (3, 4), + 'not_before': '2019-12-31', + 'version': (3, 0), + 'url': v3_url, + 'status': discover.Status.CURRENT, + 'raw_status': discover.Status.CURRENT, + }, + ], + ) - for version in (disc.data_for('v2.0'), - disc.versioned_data_for(min_version='v2.0', - max_version='v2.latest')): + for version in ( + disc.data_for('v2.0'), + disc.versioned_data_for( + min_version='v2.0', max_version='v2.latest' + ), + ): self.assertEqual((2, 0), version['version']) self.assertEqual(discover.Status.CURRENT, version['raw_status']) self.assertEqual(v2_url, version['url']) - for version in (disc.data_for(1), - disc.versioned_data_for( - min_version=(1,), - max_version=(1, discover.LATEST))): + for version in ( + disc.data_for(1), + disc.versioned_data_for( + min_version=(1,), max_version=(1, discover.LATEST) + ), + ): self.assertEqual((1, 0), version['version']) self.assertEqual(discover.Status.CURRENT, version['raw_status']) self.assertEqual(v1_url, version['url']) self.assertIsNone(disc.url_for('v4')) - self.assertIsNone(disc.versioned_url_for(min_version='v4', - max_version='v4.latest')) + self.assertIsNone( + disc.versioned_url_for(min_version='v4', max_version='v4.latest') + ) self.assertEqual(v3_url, disc.url_for('v3')) - self.assertEqual(v3_url, disc.versioned_url_for( - min_version='v3', max_version='v3.latest')) + self.assertEqual( + v3_url, + disc.versioned_url_for(min_version='v3', max_version='v3.latest'), + ) self.assertEqual(v2_url, disc.url_for('v2')) - self.assertEqual(v2_url, disc.versioned_url_for( - min_version='v2', max_version='v2.latest')) + self.assertEqual( + v2_url, + disc.versioned_url_for(min_version='v2', max_version='v2.latest'), + ) self.assertEqual(v1_url, disc.url_for('v1')) - self.assertEqual(v1_url, disc.versioned_url_for( - min_version='v1', max_version='v1.latest')) + self.assertEqual( + v1_url, + disc.versioned_url_for(min_version='v1', max_version='v1.latest'), + ) self.assertTrue(mock.called_once) def test_glance_version_data(self): - mock = self.requests_mock.get(BASE_URL, - status_code=200, - json=GLANCE_EXAMPLES) + mock = self.requests_mock.get( + BASE_URL, status_code=200, json=GLANCE_EXAMPLES + ) disc = discover.Discover(self.session, BASE_URL) raw_data = disc.raw_version_data() @@ -1113,72 +1188,77 @@ def test_glance_version_data(self): else: self.fail("Invalid version found") - v1_url = '%sv1/' % BASE_URL - v2_url = '%sv2/' % BASE_URL + v1_url = f'{BASE_URL}v1/' + v2_url = f'{BASE_URL}v2/' - self.assertEqual(clean_data, [ - { - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'version': (1, 0), - 'url': v1_url, - 'status': discover.Status.SUPPORTED, - 'raw_status': discover.Status.SUPPORTED, - }, - { - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'version': (1, 1), - 'url': v1_url, - 'status': discover.Status.CURRENT, - 'raw_status': discover.Status.CURRENT, - }, - { - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'version': (2, 0), - 'url': v2_url, - 'status': discover.Status.SUPPORTED, - 'raw_status': discover.Status.SUPPORTED, - }, - { - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'version': (2, 1), - 'url': v2_url, - 'status': discover.Status.SUPPORTED, - 'raw_status': discover.Status.SUPPORTED, - }, - { - 'collection': None, - 'max_microversion': None, - 'min_microversion': None, - 'next_min_version': None, - 'not_before': None, - 'version': (2, 2), - 'url': v2_url, - 'status': discover.Status.CURRENT, - 'raw_status': discover.Status.CURRENT, - }, - ]) + self.assertEqual( + clean_data, + [ + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'version': (1, 0), + 'url': v1_url, + 'status': discover.Status.SUPPORTED, + 'raw_status': discover.Status.SUPPORTED, + }, + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'version': (1, 1), + 'url': v1_url, + 'status': discover.Status.CURRENT, + 'raw_status': discover.Status.CURRENT, + }, + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'version': (2, 0), + 'url': v2_url, + 'status': discover.Status.SUPPORTED, + 'raw_status': discover.Status.SUPPORTED, + }, + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'version': (2, 1), + 'url': v2_url, + 'status': discover.Status.SUPPORTED, + 'raw_status': discover.Status.SUPPORTED, + }, + { + 'collection': None, + 'max_microversion': None, + 'min_microversion': None, + 'next_min_version': None, + 'not_before': None, + 'version': (2, 2), + 'url': v2_url, + 'status': discover.Status.CURRENT, + 'raw_status': discover.Status.CURRENT, + }, + ], + ) for ver in (2, 2.1, 2.2): - for version in (disc.data_for(ver), - disc.versioned_data_for( - min_version=ver, - max_version=(2, discover.LATEST))): + for version in ( + disc.data_for(ver), + disc.versioned_data_for( + min_version=ver, max_version=(2, discover.LATEST) + ), + ): self.assertEqual((2, 2), version['version']) self.assertEqual( discover.Status.CURRENT, version['raw_status'] @@ -1187,10 +1267,12 @@ def test_glance_version_data(self): self.assertEqual(v2_url, disc.url_for(ver)) for ver in (1, 1.1): - for version in (disc.data_for(ver), - disc.versioned_data_for( - min_version=ver, - max_version=(1, discover.LATEST))): + for version in ( + disc.data_for(ver), + disc.versioned_data_for( + min_version=ver, max_version=(1, discover.LATEST) + ), + ): self.assertEqual((1, 1), version['version']) self.assertEqual( discover.Status.CURRENT, version['raw_status'] @@ -1199,21 +1281,27 @@ def test_glance_version_data(self): self.assertEqual(v1_url, disc.url_for(ver)) self.assertIsNone(disc.url_for('v3')) - self.assertIsNone(disc.versioned_url_for(min_version='v3', - max_version='v3.latest')) + self.assertIsNone( + disc.versioned_url_for(min_version='v3', max_version='v3.latest') + ) self.assertIsNone(disc.url_for('v2.3')) - self.assertIsNone(disc.versioned_url_for(min_version='v2.3', - max_version='v2.latest')) + self.assertIsNone( + disc.versioned_url_for(min_version='v2.3', max_version='v2.latest') + ) self.assertTrue(mock.called_once) def test_allow_deprecated(self): status = 'deprecated' - version_list = [{'id': 'v3.0', - 'links': [{'href': V3_URL, 'rel': 'self'}], - 'media-types': V3_MEDIA_TYPES, - 'status': status, - 'updated': UPDATED}] + version_list = [ + { + 'id': 'v3.0', + 'links': [{'href': V3_URL, 'rel': 'self'}], + 'media-types': V3_MEDIA_TYPES, + 'status': status, + 'updated': UPDATED, + } + ] self.requests_mock.get(BASE_URL, json={'versions': version_list}) disc = discover.Discover(self.session, BASE_URL) @@ -1230,11 +1318,15 @@ def test_allow_deprecated(self): def test_allow_experimental(self): status = 'experimental' - version_list = [{'id': 'v3.0', - 'links': [{'href': V3_URL, 'rel': 'self'}], - 'media-types': V3_MEDIA_TYPES, - 'status': status, - 'updated': UPDATED}] + version_list = [ + { + 'id': 'v3.0', + 'links': [{'href': V3_URL, 'rel': 'self'}], + 'media-types': V3_MEDIA_TYPES, + 'status': status, + 'updated': UPDATED, + } + ] self.requests_mock.get(BASE_URL, json={'versions': version_list}) disc = discover.Discover(self.session, BASE_URL) @@ -1250,9 +1342,9 @@ def test_allow_experimental(self): def test_allow_unknown(self): status = 'abcdef' - version_list = fixture.DiscoveryList(BASE_URL, - v2=False, - v3_status=status) + version_list = fixture.DiscoveryList( + BASE_URL, v2=False, v3_status=status + ) self.requests_mock.get(BASE_URL, json=version_list) disc = discover.Discover(self.session, BASE_URL) @@ -1267,20 +1359,27 @@ def test_allow_unknown(self): self.assertEqual((3, 0), versions[0]['version']) def test_ignoring_invalid_links(self): - version_list = [{'id': 'v3.0', - 'links': [{'href': V3_URL, 'rel': 'self'}], - 'media-types': V3_MEDIA_TYPES, - 'status': 'stable', - 'updated': UPDATED}, - {'id': 'v3.1', - 'media-types': V3_MEDIA_TYPES, - 'status': 'stable', - 'updated': UPDATED}, - {'media-types': V3_MEDIA_TYPES, - 'status': 'stable', - 'updated': UPDATED, - 'links': [{'href': V3_URL, 'rel': 'self'}], - }] + version_list = [ + { + 'id': 'v3.0', + 'links': [{'href': V3_URL, 'rel': 'self'}], + 'media-types': V3_MEDIA_TYPES, + 'status': 'stable', + 'updated': UPDATED, + }, + { + 'id': 'v3.1', + 'media-types': V3_MEDIA_TYPES, + 'status': 'stable', + 'updated': UPDATED, + }, + { + 'media-types': V3_MEDIA_TYPES, + 'status': 'stable', + 'updated': UPDATED, + 'links': [{'href': V3_URL, 'rel': 'self'}], + }, + ] self.requests_mock.get(BASE_URL, json={'versions': version_list}) @@ -1297,12 +1396,13 @@ def test_ignoring_invalid_links(self): class EndpointDataTests(utils.TestCase): def setUp(self): - super(EndpointDataTests, self).setUp() + super().setUp() self.session = session.Session() @mock.patch('keystoneauth1.discover.get_discovery') - @mock.patch('keystoneauth1.discover.EndpointData.' - '_get_discovery_url_choices') + @mock.patch( + 'keystoneauth1.discover.EndpointData._get_discovery_url_choices' + ) def test_run_discovery_cache(self, mock_url_choices, mock_get_disc): # get_discovery raises so we keep looping mock_get_disc.side_effect = exceptions.DiscoveryFailure() @@ -1310,19 +1410,29 @@ def test_run_discovery_cache(self, mock_url_choices, mock_get_disc): mock_url_choices.return_value = ('url1', 'url2', 'url1', 'url3') epd = discover.EndpointData() epd._run_discovery( - session='sess', cache='cache', min_version='min', - max_version='max', project_id='projid', - allow_version_hack='allow_hack', discover_versions='disc_vers') + session='sess', + cache='cache', + min_version='min', + max_version='max', + project_id='projid', + allow_version_hack='allow_hack', + discover_versions='disc_vers', + ) # Only one call with 'url1' self.assertEqual(3, mock_get_disc.call_count) mock_get_disc.assert_has_calls( - [mock.call('sess', url, cache='cache', authenticated=False) - for url in ('url1', 'url2', 'url3')]) + [ + mock.call('sess', url, cache='cache', authenticated=False) + for url in ('url1', 'url2', 'url3') + ] + ) def test_run_discovery_auth(self): url = 'https://example.com' - headers = {'Accept': 'application/json', - 'OpenStack-API-Version': 'version header test'} + headers = { + 'Accept': 'application/json', + 'OpenStack-API-Version': 'version header test', + } session = mock.Mock() session.get.side_effect = [ @@ -1334,32 +1444,37 @@ def test_run_discovery_auth(self): try: discover.get_version_data( - session, url, version_header='version header test') + session, url, version_header='version header test' + ) except exceptions.BadRequest: pass # Only one call with 'url' self.assertEqual(2, session.get.call_count) - session.get.assert_has_calls([ - mock.call(url, headers=headers, authenticated=None), - mock.call(url, headers=headers, authenticated=True), - ]) + session.get.assert_has_calls( + [ + mock.call(url, headers=headers, authenticated=None), + mock.call(url, headers=headers, authenticated=True), + ] + ) def test_endpoint_data_str(self): """Validate EndpointData.__str__.""" # Populate a few fields to make sure they come through. - epd = discover.EndpointData(catalog_url='abc', service_type='123', - api_version=(2, 3)) + epd = discover.EndpointData( + catalog_url='abc', service_type='123', api_version=(2, 3) + ) exp = ( 'EndpointData{api_version=(2, 3), catalog_url=abc,' ' endpoint_id=None, interface=None, major_version=None,' ' max_microversion=None, min_microversion=None,' ' next_min_version=None, not_before=None, raw_endpoint=None,' ' region_name=None, service_id=None, service_name=None,' - ' service_type=123, service_url=None, url=abc}') + ' service_type=123, service_url=None, url=abc}' + ) # Works with str() self.assertEqual(exp, str(epd)) # Works with implicit stringification - self.assertEqual(exp, "%s" % epd) + self.assertEqual(exp, f"{epd}") def test_project_id_int_fallback(self): bad_url = "https://compute.example.com/v2/123456" @@ -1372,5 +1487,6 @@ def test_url_version_match_project_id_int(self): discovery_doc = _create_single_version(discovery_fixture) self.requests_mock.get(V3_URL, status_code=200, json=discovery_doc) epd = discover.EndpointData(catalog_url=V3_URL).get_versioned_data( - session=self.session, project_id='3') + session=self.session, project_id='3' + ) self.assertEqual(epd.catalog_url, epd.url) diff --git a/keystoneauth1/tests/unit/test_fair_sempahore.py b/keystoneauth1/tests/unit/test_fair_sempahore.py index 6804da5a..a6d13bae 100644 --- a/keystoneauth1/tests/unit/test_fair_sempahore.py +++ b/keystoneauth1/tests/unit/test_fair_sempahore.py @@ -21,7 +21,6 @@ class SemaphoreTests(testtools.TestCase): - def _thread_worker(self): while True: # get returns the Item, but we don't care about the value so we @@ -48,7 +47,7 @@ def _concurrency_core(self, concurrency, delay): self.q.join() def setUp(self): - super(SemaphoreTests, self).setUp() + super().setUp() self.mock_payload = mock.Mock() # We should be waiting at least 0.1s between operations, so diff --git a/keystoneauth1/tests/unit/test_fixtures.py b/keystoneauth1/tests/unit/test_fixtures.py index c7ee636e..e01e5128 100644 --- a/keystoneauth1/tests/unit/test_fixtures.py +++ b/keystoneauth1/tests/unit/test_fixtures.py @@ -17,15 +17,14 @@ class V2TokenTests(utils.TestCase): - def test_unscoped(self): token_id = uuid.uuid4().hex user_id = uuid.uuid4().hex user_name = uuid.uuid4().hex - token = fixture.V2Token(token_id=token_id, - user_id=user_id, - user_name=user_name) + token = fixture.V2Token( + token_id=token_id, user_id=user_id, user_name=user_name + ) self.assertEqual(token_id, token.token_id) self.assertEqual(token_id, token['access']['token']['id']) @@ -39,8 +38,7 @@ def test_tenant_scoped(self): tenant_id = uuid.uuid4().hex tenant_name = uuid.uuid4().hex - token = fixture.V2Token(tenant_id=tenant_id, - tenant_name=tenant_name) + token = fixture.V2Token(tenant_id=tenant_id, tenant_name=tenant_name) self.assertEqual(tenant_id, token.tenant_id) self.assertEqual(tenant_id, token['access']['token']['tenant']['id']) @@ -53,8 +51,9 @@ def test_trust_scoped(self): trust_id = uuid.uuid4().hex trustee_user_id = uuid.uuid4().hex - token = fixture.V2Token(trust_id=trust_id, - trustee_user_id=trustee_user_id) + token = fixture.V2Token( + trust_id=trust_id, trustee_user_id=trustee_user_id + ) trust = token['access']['trust'] self.assertEqual(trust_id, token.trust_id) @@ -75,7 +74,7 @@ def test_roles(self): role_names = token['access']['user']['roles'] role_ids = token['access']['metadata']['roles'] - self.assertEqual(set([role_id1, role_id2]), set(role_ids)) + self.assertEqual({role_id1, role_id2}, set(role_ids)) for r in (role_name1, role_name2): self.assertIn({'name': r}, role_names) @@ -92,11 +91,13 @@ def test_services(self): token = fixture.V2Token() svc = token.add_service(type=service_type, name=service_name) - svc.add_endpoint(public=public, - admin=admin, - internal=internal, - region=region, - id=endpoint_id) + svc.add_endpoint( + public=public, + admin=admin, + internal=internal, + region=region, + id=endpoint_id, + ) self.assertEqual(1, len(token['access']['serviceCatalog'])) service = token['access']['serviceCatalog'][0]['endpoints'][0] @@ -120,22 +121,24 @@ def test_token_bind(self): token.set_bind(name1, data1) token.set_bind(name2, data2) - self.assertEqual({name1: data1, name2: data2}, - token['access']['token']['bind']) + self.assertEqual( + {name1: data1, name2: data2}, token['access']['token']['bind'] + ) class V3TokenTests(utils.TestCase): - def test_unscoped(self): user_id = uuid.uuid4().hex user_name = uuid.uuid4().hex user_domain_id = uuid.uuid4().hex user_domain_name = uuid.uuid4().hex - token = fixture.V3Token(user_id=user_id, - user_name=user_name, - user_domain_id=user_domain_id, - user_domain_name=user_domain_name) + token = fixture.V3Token( + user_id=user_id, + user_name=user_name, + user_domain_id=user_domain_id, + user_domain_name=user_domain_name, + ) self.assertEqual(user_id, token.user_id) self.assertEqual(user_id, token['token']['user']['id']) @@ -155,10 +158,12 @@ def test_project_scoped(self): project_domain_id = uuid.uuid4().hex project_domain_name = uuid.uuid4().hex - token = fixture.V3Token(project_id=project_id, - project_name=project_name, - project_domain_id=project_domain_id, - project_domain_name=project_domain_name) + token = fixture.V3Token( + project_id=project_id, + project_name=project_name, + project_domain_id=project_domain_id, + project_domain_name=project_domain_name, + ) self.assertEqual(project_id, token.project_id) self.assertEqual(project_id, token['token']['project']['id']) @@ -181,11 +186,13 @@ def test_project_as_domain_scoped(self): project_domain_name = uuid.uuid4().hex project_is_domain = True - token = fixture.V3Token(project_id=project_id, - project_name=project_name, - project_domain_id=project_domain_id, - project_domain_name=project_domain_name, - project_is_domain=project_is_domain) + token = fixture.V3Token( + project_id=project_id, + project_name=project_name, + project_domain_id=project_domain_id, + project_domain_name=project_domain_name, + project_is_domain=project_is_domain, + ) self.assertEqual(project_id, token.project_id) self.assertEqual(project_id, token['token']['project']['id']) @@ -204,8 +211,7 @@ def test_domain_scoped(self): domain_id = uuid.uuid4().hex domain_name = uuid.uuid4().hex - token = fixture.V3Token(domain_id=domain_id, - domain_name=domain_name) + token = fixture.V3Token(domain_id=domain_id, domain_name=domain_name) self.assertEqual(domain_id, token.domain_id) self.assertEqual(domain_id, token['token']['domain']['id']) @@ -231,10 +237,12 @@ def test_trust_scoped(self): trustor_user_id = uuid.uuid4().hex impersonation = True - token = fixture.V3Token(trust_id=trust_id, - trustee_user_id=trustee_user_id, - trustor_user_id=trustor_user_id, - trust_impersonation=impersonation) + token = fixture.V3Token( + trust_id=trust_id, + trustee_user_id=trustee_user_id, + trustor_user_id=trustor_user_id, + trust_impersonation=impersonation, + ) trust = token['token']['OS-TRUST:trust'] self.assertEqual(trust_id, token.trust_id) @@ -250,8 +258,9 @@ def test_oauth_scoped(self): access_id = uuid.uuid4().hex consumer_id = uuid.uuid4().hex - token = fixture.V3Token(oauth_access_token_id=access_id, - oauth_consumer_id=consumer_id) + token = fixture.V3Token( + oauth_access_token_id=access_id, oauth_consumer_id=consumer_id + ) oauth = token['token']['OS-OAUTH1'] @@ -265,14 +274,16 @@ def test_catalog(self): service_name = uuid.uuid4().hex service_id = uuid.uuid4().hex region = uuid.uuid4().hex - endpoints = {'public': uuid.uuid4().hex, - 'internal': uuid.uuid4().hex, - 'admin': uuid.uuid4().hex} + endpoints = { + 'public': uuid.uuid4().hex, + 'internal': uuid.uuid4().hex, + 'admin': uuid.uuid4().hex, + } token = fixture.V3Token() - svc = token.add_service(type=service_type, - name=service_name, - id=service_id) + svc = token.add_service( + type=service_type, name=service_name, id=service_id + ) svc.add_standard_endpoints(region=region, **endpoints) self.assertEqual(1, len(token['token']['catalog'])) @@ -289,8 +300,12 @@ def test_catalog(self): self.assertTrue(endpoint.pop('id')) for interface, url in endpoints.items(): - endpoint = {'interface': interface, 'url': url, - 'region': region, 'region_id': region} + endpoint = { + 'interface': interface, + 'url': url, + 'region': region, + 'region_id': region, + } self.assertIn(endpoint, service['endpoints']) token.remove_service(type=service_type) @@ -305,17 +320,17 @@ def new_sp(): return { 'id': uuid.uuid4().hex, 'sp_url': uuid.uuid4().hex, - 'auth_url': uuid.uuid4().hex + 'auth_url': uuid.uuid4().hex, } + ref_service_providers = [new_sp(), new_sp()] token = fixture.V3Token() for sp in ref_service_providers: - token.add_service_provider(sp['id'], - sp['auth_url'], - sp['sp_url']) + token.add_service_provider(sp['id'], sp['auth_url'], sp['sp_url']) self.assertEqual(ref_service_providers, token.service_providers) - self.assertEqual(ref_service_providers, - token['token']['service_providers']) + self.assertEqual( + ref_service_providers, token['token']['service_providers'] + ) def test_token_bind(self): name1 = uuid.uuid4().hex @@ -327,8 +342,7 @@ def test_token_bind(self): token.set_bind(name1, data1) token.set_bind(name2, data2) - self.assertEqual({name1: data1, name2: data2}, - token['token']['bind']) + self.assertEqual({name1: data1, name2: data2}, token['token']['bind']) def test_is_admin_project(self): token = fixture.V3Token() @@ -351,12 +365,9 @@ def test_oauth2(self): methods = ['oauth2_credential'] oauth2_thumbprint = uuid.uuid4().hex token = fixture.V3Token( - methods=methods, - oauth2_thumbprint=oauth2_thumbprint, + methods=methods, oauth2_thumbprint=oauth2_thumbprint ) - oauth2_credential = { - 'x5t#S256': oauth2_thumbprint, - } + oauth2_credential = {'x5t#S256': oauth2_thumbprint} self.assertEqual(methods, token.methods) self.assertEqual(oauth2_credential, token.oauth2_credential) self.assertEqual(oauth2_thumbprint, token.oauth2_thumbprint) diff --git a/keystoneauth1/tests/unit/test_hacking_checks.py b/keystoneauth1/tests/unit/test_hacking_checks.py index 751ac29c..a10ce69f 100644 --- a/keystoneauth1/tests/unit/test_hacking_checks.py +++ b/keystoneauth1/tests/unit/test_hacking_checks.py @@ -21,11 +21,12 @@ class TestCheckOsloNamespaceImports(testtools.TestCase): - # We are patching pycodestyle so that only the check under test is actually # installed. - @mock.patch('pycodestyle._checks', - {'physical_line': {}, 'logical_line': {}, 'tree': {}}) + @mock.patch( + 'pycodestyle._checks', + {'physical_line': {}, 'logical_line': {}, 'tree': {}}, + ) def run_check(self, code): pycodestyle.register_check(checks.check_oslo_namespace_imports) diff --git a/keystoneauth1/tests/unit/test_http_basic.py b/keystoneauth1/tests/unit/test_http_basic.py index 5bf3169e..0b12a723 100644 --- a/keystoneauth1/tests/unit/test_http_basic.py +++ b/keystoneauth1/tests/unit/test_http_basic.py @@ -17,7 +17,6 @@ class HTTPBasicAuthTest(utils.TestCase): - TEST_URL = 'http://server/prefix' def test_basic_case(self): @@ -30,13 +29,15 @@ def test_basic_case(self): self.assertEqual(data.text, 'body') self.assertRequestHeaderEqual( - 'Authorization', 'Basic bXlOYW1lOm15UGFzc3dvcmQ=') + 'Authorization', 'Basic bXlOYW1lOm15UGFzc3dvcmQ=' + ) self.assertIsNone(a.get_endpoint(s)) def test_basic_options(self): opts = loader.HTTPBasicAuth().get_options() - self.assertEqual(['username', 'password', 'endpoint'], - [o.name for o in opts]) + self.assertEqual( + ['username', 'password', 'endpoint'], [o.name for o in opts] + ) def test_get_endpoint(self): a = http_basic.HTTPBasicAuth(endpoint=self.TEST_URL) diff --git a/keystoneauth1/tests/unit/test_matchers.py b/keystoneauth1/tests/unit/test_matchers.py index 4e704b65..6159475c 100644 --- a/keystoneauth1/tests/unit/test_matchers.py +++ b/keystoneauth1/tests/unit/test_matchers.py @@ -55,9 +55,9 @@ class TestXMLEquals(testtools.TestCase): matches_matches = [matches_xml, equivalent_xml] matches_mismatches = [mismatches_xml] describe_examples = [ - (mismatches_description, mismatches_xml, matches_matcher), + (mismatches_description, mismatches_xml, matches_matcher) ] - str_examples = [('XMLEquals(%r)' % matches_xml, matches_matcher)] + str_examples = [(f'XMLEquals({matches_xml!r})', matches_matcher)] def test_matches_match(self): matcher = self.matches_matcher diff --git a/keystoneauth1/tests/unit/test_noauth.py b/keystoneauth1/tests/unit/test_noauth.py index 08e4a51a..dfe7037e 100644 --- a/keystoneauth1/tests/unit/test_noauth.py +++ b/keystoneauth1/tests/unit/test_noauth.py @@ -17,7 +17,6 @@ class NoAuthTest(utils.TestCase): - NOAUTH_TOKEN = 'notused' TEST_URL = 'http://server/prefix' diff --git a/keystoneauth1/tests/unit/test_service_token.py b/keystoneauth1/tests/unit/test_service_token.py index 1fe20562..f202cd0f 100644 --- a/keystoneauth1/tests/unit/test_service_token.py +++ b/keystoneauth1/tests/unit/test_service_token.py @@ -20,53 +20,60 @@ class ServiceTokenTests(utils.TestCase): - TEST_URL = 'http://test.example.com/path/' USER_URL = 'http://user-keystone.example.com/v3' SERVICE_URL = 'http://service-keystone.example.com/v3' def setUp(self): - super(ServiceTokenTests, self).setUp() + super().setUp() self.user_token_id = uuid.uuid4().hex self.user_token = fixture.V3Token() self.user_token.set_project_scope() - self.user_auth = identity.V3Password(auth_url=self.USER_URL, - user_id=uuid.uuid4().hex, - password=uuid.uuid4().hex, - project_id=uuid.uuid4().hex) + self.user_auth = identity.V3Password( + auth_url=self.USER_URL, + user_id=uuid.uuid4().hex, + password=uuid.uuid4().hex, + project_id=uuid.uuid4().hex, + ) self.service_token_id = uuid.uuid4().hex self.service_token = fixture.V3Token() self.service_token.set_project_scope() - self.service_auth = identity.V3Password(auth_url=self.SERVICE_URL, - user_id=uuid.uuid4().hex, - password=uuid.uuid4().hex, - project_id=uuid.uuid4().hex) + self.service_auth = identity.V3Password( + auth_url=self.SERVICE_URL, + user_id=uuid.uuid4().hex, + password=uuid.uuid4().hex, + project_id=uuid.uuid4().hex, + ) for t in (self.user_token, self.service_token): s = t.add_service('identity') - s.add_standard_endpoints(public='http://keystone.example.com', - admin='http://keystone.example.com', - internal='http://keystone.example.com') + s.add_standard_endpoints( + public='http://keystone.example.com', + admin='http://keystone.example.com', + internal='http://keystone.example.com', + ) self.test_data = {'data': uuid.uuid4().hex} self.user_mock = self.requests_mock.post( self.USER_URL + '/auth/tokens', json=self.user_token, - headers={'X-Subject-Token': self.user_token_id}) + headers={'X-Subject-Token': self.user_token_id}, + ) self.service_mock = self.requests_mock.post( self.SERVICE_URL + '/auth/tokens', json=self.service_token, - headers={'X-Subject-Token': self.service_token_id}) + headers={'X-Subject-Token': self.service_token_id}, + ) self.requests_mock.get(self.TEST_URL, json=self.test_data) self.combined_auth = service_token.ServiceTokenAuthWrapper( - self.user_auth, - self.service_auth) + self.user_auth, self.service_auth + ) self.session = session.Session(auth=self.combined_auth) @@ -96,21 +103,32 @@ def test_invalidation(self): self.assertEqual(2, self.service_mock.call_count) def test_pass_throughs(self): - self.assertEqual(self.user_auth.get_token(self.session), - self.combined_auth.get_token(self.session)) + self.assertEqual( + self.user_auth.get_token(self.session), + self.combined_auth.get_token(self.session), + ) self.assertEqual( self.user_auth.get_endpoint(self.session, 'identity'), - self.combined_auth.get_endpoint(self.session, 'identity')) + self.combined_auth.get_endpoint(self.session, 'identity'), + ) - self.assertEqual(self.user_auth.get_user_id(self.session), - self.combined_auth.get_user_id(self.session)) + self.assertEqual( + self.user_auth.get_user_id(self.session), + self.combined_auth.get_user_id(self.session), + ) - self.assertEqual(self.user_auth.get_project_id(self.session), - self.combined_auth.get_project_id(self.session)) + self.assertEqual( + self.user_auth.get_project_id(self.session), + self.combined_auth.get_project_id(self.session), + ) - self.assertEqual(self.user_auth.get_sp_auth_url(self.session, 'a'), - self.combined_auth.get_sp_auth_url(self.session, 'a')) + self.assertEqual( + self.user_auth.get_sp_auth_url(self.session, 'a'), + self.combined_auth.get_sp_auth_url(self.session, 'a'), + ) - self.assertEqual(self.user_auth.get_sp_url(self.session, 'a'), - self.combined_auth.get_sp_url(self.session, 'a')) + self.assertEqual( + self.user_auth.get_sp_url(self.session, 'a'), + self.combined_auth.get_sp_url(self.session, 'a'), + ) diff --git a/keystoneauth1/tests/unit/test_session.py b/keystoneauth1/tests/unit/test_session.py index 8f95d6bd..0d94b5a0 100644 --- a/keystoneauth1/tests/unit/test_session.py +++ b/keystoneauth1/tests/unit/test_session.py @@ -34,9 +34,8 @@ class RequestsAuth(requests.auth.AuthBase): - def __init__(self, *args, **kwargs): - super(RequestsAuth, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.header_name = uuid.uuid4().hex self.header_val = uuid.uuid4().hex self.called = False @@ -48,7 +47,6 @@ def __call__(self, request): class SessionTests(utils.TestCase): - TEST_URL = 'http://127.0.0.1:5000/' def test_get(self): @@ -109,11 +107,11 @@ def test_patch(self): self.assertRequestBodyIs(json={'hello': 'world'}) def test_set_microversion_headers(self): - # String microversion, specified service type headers = {} client_session.Session._set_microversion_headers( - headers, '2.30', 'compute', None) + headers, '2.30', 'compute', None + ) self.assertEqual(headers['OpenStack-API-Version'], 'compute 2.30') self.assertEqual(headers['X-OpenStack-Nova-API-Version'], '2.30') self.assertEqual(len(headers.keys()), 2) @@ -121,7 +119,8 @@ def test_set_microversion_headers(self): # Tuple microversion, service type via endpoint_filter headers = {} client_session.Session._set_microversion_headers( - headers, (2, 30), None, {'service_type': 'compute'}) + headers, (2, 30), None, {'service_type': 'compute'} + ) self.assertEqual(headers['OpenStack-API-Version'], 'compute 2.30') self.assertEqual(headers['X-OpenStack-Nova-API-Version'], '2.30') self.assertEqual(len(headers.keys()), 2) @@ -129,7 +128,8 @@ def test_set_microversion_headers(self): # 'latest' (string) microversion headers = {} client_session.Session._set_microversion_headers( - headers, 'latest', 'compute', None) + headers, 'latest', 'compute', None + ) self.assertEqual(headers['OpenStack-API-Version'], 'compute latest') self.assertEqual(headers['X-OpenStack-Nova-API-Version'], 'latest') self.assertEqual(len(headers.keys()), 2) @@ -137,7 +137,8 @@ def test_set_microversion_headers(self): # LATEST (tuple) microversion headers = {} client_session.Session._set_microversion_headers( - headers, (discover.LATEST, discover.LATEST), 'compute', None) + headers, (discover.LATEST, discover.LATEST), 'compute', None + ) self.assertEqual(headers['OpenStack-API-Version'], 'compute latest') self.assertEqual(headers['X-OpenStack-Nova-API-Version'], 'latest') self.assertEqual(len(headers.keys()), 2) @@ -145,7 +146,8 @@ def test_set_microversion_headers(self): # ironic microversion, specified service type headers = {} client_session.Session._set_microversion_headers( - headers, '2.30', 'baremetal', None) + headers, '2.30', 'baremetal', None + ) self.assertEqual(headers['OpenStack-API-Version'], 'baremetal 2.30') self.assertEqual(headers['X-OpenStack-Ironic-API-Version'], '2.30') self.assertEqual(len(headers.keys()), 2) @@ -153,14 +155,16 @@ def test_set_microversion_headers(self): # volumev2 service-type - volume microversion headers = {} client_session.Session._set_microversion_headers( - headers, (2, 30), None, {'service_type': 'volumev2'}) + headers, (2, 30), None, {'service_type': 'volumev2'} + ) self.assertEqual(headers['OpenStack-API-Version'], 'volume 2.30') self.assertEqual(len(headers.keys()), 1) # block-storage service-type - volume microversion headers = {} client_session.Session._set_microversion_headers( - headers, (2, 30), None, {'service_type': 'block-storage'}) + headers, (2, 30), None, {'service_type': 'block-storage'} + ) self.assertEqual(headers['OpenStack-API-Version'], 'volume 2.30') self.assertEqual(len(headers.keys()), 1) @@ -169,10 +173,12 @@ def test_set_microversion_headers(self): for service_type in ['sharev2', 'shared-file-system']: headers = {} client_session.Session._set_microversion_headers( - headers, (2, 30), None, {'service_type': service_type}) + headers, (2, 30), None, {'service_type': service_type} + ) self.assertEqual(headers['X-OpenStack-Manila-API-Version'], '2.30') - self.assertEqual(headers['OpenStack-API-Version'], - 'shared-file-system 2.30') + self.assertEqual( + headers['OpenStack-API-Version'], 'shared-file-system 2.30' + ) self.assertEqual(len(headers.keys()), 2) # Headers already exist - no change @@ -181,30 +187,56 @@ def test_set_microversion_headers(self): 'X-OpenStack-Nova-API-Version': '2.30', } client_session.Session._set_microversion_headers( - headers, (2, 31), None, {'service_type': 'volume'}) + headers, (2, 31), None, {'service_type': 'volume'} + ) self.assertEqual(headers['OpenStack-API-Version'], 'compute 2.30') self.assertEqual(headers['X-OpenStack-Nova-API-Version'], '2.30') # Can't specify a 'M.latest' microversion - self.assertRaises(TypeError, - client_session.Session._set_microversion_headers, - {}, '2.latest', 'service_type', None) - self.assertRaises(TypeError, - client_session.Session._set_microversion_headers, - {}, (2, discover.LATEST), 'service_type', None) + self.assertRaises( + TypeError, + client_session.Session._set_microversion_headers, + {}, + '2.latest', + 'service_type', + None, + ) + self.assertRaises( + TypeError, + client_session.Session._set_microversion_headers, + {}, + (2, discover.LATEST), + 'service_type', + None, + ) # Normalization error - self.assertRaises(TypeError, - client_session.Session._set_microversion_headers, - {}, 'bogus', 'service_type', None) + self.assertRaises( + TypeError, + client_session.Session._set_microversion_headers, + {}, + 'bogus', + 'service_type', + None, + ) # No service type in param or endpoint filter - self.assertRaises(TypeError, - client_session.Session._set_microversion_headers, - {}, (2, 30), None, None) - self.assertRaises(TypeError, - client_session.Session._set_microversion_headers, - {}, (2, 30), None, {'no_service_type': 'here'}) + self.assertRaises( + TypeError, + client_session.Session._set_microversion_headers, + {}, + (2, 30), + None, + None, + ) + self.assertRaises( + TypeError, + client_session.Session._set_microversion_headers, + {}, + (2, 30), + None, + {'no_service_type': 'here'}, + ) def test_microversion(self): # microversion not specified @@ -217,9 +249,12 @@ def test_microversion(self): session = client_session.Session() self.stub_url('GET', text='response') - resp = session.get(self.TEST_URL, microversion='2.30', - microversion_service_type='compute', - endpoint_filter={'endpoint': 'filter'}) + resp = session.get( + self.TEST_URL, + microversion='2.30', + microversion_service_type='compute', + endpoint_filter={'endpoint': 'filter'}, + ) self.assertTrue(resp.ok) self.assertRequestHeaderEqual('OpenStack-API-Version', 'compute 2.30') @@ -233,7 +268,8 @@ def test_user_agent(self): self.assertTrue(resp.ok) self.assertRequestHeaderEqual( 'User-Agent', - '%s %s' % ("run.py", client_session.DEFAULT_USER_AGENT)) + '{} {}'.format("run.py", client_session.DEFAULT_USER_AGENT), + ) custom_agent = 'custom-agent/1.0' session = client_session.Session(user_agent=custom_agent) @@ -242,15 +278,18 @@ def test_user_agent(self): self.assertTrue(resp.ok) self.assertRequestHeaderEqual( - 'User-Agent', - '%s %s' % (custom_agent, client_session.DEFAULT_USER_AGENT)) + 'User-Agent', f'{custom_agent} {client_session.DEFAULT_USER_AGENT}' + ) resp = session.get(self.TEST_URL, headers={'User-Agent': 'new-agent'}) self.assertTrue(resp.ok) self.assertRequestHeaderEqual('User-Agent', 'new-agent') - resp = session.get(self.TEST_URL, headers={'User-Agent': 'new-agent'}, - user_agent='overrides-agent') + resp = session.get( + self.TEST_URL, + headers={'User-Agent': 'new-agent'}, + user_agent='overrides-agent', + ) self.assertTrue(resp.ok) self.assertRequestHeaderEqual('User-Agent', 'overrides-agent') @@ -260,8 +299,8 @@ def test_user_agent(self): resp = session.get(self.TEST_URL) self.assertTrue(resp.ok) self.assertRequestHeaderEqual( - 'User-Agent', - client_session.DEFAULT_USER_AGENT) + 'User-Agent', client_session.DEFAULT_USER_AGENT + ) # If sys.argv[0] is an empty string, then doesn't fail. with mock.patch.object(sys, 'argv', ['']): @@ -269,12 +308,13 @@ def test_user_agent(self): resp = session.get(self.TEST_URL) self.assertTrue(resp.ok) self.assertRequestHeaderEqual( - 'User-Agent', - client_session.DEFAULT_USER_AGENT) + 'User-Agent', client_session.DEFAULT_USER_AGENT + ) def test_http_session_opts(self): - session = client_session.Session(cert='cert.pem', timeout=5, - verify='certs') + session = client_session.Session( + cert='cert.pem', timeout=5, verify='certs' + ) FAKE_RESP = utils.TestResponse({'status_code': 200, 'text': 'resp'}) RESP = mock.Mock(return_value=FAKE_RESP) @@ -299,8 +339,9 @@ def test_not_found(self): def test_server_error(self): session = client_session.Session() self.stub_url('GET', status_code=500) - self.assertRaises(exceptions.InternalServerError, - session.get, self.TEST_URL) + self.assertRaises( + exceptions.InternalServerError, session.get, self.TEST_URL + ) def test_session_debug_output(self): """Test request and response headers in debug logs. @@ -308,16 +349,18 @@ def test_session_debug_output(self): in order to redact secure headers while debug is true. """ session = client_session.Session(verify=False) - headers = {'HEADERA': 'HEADERVALB', - 'Content-Type': 'application/json'} - security_headers = {'Authorization': uuid.uuid4().hex, - 'X-Auth-Token': uuid.uuid4().hex, - 'X-Subject-Token': uuid.uuid4().hex, - 'X-Service-Token': uuid.uuid4().hex} + headers = {'HEADERA': 'HEADERVALB', 'Content-Type': 'application/json'} + security_headers = { + 'Authorization': uuid.uuid4().hex, + 'X-Auth-Token': uuid.uuid4().hex, + 'X-Subject-Token': uuid.uuid4().hex, + 'X-Service-Token': uuid.uuid4().hex, + } body = '{"a": "b"}' data = '{"c": "d"}' all_headers = dict( - itertools.chain(headers.items(), security_headers.items())) + itertools.chain(headers.items(), security_headers.items()) + ) self.stub_url('POST', text=body, headers=all_headers) resp = session.post(self.TEST_URL, headers=all_headers, data=data) self.assertEqual(resp.status_code, 200) @@ -326,7 +369,7 @@ def test_session_debug_output(self): self.assertIn('POST', self.logger.output) self.assertIn('--insecure', self.logger.output) self.assertIn(body, self.logger.output) - self.assertIn("'%s'" % data, self.logger.output) + self.assertIn(f"'{data}'", self.logger.output) for k, v in headers.items(): self.assertIn(k, self.logger.output) @@ -335,12 +378,13 @@ def test_session_debug_output(self): # Assert that response headers contains actual values and # only debug logs has been masked for k, v in security_headers.items(): - self.assertIn('%s: {SHA256}' % k, self.logger.output) + self.assertIn(f'{k}: {{SHA256}}', self.logger.output) self.assertEqual(v, resp.headers[k]) self.assertNotIn(v, self.logger.output) def test_session_debug_output_logs_openstack_request_id(self): """Test x-openstack-request-id is logged in debug logs.""" + def get_response(log=True): session = client_session.Session(verify=False) endpoint_filter = {'service_name': 'Identity'} @@ -349,16 +393,23 @@ def get_response(log=True): data = 'BODYDATA' all_headers = dict(itertools.chain(headers.items())) self.stub_url('POST', text=body, headers=all_headers) - resp = session.post(self.TEST_URL, endpoint_filter=endpoint_filter, - headers=all_headers, data=data, log=log) + resp = session.post( + self.TEST_URL, + endpoint_filter=endpoint_filter, + headers=all_headers, + data=data, + log=log, + ) return resp # if log is disabled then request-id is not logged in debug logs resp = get_response(log=False) self.assertEqual(resp.status_code, 200) - expected_log = ('POST call to Identity for %s used request ' - 'id req-1234' % self.TEST_URL) + expected_log = ( + f'POST call to Identity for {self.TEST_URL} used request ' + 'id req-1234' + ) self.assertNotIn(expected_log, self.logger.output) # if log is enabled then request-id is logged in debug logs @@ -371,8 +422,12 @@ def test_logs_failed_output(self): session = client_session.Session() body = {uuid.uuid4().hex: uuid.uuid4().hex} - self.stub_url('GET', json=body, status_code=400, - headers={'Content-Type': 'application/json'}) + self.stub_url( + 'GET', + json=body, + status_code=400, + headers={'Content-Type': 'application/json'}, + ) resp = session.get(self.TEST_URL, raise_exc=False) self.assertEqual(resp.status_code, 400) @@ -387,9 +442,11 @@ def test_logging_body_only_for_specified_content_types(self): unexpected MemoryError when reading arbitrary responses, such as streams. """ - OMITTED_BODY = ('Omitted, Content-Type is set to %s. Only ' + - ', '.join(client_session._LOG_CONTENT_TYPES) + - ' responses have their bodies logged.') + OMITTED_BODY = ( + 'Omitted, Content-Type is set to %s. Only ' + + ', '.join(client_session._LOG_CONTENT_TYPES) + + ' responses have their bodies logged.' + ) session = client_session.Session(verify=False) # Content-Type is not set @@ -408,8 +465,9 @@ def test_logging_body_only_for_specified_content_types(self): # Content-Type is set to application/json body = json.dumps({'token': {'id': '...'}}) - self.stub_url('POST', text=body, - headers={'Content-Type': 'application/json'}) + self.stub_url( + 'POST', text=body, headers={'Content-Type': 'application/json'} + ) session.post(self.TEST_URL) self.assertIn(body, self.logger.output) self.assertNotIn(OMITTED_BODY % 'application/json', self.logger.output) @@ -417,29 +475,38 @@ def test_logging_body_only_for_specified_content_types(self): # Content-Type is set to application/json; charset=UTF-8 body = json.dumps({'token': {'id': '...'}}) self.stub_url( - 'POST', text=body, - headers={'Content-Type': 'application/json; charset=UTF-8'}) + 'POST', + text=body, + headers={'Content-Type': 'application/json; charset=UTF-8'}, + ) session.post(self.TEST_URL) self.assertIn(body, self.logger.output) - self.assertNotIn(OMITTED_BODY % 'application/json; charset=UTF-8', - self.logger.output) + self.assertNotIn( + OMITTED_BODY % 'application/json; charset=UTF-8', + self.logger.output, + ) # Content-Type is set to text/plain text = 'Error detected, unable to continue.' - self.stub_url('POST', text=text, - headers={'Content-Type': 'text/plain'}) + self.stub_url( + 'POST', text=text, headers={'Content-Type': 'text/plain'} + ) session.post(self.TEST_URL) self.assertIn(text, self.logger.output) self.assertNotIn(OMITTED_BODY % 'text/plain', self.logger.output) # Content-Type is set to text/plain; charset=UTF-8 text = 'Error detected, unable to continue.' - self.stub_url('POST', text=text, - headers={'Content-Type': 'text/plain; charset=UTF-8'}) + self.stub_url( + 'POST', + text=text, + headers={'Content-Type': 'text/plain; charset=UTF-8'}, + ) session.post(self.TEST_URL) self.assertIn(text, self.logger.output) - self.assertNotIn(OMITTED_BODY % 'text/plain; charset=UTF-8', - self.logger.output) + self.assertNotIn( + OMITTED_BODY % 'text/plain; charset=UTF-8', self.logger.output + ) def test_logging_cacerts(self): path_to_certs = '/path/to/certs' @@ -451,8 +518,9 @@ def test_logging_cacerts(self): self.assertIn('--cacert', self.logger.output) self.assertIn(path_to_certs, self.logger.output) - def _connect_retries_check(self, session, expected_retries=0, - call_args=None): + def _connect_retries_check( + self, session, expected_retries=0, call_args=None + ): call_args = call_args or {} self.stub_url('GET', exc=requests.exceptions.Timeout()) @@ -460,17 +528,19 @@ def _connect_retries_check(self, session, expected_retries=0, call_args['url'] = self.TEST_URL with mock.patch('time.sleep') as m: - self.assertRaises(exceptions.ConnectTimeout, - session.get, - **call_args) + self.assertRaises( + exceptions.ConnectTimeout, session.get, **call_args + ) self.assertEqual(expected_retries, m.call_count) # 3 retries finishing with 2.0 means 0.5, 1.0 and 2.0 m.assert_called_with(2.0) # we count retries so there will be one initial request + 3 retries - self.assertThat(self.requests_mock.request_history, - matchers.HasLength(expected_retries + 1)) + self.assertThat( + self.requests_mock.request_history, + matchers.HasLength(expected_retries + 1), + ) def test_session_connect_retries(self): retries = 3 @@ -481,18 +551,20 @@ def test_call_args_connect_retries_session_init(self): session = client_session.Session() retries = 3 call_args = {'connect_retries': retries} - self._connect_retries_check(session=session, - expected_retries=retries, - call_args=call_args) + self._connect_retries_check( + session=session, expected_retries=retries, call_args=call_args + ) def test_call_args_connect_retries_overrides_session_retries(self): session_retries = 6 call_arg_retries = 3 call_args = {'connect_retries': call_arg_retries} session = client_session.Session(connect_retries=session_retries) - self._connect_retries_check(session=session, - expected_retries=call_arg_retries, - call_args=call_args) + self._connect_retries_check( + session=session, + expected_retries=call_arg_retries, + call_args=call_args, + ) def test_override_session_connect_retries_for_request(self): session_retries = 1 @@ -507,7 +579,7 @@ def test_override_session_connect_retries_for_request(self): session.request, self.TEST_URL, 'GET', - **call_args + **call_args, ) self.assertEqual(0, m.call_count) @@ -519,16 +591,20 @@ def test_connect_retries_interval_limit(self): retries = 20 with mock.patch('time.sleep') as m: - self.assertRaises(exceptions.ConnectTimeout, - session.get, - self.TEST_URL, connect_retries=retries) + self.assertRaises( + exceptions.ConnectTimeout, + session.get, + self.TEST_URL, + connect_retries=retries, + ) self.assertEqual(retries, m.call_count) # The interval maxes out at 60 m.assert_called_with(60.0) - self.assertThat(self.requests_mock.request_history, - matchers.HasLength(retries + 1)) + self.assertThat( + self.requests_mock.request_history, matchers.HasLength(retries + 1) + ) def test_connect_retries_fixed_delay(self): self.stub_url('GET', exc=requests.exceptions.Timeout()) @@ -537,17 +613,21 @@ def test_connect_retries_fixed_delay(self): retries = 3 with mock.patch('time.sleep') as m: - self.assertRaises(exceptions.ConnectTimeout, - session.get, - self.TEST_URL, connect_retries=retries, - connect_retry_delay=0.5) + self.assertRaises( + exceptions.ConnectTimeout, + session.get, + self.TEST_URL, + connect_retries=retries, + connect_retry_delay=0.5, + ) self.assertEqual(retries, m.call_count) m.assert_has_calls([mock.call(0.5)] * retries) # we count retries so there will be one initial request + 3 retries - self.assertThat(self.requests_mock.request_history, - matchers.HasLength(retries + 1)) + self.assertThat( + self.requests_mock.request_history, matchers.HasLength(retries + 1) + ) def test_http_503_retries(self): self.stub_url('GET', status_code=503) @@ -556,17 +636,21 @@ def test_http_503_retries(self): retries = 3 with mock.patch('time.sleep') as m: - self.assertRaises(exceptions.ServiceUnavailable, - session.get, - self.TEST_URL, status_code_retries=retries) + self.assertRaises( + exceptions.ServiceUnavailable, + session.get, + self.TEST_URL, + status_code_retries=retries, + ) self.assertEqual(retries, m.call_count) # 3 retries finishing with 2.0 means 0.5, 1.0 and 2.0 m.assert_called_with(2.0) # we count retries so there will be one initial request + 3 retries - self.assertThat(self.requests_mock.request_history, - matchers.HasLength(retries + 1)) + self.assertThat( + self.requests_mock.request_history, matchers.HasLength(retries + 1) + ) def test_http_status_retries(self): self.stub_url('GET', status_code=409) @@ -575,18 +659,22 @@ def test_http_status_retries(self): retries = 3 with mock.patch('time.sleep') as m: - self.assertRaises(exceptions.Conflict, - session.get, - self.TEST_URL, status_code_retries=retries, - retriable_status_codes=[503, 409]) + self.assertRaises( + exceptions.Conflict, + session.get, + self.TEST_URL, + status_code_retries=retries, + retriable_status_codes=[503, 409], + ) self.assertEqual(retries, m.call_count) # 3 retries finishing with 2.0 means 0.5, 1.0 and 2.0 m.assert_called_with(2.0) # we count retries so there will be one initial request + 3 retries - self.assertThat(self.requests_mock.request_history, - matchers.HasLength(retries + 1)) + self.assertThat( + self.requests_mock.request_history, matchers.HasLength(retries + 1) + ) def test_http_status_retries_another_code(self): self.stub_url('GET', status_code=404) @@ -595,15 +683,19 @@ def test_http_status_retries_another_code(self): retries = 3 with mock.patch('time.sleep') as m: - self.assertRaises(exceptions.NotFound, - session.get, - self.TEST_URL, status_code_retries=retries, - retriable_status_codes=[503, 409]) + self.assertRaises( + exceptions.NotFound, + session.get, + self.TEST_URL, + status_code_retries=retries, + retriable_status_codes=[503, 409], + ) self.assertFalse(m.called) - self.assertThat(self.requests_mock.request_history, - matchers.HasLength(1)) + self.assertThat( + self.requests_mock.request_history, matchers.HasLength(1) + ) def test_http_status_retries_fixed_delay(self): self.stub_url('GET', status_code=409) @@ -612,18 +704,22 @@ def test_http_status_retries_fixed_delay(self): retries = 3 with mock.patch('time.sleep') as m: - self.assertRaises(exceptions.Conflict, - session.get, - self.TEST_URL, status_code_retries=retries, - status_code_retry_delay=0.5, - retriable_status_codes=[503, 409]) + self.assertRaises( + exceptions.Conflict, + session.get, + self.TEST_URL, + status_code_retries=retries, + status_code_retry_delay=0.5, + retriable_status_codes=[503, 409], + ) self.assertEqual(retries, m.call_count) m.assert_has_calls([mock.call(0.5)] * retries) # we count retries so there will be one initial request + 3 retries - self.assertThat(self.requests_mock.request_history, - matchers.HasLength(retries + 1)) + self.assertThat( + self.requests_mock.request_history, matchers.HasLength(retries + 1) + ) def test_http_status_retries_inverval_limit(self): self.stub_url('GET', status_code=409) @@ -632,26 +728,34 @@ def test_http_status_retries_inverval_limit(self): retries = 20 with mock.patch('time.sleep') as m: - self.assertRaises(exceptions.Conflict, - session.get, - self.TEST_URL, status_code_retries=retries, - retriable_status_codes=[503, 409]) + self.assertRaises( + exceptions.Conflict, + session.get, + self.TEST_URL, + status_code_retries=retries, + retriable_status_codes=[503, 409], + ) self.assertEqual(retries, m.call_count) # The interval maxes out at 60 m.assert_called_with(60.0) # we count retries so there will be one initial request + 3 retries - self.assertThat(self.requests_mock.request_history, - matchers.HasLength(retries + 1)) + self.assertThat( + self.requests_mock.request_history, matchers.HasLength(retries + 1) + ) def test_uses_tcp_keepalive_by_default(self): session = client_session.Session() requests_session = session.session - self.assertIsInstance(requests_session.adapters['http://'], - client_session.TCPKeepAliveAdapter) - self.assertIsInstance(requests_session.adapters['https://'], - client_session.TCPKeepAliveAdapter) + self.assertIsInstance( + requests_session.adapters['http://'], + client_session.TCPKeepAliveAdapter, + ) + self.assertIsInstance( + requests_session.adapters['https://'], + client_session.TCPKeepAliveAdapter, + ) def test_does_not_set_tcp_keepalive_on_custom_sessions(self): mock_session = mock.Mock() @@ -665,30 +769,26 @@ def test_ssl_error_message(self): session = client_session.Session() # The exception should contain the URL and details about the SSL error - msg = 'SSL exception connecting to %(url)s: %(error)s' % { - 'url': self.TEST_URL, 'error': error} - self.assertRaisesRegex(exceptions.SSLError, - msg, - session.get, - self.TEST_URL) + msg = f'SSL exception connecting to {self.TEST_URL}: {error}' + self.assertRaisesRegex( + exceptions.SSLError, msg, session.get, self.TEST_URL + ) def test_json_content_type(self): session = client_session.Session() self.stub_url('POST', text='response') resp = session.post( self.TEST_URL, - json=[{'op': 'replace', - 'path': '/name', - 'value': 'new_name'}], - headers={'Content-Type': 'application/json-patch+json'}) + json=[{'op': 'replace', 'path': '/name', 'value': 'new_name'}], + headers={'Content-Type': 'application/json-patch+json'}, + ) self.assertEqual('POST', self.requests_mock.last_request.method) self.assertEqual(resp.text, 'response') self.assertTrue(resp.ok) self.assertRequestBodyIs( - json=[{'op': 'replace', - 'path': '/name', - 'value': 'new_name'}]) + json=[{'op': 'replace', 'path': '/name', 'value': 'new_name'}] + ) self.assertContentTypeIs('application/json-patch+json') def test_api_sig_error_message_single(self): @@ -703,21 +803,22 @@ def test_api_sig_error_message_single(self): 'title': title, 'detail': detail, 'links': [ - { - 'rel': 'help', - 'href': 'https://openstack.org' - } - ] + {'rel': 'help', 'href': 'https://openstack.org'} + ], } ] } payload = json.dumps(error_message) - self.stub_url('GET', status_code=9000, text=payload, - headers={'Content-Type': 'application/json'}) + self.stub_url( + 'GET', + status_code=9000, + text=payload, + headers={'Content-Type': 'application/json'}, + ) session = client_session.Session() # The exception should contain the information from the error response - msg = '{} (HTTP 9000)'.format(title) + msg = f'{title} (HTTP 9000)' try: session.get(self.TEST_URL) except exceptions.HttpError as ex: @@ -736,11 +837,8 @@ def test_api_sig_error_message_multiple(self): 'title': title, 'detail': detail, 'links': [ - { - 'rel': 'help', - 'href': 'https://openstack.org' - } - ] + {'rel': 'help', 'href': 'https://openstack.org'} + ], }, { 'request_id': uuid.uuid4().hex, @@ -749,22 +847,22 @@ def test_api_sig_error_message_multiple(self): 'title': 'some other error', 'detail': detail, 'links': [ - { - 'rel': 'help', - 'href': 'https://openstack.org' - } - ] - } + {'rel': 'help', 'href': 'https://openstack.org'} + ], + }, ] } payload = json.dumps(error_message) - self.stub_url('GET', status_code=9000, text=payload, - headers={'Content-Type': 'application/json'}) + self.stub_url( + 'GET', + status_code=9000, + text=payload, + headers={'Content-Type': 'application/json'}, + ) session = client_session.Session() # The exception should contain the information from the error response - msg = ('Multiple error responses, showing first only: {} (HTTP 9000)' - .format(title)) + msg = f'Multiple error responses, showing first only: {title} (HTTP 9000)' try: session.get(self.TEST_URL) except exceptions.HttpError as ex: @@ -772,13 +870,14 @@ def test_api_sig_error_message_multiple(self): self.assertEqual(ex.details, detail) def test_api_sig_error_message_empty(self): - error_message = { - 'errors': [ - ] - } + error_message = {'errors': []} payload = json.dumps(error_message) - self.stub_url('GET', status_code=9000, text=payload, - headers={'Content-Type': 'application/json'}) + self.stub_url( + 'GET', + status_code=9000, + text=payload, + headers={'Content-Type': 'application/json'}, + ) session = client_session.Session() # The exception should contain the information from the error response @@ -793,8 +892,12 @@ def test_api_sig_error_message_empty(self): def test_error_message_unknown_schema(self): error_message = 'Uh oh, things went bad!' payload = json.dumps(error_message) - self.stub_url('GET', status_code=9000, text=payload, - headers={'Content-Type': 'application/json'}) + self.stub_url( + 'GET', + status_code=9000, + text=payload, + headers={'Content-Type': 'application/json'}, + ) session = client_session.Session() msg = 'Unrecognized schema in response body. (HTTP 9000)' @@ -805,28 +908,39 @@ def test_error_message_unknown_schema(self): class RedirectTests(utils.TestCase): - - REDIRECT_CHAIN = ['http://myhost:3445/', - 'http://anotherhost:6555/', - 'http://thirdhost/', - 'http://finaldestination:55/'] + REDIRECT_CHAIN = [ + 'http://myhost:3445/', + 'http://anotherhost:6555/', + 'http://thirdhost/', + 'http://finaldestination:55/', + ] DEFAULT_REDIRECT_BODY = 'Redirect' DEFAULT_RESP_BODY = 'Found' - def setup_redirects(self, method='GET', status_code=305, - redirect_kwargs={}, final_kwargs={}): + def setup_redirects( + self, + method='GET', + status_code=305, + redirect_kwargs={}, + final_kwargs={}, + ): redirect_kwargs.setdefault('text', self.DEFAULT_REDIRECT_BODY) for s, d in zip(self.REDIRECT_CHAIN, self.REDIRECT_CHAIN[1:]): - self.requests_mock.register_uri(method, s, status_code=status_code, - headers={'Location': d}, - **redirect_kwargs) + self.requests_mock.register_uri( + method, + s, + status_code=status_code, + headers={'Location': d}, + **redirect_kwargs, + ) final_kwargs.setdefault('status_code', 200) final_kwargs.setdefault('text', self.DEFAULT_RESP_BODY) - self.requests_mock.register_uri(method, self.REDIRECT_CHAIN[-1], - **final_kwargs) + self.requests_mock.register_uri( + method, self.REDIRECT_CHAIN[-1], **final_kwargs + ) def assertResponse(self, resp): self.assertEqual(resp.status_code, 200) @@ -881,8 +995,7 @@ def test_redirect_with_params(self): def test_history_matches_requests(self): self.setup_redirects(status_code=301) session = client_session.Session(redirect=True) - req_resp = requests.get(self.REDIRECT_CHAIN[0], - allow_redirects=True) + req_resp = requests.get(self.REDIRECT_CHAIN[0], allow_redirects=True) ses_resp = session.get(self.REDIRECT_CHAIN[0]) @@ -901,11 +1014,14 @@ def test_permanent_redirect_308(self): def test_req_id_redirect(self): session = client_session.Session() self.setup_redirects(status_code=302) - resp = session.get(self.REDIRECT_CHAIN[0], - headers={'x-openstack-request-id': 'req-1234-5678'}) + resp = session.get( + self.REDIRECT_CHAIN[0], + headers={'x-openstack-request-id': 'req-1234-5678'}, + ) self.assertResponse(resp) - self.assertRequestHeaderEqual('x-openstack-request-id', - 'req-1234-5678') + self.assertRequestHeaderEqual( + 'x-openstack-request-id', 'req-1234-5678' + ) class AuthPlugin(plugin.BaseAuthPlugin): @@ -919,12 +1035,18 @@ class AuthPlugin(plugin.BaseAuthPlugin): TEST_PROJECT_ID = 'aProject' SERVICE_URLS = { - 'identity': {'public': 'http://identity-public:1111/v2.0', - 'admin': 'http://identity-admin:1111/v2.0'}, - 'compute': {'public': 'http://compute-public:2222/v1.0', - 'admin': 'http://compute-admin:2222/v1.0'}, - 'image': {'public': 'http://image-public:3333/v2.0', - 'admin': 'http://image-admin:3333/v2.0'} + 'identity': { + 'public': 'http://identity-public:1111/v2.0', + 'admin': 'http://identity-admin:1111/v2.0', + }, + 'compute': { + 'public': 'http://compute-public:2222/v1.0', + 'admin': 'http://compute-admin:2222/v1.0', + }, + 'image': { + 'public': 'http://image-public:3333/v2.0', + 'admin': 'http://image-admin:3333/v2.0', + }, } def __init__(self, token=TEST_TOKEN, invalidate=True): @@ -934,8 +1056,9 @@ def __init__(self, token=TEST_TOKEN, invalidate=True): def get_token(self, session): return self.token - def get_endpoint(self, session, service_type=None, interface=None, - **kwargs): + def get_endpoint( + self, session, service_type=None, interface=None, **kwargs + ): try: return self.SERVICE_URLS[service_type][interface] except (KeyError, AttributeError): @@ -952,7 +1075,6 @@ def get_project_id(self, session): class CalledAuthPlugin(plugin.BaseAuthPlugin): - ENDPOINT = 'http://fakeendpoint/' TOKEN = utils.TestCase.TEST_TOKEN USER_ID = uuid.uuid4().hex @@ -990,14 +1112,14 @@ def get_user_id(self, session, **kwargs): class SessionAuthTests(utils.TestCase): - TEST_URL = 'http://127.0.0.1:5000/' TEST_JSON = {'hello': 'world'} - def stub_service_url(self, service_type, interface, path, - method='GET', **kwargs): + def stub_service_url( + self, service_type, interface, path, method='GET', **kwargs + ): base_url = AuthPlugin.SERVICE_URLS[service_type][interface] - uri = "%s/%s" % (base_url.rstrip('/'), path.lstrip('/')) + uri = "{}/{}".format(base_url.rstrip('/'), path.lstrip('/')) self.requests_mock.register_uri(method, uri, **kwargs) @@ -1037,35 +1159,47 @@ def test_service_type_urls(self): status = 200 body = 'SUCCESS' - self.stub_service_url(service_type=service_type, - interface=interface, - path=path, - status_code=status, - text=body) + self.stub_service_url( + service_type=service_type, + interface=interface, + path=path, + status_code=status, + text=body, + ) sess = client_session.Session(auth=AuthPlugin()) - resp = sess.get(path, - endpoint_filter={'service_type': service_type, - 'interface': interface}) + resp = sess.get( + path, + endpoint_filter={ + 'service_type': service_type, + 'interface': interface, + }, + ) - self.assertEqual(self.requests_mock.last_request.url, - AuthPlugin.SERVICE_URLS['compute']['public'] + path) + self.assertEqual( + self.requests_mock.last_request.url, + AuthPlugin.SERVICE_URLS['compute']['public'] + path, + ) self.assertEqual(resp.text, body) self.assertEqual(resp.status_code, status) def test_service_url_raises_if_no_auth_plugin(self): sess = client_session.Session() - self.assertRaises(exceptions.MissingAuthPlugin, - sess.get, '/path', - endpoint_filter={'service_type': 'compute', - 'interface': 'public'}) + self.assertRaises( + exceptions.MissingAuthPlugin, + sess.get, + '/path', + endpoint_filter={'service_type': 'compute', 'interface': 'public'}, + ) def test_service_url_raises_if_no_url_returned(self): sess = client_session.Session(auth=AuthPlugin()) - self.assertRaises(exceptions.EndpointNotFound, - sess.get, '/path', - endpoint_filter={'service_type': 'unknown', - 'interface': 'public'}) + self.assertRaises( + exceptions.EndpointNotFound, + sess.get, + '/path', + endpoint_filter={'service_type': 'unknown', 'interface': 'public'}, + ) def test_raises_exc_only_when_asked(self): # A request that returns a HTTP error should by default raise an @@ -1082,17 +1216,24 @@ def test_passed_auth_plugin(self): passed = CalledAuthPlugin() sess = client_session.Session() - self.requests_mock.get(CalledAuthPlugin.ENDPOINT + 'path', - status_code=200) + self.requests_mock.get( + CalledAuthPlugin.ENDPOINT + 'path', status_code=200 + ) endpoint_filter = {'service_type': 'identity'} # no plugin with authenticated won't work - self.assertRaises(exceptions.MissingAuthPlugin, sess.get, 'path', - authenticated=True) + self.assertRaises( + exceptions.MissingAuthPlugin, sess.get, 'path', authenticated=True + ) # no plugin with an endpoint filter won't work - self.assertRaises(exceptions.MissingAuthPlugin, sess.get, 'path', - authenticated=False, endpoint_filter=endpoint_filter) + self.assertRaises( + exceptions.MissingAuthPlugin, + sess.get, + 'path', + authenticated=False, + endpoint_filter=endpoint_filter, + ) resp = sess.get('path', auth=passed, endpoint_filter=endpoint_filter) @@ -1106,11 +1247,13 @@ def test_passed_auth_plugin_overrides(self): sess = client_session.Session(fixed) - self.requests_mock.get(CalledAuthPlugin.ENDPOINT + 'path', - status_code=200) + self.requests_mock.get( + CalledAuthPlugin.ENDPOINT + 'path', status_code=200 + ) - resp = sess.get('path', auth=passed, - endpoint_filter={'service_type': 'identity'}) + resp = sess.get( + 'path', auth=passed, endpoint_filter={'service_type': 'identity'} + ) self.assertEqual(200, resp.status_code) self.assertTrue(passed.get_endpoint_called) @@ -1127,17 +1270,22 @@ def test_requests_auth_plugin(self): sess.get(self.TEST_URL, requests_auth=requests_auth) last = self.requests_mock.last_request - self.assertEqual(requests_auth.header_val, - last.headers[requests_auth.header_name]) + self.assertEqual( + requests_auth.header_val, last.headers[requests_auth.header_name] + ) self.assertTrue(requests_auth.called) def test_reauth_called(self): auth = CalledAuthPlugin(invalidate=True) sess = client_session.Session(auth=auth) - self.requests_mock.get(self.TEST_URL, - [{'text': 'Failed', 'status_code': 401}, - {'text': 'Hello', 'status_code': 200}]) + self.requests_mock.get( + self.TEST_URL, + [ + {'text': 'Failed', 'status_code': 401}, + {'text': 'Hello', 'status_code': 200}, + ], + ) # allow_reauth=True is the default resp = sess.get(self.TEST_URL, authenticated=True) @@ -1150,12 +1298,21 @@ def test_reauth_not_called(self): auth = CalledAuthPlugin(invalidate=True) sess = client_session.Session(auth=auth) - self.requests_mock.get(self.TEST_URL, - [{'text': 'Failed', 'status_code': 401}, - {'text': 'Hello', 'status_code': 200}]) - - self.assertRaises(exceptions.Unauthorized, sess.get, self.TEST_URL, - authenticated=True, allow_reauth=False) + self.requests_mock.get( + self.TEST_URL, + [ + {'text': 'Failed', 'status_code': 401}, + {'text': 'Hello', 'status_code': 200}, + ], + ) + + self.assertRaises( + exceptions.Unauthorized, + sess.get, + self.TEST_URL, + authenticated=True, + allow_reauth=False, + ) self.assertFalse(auth.invalidate_called) def test_endpoint_override_overrides_filter(self): @@ -1169,9 +1326,11 @@ def test_endpoint_override_overrides_filter(self): self.requests_mock.get(override_url, text=resp_text) - resp = sess.get(path, - endpoint_override=override_base, - endpoint_filter={'service_type': 'identity'}) + resp = sess.get( + path, + endpoint_override=override_base, + endpoint_filter={'service_type': 'identity'}, + ) self.assertEqual(resp_text, resp.text) self.assertEqual(override_url, self.requests_mock.last_request.url) @@ -1192,9 +1351,11 @@ def test_endpoint_override_ignore_full_url(self): resp_text = uuid.uuid4().hex self.requests_mock.get(url, text=resp_text) - resp = sess.get(url, - endpoint_override='http://someother.url', - endpoint_filter={'service_type': 'identity'}) + resp = sess.get( + url, + endpoint_override='http://someother.url', + endpoint_filter={'service_type': 'identity'}, + ) self.assertEqual(resp_text, resp.text) self.assertEqual(url, self.requests_mock.last_request.url) @@ -1211,16 +1372,20 @@ def test_endpoint_override_does_id_replacement(self): override_base = 'http://mytest/%(project_id)s/%(user_id)s' path = 'path' - replacements = {'user_id': CalledAuthPlugin.USER_ID, - 'project_id': CalledAuthPlugin.PROJECT_ID} + replacements = { + 'user_id': CalledAuthPlugin.USER_ID, + 'project_id': CalledAuthPlugin.PROJECT_ID, + } override_url = override_base % replacements + '/' + path resp_text = uuid.uuid4().hex self.requests_mock.get(override_url, text=resp_text) - resp = sess.get(path, - endpoint_override=override_base, - endpoint_filter={'service_type': 'identity'}) + resp = sess.get( + path, + endpoint_override=override_base, + endpoint_filter={'service_type': 'identity'}, + ) self.assertEqual(resp_text, resp.text) self.assertEqual(override_url, self.requests_mock.last_request.url) @@ -1237,20 +1402,24 @@ def test_endpoint_override_fails_to_replace_if_none(self): override_base = 'http://mytest/%(project_id)s' - e = self.assertRaises(ValueError, - sess.get, - '/path', - endpoint_override=override_base, - endpoint_filter={'service_type': 'identity'}) + e = self.assertRaises( + ValueError, + sess.get, + '/path', + endpoint_override=override_base, + endpoint_filter={'service_type': 'identity'}, + ) self.assertIn('project_id', str(e)) override_base = 'http://mytest/%(user_id)s' - e = self.assertRaises(ValueError, - sess.get, - '/path', - endpoint_override=override_base, - endpoint_filter={'service_type': 'identity'}) + e = self.assertRaises( + ValueError, + sess.get, + '/path', + endpoint_override=override_base, + endpoint_filter={'service_type': 'identity'}, + ) self.assertIn('user_id', str(e)) def test_endpoint_override_fails_to_do_unknown_replacement(self): @@ -1259,11 +1428,13 @@ def test_endpoint_override_fails_to_do_unknown_replacement(self): override_base = 'http://mytest/%(unknown_id)s' - e = self.assertRaises(AttributeError, - sess.get, - '/path', - endpoint_override=override_base, - endpoint_filter={'service_type': 'identity'}) + e = self.assertRaises( + AttributeError, + sess.get, + '/path', + endpoint_override=override_base, + endpoint_filter={'service_type': 'identity'}, + ) self.assertIn('unknown_id', str(e)) def test_user_and_project_id(self): @@ -1286,9 +1457,9 @@ def test_logger_object_passed(self): sess = client_session.Session(auth=auth) response = {uuid.uuid4().hex: uuid.uuid4().hex} - self.stub_url('GET', - json=response, - headers={'Content-Type': 'application/json'}) + self.stub_url( + 'GET', json=response, headers={'Content-Type': 'application/json'} + ) resp = sess.get(self.TEST_URL, logger=logger) @@ -1303,9 +1474,8 @@ def test_logger_object_passed(self): self.assertNotIn(list(response.values())[0], self.logger.output) def test_split_loggers(self): - def get_logger_io(name): - logger_name = 'keystoneauth.session.{name}'.format(name=name) + logger_name = f'keystoneauth.session.{name}' logger = logging.getLogger(logger_name) logger.setLevel(logging.DEBUG) @@ -1331,14 +1501,17 @@ def get_logger_io(name): headers={ 'Content-Type': 'application/json', 'X-OpenStack-Request-ID': request_id, - }) + }, + ) resp = sess.get( self.TEST_URL, headers={ - encodeutils.safe_encode('x-bytes-header'): - encodeutils.safe_encode('bytes-value') - }) + encodeutils.safe_encode( + 'x-bytes-header' + ): encodeutils.safe_encode('bytes-value') + }, + ) self.assertEqual(response, resp.json()) @@ -1347,29 +1520,28 @@ def get_logger_io(name): body_output = io_dict['body'].getvalue().strip() id_output = io_dict['request-id'].getvalue().strip() - self.assertIn('curl -g -i -X GET {url}'.format(url=self.TEST_URL), - request_output) + self.assertIn(f'curl -g -i -X GET {self.TEST_URL}', request_output) self.assertIn('-H "x-bytes-header: bytes-value"', request_output) - self.assertEqual('[200] Content-Type: application/json ' - 'X-OpenStack-Request-ID: ' - '{id}'.format(id=request_id), response_output) self.assertEqual( - 'GET call to {url} used request id {id}'.format( - url=self.TEST_URL, id=request_id), - id_output) + '[200] Content-Type: application/json ' + 'X-OpenStack-Request-ID: ' + f'{request_id}', + response_output, + ) self.assertEqual( - '{{"{key}": "{val}"}}'.format( - key=response_key, val=response_val), - body_output) + f'GET call to {self.TEST_URL} used request id {request_id}', + id_output, + ) + self.assertEqual(json.dumps({response_key: response_val}), body_output) def test_collect_timing(self): auth = AuthPlugin() sess = client_session.Session(auth=auth, collect_timing=True) response = {uuid.uuid4().hex: uuid.uuid4().hex} - self.stub_url('GET', - json=response, - headers={'Content-Type': 'application/json'}) + self.stub_url( + 'GET', json=response, headers={'Content-Type': 'application/json'} + ) resp = sess.get(self.TEST_URL) @@ -1384,41 +1556,47 @@ def test_collect_timing(self): class AdapterTest(utils.TestCase): - SERVICE_TYPE = uuid.uuid4().hex SERVICE_NAME = uuid.uuid4().hex INTERFACE = uuid.uuid4().hex REGION_NAME = uuid.uuid4().hex USER_AGENT = uuid.uuid4().hex VERSION = uuid.uuid4().hex - ALLOW = {'allow_deprecated': False, - 'allow_experimental': True, - 'allow_unknown': True} + ALLOW = { + 'allow_deprecated': False, + 'allow_experimental': True, + 'allow_unknown': True, + } TEST_URL = CalledAuthPlugin.ENDPOINT def _create_loaded_adapter(self, sess=None, auth=None): - return adapter.Adapter(sess or client_session.Session(), - auth=auth or CalledAuthPlugin(), - service_type=self.SERVICE_TYPE, - service_name=self.SERVICE_NAME, - interface=self.INTERFACE, - region_name=self.REGION_NAME, - user_agent=self.USER_AGENT, - version=self.VERSION, - allow=self.ALLOW) + return adapter.Adapter( + sess or client_session.Session(), + auth=auth or CalledAuthPlugin(), + service_type=self.SERVICE_TYPE, + service_name=self.SERVICE_NAME, + interface=self.INTERFACE, + region_name=self.REGION_NAME, + user_agent=self.USER_AGENT, + version=self.VERSION, + allow=self.ALLOW, + ) def _verify_endpoint_called(self, adpt): - self.assertEqual(self.SERVICE_TYPE, - adpt.auth.endpoint_arguments['service_type']) - self.assertEqual(self.SERVICE_NAME, - adpt.auth.endpoint_arguments['service_name']) - self.assertEqual(self.INTERFACE, - adpt.auth.endpoint_arguments['interface']) - self.assertEqual(self.REGION_NAME, - adpt.auth.endpoint_arguments['region_name']) - self.assertEqual(self.VERSION, - adpt.auth.endpoint_arguments['version']) + self.assertEqual( + self.SERVICE_TYPE, adpt.auth.endpoint_arguments['service_type'] + ) + self.assertEqual( + self.SERVICE_NAME, adpt.auth.endpoint_arguments['service_name'] + ) + self.assertEqual( + self.INTERFACE, adpt.auth.endpoint_arguments['interface'] + ) + self.assertEqual( + self.REGION_NAME, adpt.auth.endpoint_arguments['region_name'] + ) + self.assertEqual(self.VERSION, adpt.auth.endpoint_arguments['version']) def test_setting_variables_on_request(self): response = uuid.uuid4().hex @@ -1428,28 +1606,29 @@ def test_setting_variables_on_request(self): self.assertEqual(resp.text, response) self._verify_endpoint_called(adpt) - self.assertEqual(self.ALLOW, - adpt.auth.endpoint_arguments['allow']) + self.assertEqual(self.ALLOW, adpt.auth.endpoint_arguments['allow']) self.assertTrue(adpt.auth.get_token_called) self.assertRequestHeaderEqual('User-Agent', self.USER_AGENT) def test_setting_global_id_on_request(self): - global_id_adpt = "req-%s" % uuid.uuid4() - global_id_req = "req-%s" % uuid.uuid4() + global_id_adpt = f"req-{uuid.uuid4()}" + global_id_req = f"req-{uuid.uuid4()}" response = uuid.uuid4().hex self.stub_url('GET', text=response) def mk_adpt(**kwargs): - return adapter.Adapter(client_session.Session(), - auth=CalledAuthPlugin(), - service_type=self.SERVICE_TYPE, - service_name=self.SERVICE_NAME, - interface=self.INTERFACE, - region_name=self.REGION_NAME, - user_agent=self.USER_AGENT, - version=self.VERSION, - allow=self.ALLOW, - **kwargs) + return adapter.Adapter( + client_session.Session(), + auth=CalledAuthPlugin(), + service_type=self.SERVICE_TYPE, + service_name=self.SERVICE_NAME, + interface=self.INTERFACE, + region_name=self.REGION_NAME, + user_agent=self.USER_AGENT, + version=self.VERSION, + allow=self.ALLOW, + **kwargs, + ) # No global_request_id adpt = mk_adpt() @@ -1457,8 +1636,7 @@ def mk_adpt(**kwargs): self.assertEqual(resp.text, response) self._verify_endpoint_called(adpt) - self.assertEqual(self.ALLOW, - adpt.auth.endpoint_arguments['allow']) + self.assertEqual(self.ALLOW, adpt.auth.endpoint_arguments['allow']) self.assertTrue(adpt.auth.get_token_called) self.assertRequestHeaderEqual('X-OpenStack-Request-ID', None) @@ -1492,30 +1670,33 @@ def test_legacy_binding(self): auth = CalledAuthPlugin() sess = client_session.Session(auth=auth) - adpt = adapter.LegacyJsonAdapter(sess, - service_type=self.SERVICE_TYPE, - user_agent=self.USER_AGENT) + adpt = adapter.LegacyJsonAdapter( + sess, service_type=self.SERVICE_TYPE, user_agent=self.USER_AGENT + ) resp, body = adpt.get('/') - self.assertEqual(self.SERVICE_TYPE, - auth.endpoint_arguments['service_type']) + self.assertEqual( + self.SERVICE_TYPE, auth.endpoint_arguments['service_type'] + ) self.assertEqual(resp.text, response) self.assertEqual(val, body[key]) def test_legacy_binding_non_json_resp(self): response = uuid.uuid4().hex - self.stub_url('GET', text=response, - headers={'Content-Type': 'text/html'}) + self.stub_url( + 'GET', text=response, headers={'Content-Type': 'text/html'} + ) auth = CalledAuthPlugin() sess = client_session.Session(auth=auth) - adpt = adapter.LegacyJsonAdapter(sess, - service_type=self.SERVICE_TYPE, - user_agent=self.USER_AGENT) + adpt = adapter.LegacyJsonAdapter( + sess, service_type=self.SERVICE_TYPE, user_agent=self.USER_AGENT + ) resp, body = adpt.get('/') - self.assertEqual(self.SERVICE_TYPE, - auth.endpoint_arguments['service_type']) + self.assertEqual( + self.SERVICE_TYPE, auth.endpoint_arguments['service_type'] + ) self.assertEqual(resp.text, response) self.assertIsNone(body) @@ -1573,13 +1754,15 @@ def test_adapter_connect_retries(self): self.stub_url('GET', exc=requests.exceptions.ConnectionError()) with mock.patch('time.sleep') as m: - self.assertRaises(exceptions.ConnectionError, - adpt.get, self.TEST_URL) + self.assertRaises( + exceptions.ConnectionError, adpt.get, self.TEST_URL + ) self.assertEqual(retries, m.call_count) # we count retries so there will be one initial request + 2 retries - self.assertThat(self.requests_mock.request_history, - matchers.HasLength(retries + 1)) + self.assertThat( + self.requests_mock.request_history, matchers.HasLength(retries + 1) + ) def test_adapter_http_503_retries(self): retries = 2 @@ -1589,30 +1772,35 @@ def test_adapter_http_503_retries(self): self.stub_url('GET', status_code=503) with mock.patch('time.sleep') as m: - self.assertRaises(exceptions.ServiceUnavailable, - adpt.get, self.TEST_URL) + self.assertRaises( + exceptions.ServiceUnavailable, adpt.get, self.TEST_URL + ) self.assertEqual(retries, m.call_count) # we count retries so there will be one initial request + 2 retries - self.assertThat(self.requests_mock.request_history, - matchers.HasLength(retries + 1)) + self.assertThat( + self.requests_mock.request_history, matchers.HasLength(retries + 1) + ) def test_adapter_http_status_retries(self): retries = 2 sess = client_session.Session() - adpt = adapter.Adapter(sess, status_code_retries=retries, - retriable_status_codes=[503, 409]) + adpt = adapter.Adapter( + sess, + status_code_retries=retries, + retriable_status_codes=[503, 409], + ) self.stub_url('GET', status_code=409) with mock.patch('time.sleep') as m: - self.assertRaises(exceptions.Conflict, - adpt.get, self.TEST_URL) + self.assertRaises(exceptions.Conflict, adpt.get, self.TEST_URL) self.assertEqual(retries, m.call_count) # we count retries so there will be one initial request + 2 retries - self.assertThat(self.requests_mock.request_history, - matchers.HasLength(retries + 1)) + self.assertThat( + self.requests_mock.request_history, matchers.HasLength(retries + 1) + ) def test_user_and_project_id(self): auth = AuthPlugin() @@ -1637,8 +1825,9 @@ def test_logger_object_passed(self): response = {uuid.uuid4().hex: uuid.uuid4().hex} - self.stub_url('GET', json=response, - headers={'Content-Type': 'application/json'}) + self.stub_url( + 'GET', json=response, headers={'Content-Type': 'application/json'} + ) resp = adpt.get(self.TEST_URL, logger=logger) @@ -1654,10 +1843,12 @@ def test_logger_object_passed(self): def test_unknown_connection_error(self): self.stub_url('GET', exc=requests.exceptions.RequestException) - self.assertRaises(exceptions.UnknownConnectionError, - client_session.Session().request, - self.TEST_URL, - 'GET') + self.assertRaises( + exceptions.UnknownConnectionError, + client_session.Session().request, + self.TEST_URL, + 'GET', + ) def test_additional_headers(self): session_key = uuid.uuid4().hex @@ -1672,9 +1863,11 @@ def test_additional_headers(self): self.requests_mock.get(url, text=text) sess = client_session.Session( - additional_headers={session_key: session_val}) - adap = adapter.Adapter(session=sess, - additional_headers={adapter_key: adapter_val}) + additional_headers={session_key: session_val} + ) + adap = adapter.Adapter( + session=sess, additional_headers={adapter_key: adapter_val} + ) resp = adap.get(url, headers={request_key: request_val}) request = self.requests_mock.last_request @@ -1697,23 +1890,26 @@ def test_additional_headers_overrides(self): adap = adapter.Adapter(session=sess) adap.get(url) - self.assertEqual(session_val, - self.requests_mock.last_request.headers[header]) + self.assertEqual( + session_val, self.requests_mock.last_request.headers[header] + ) adap.additional_headers[header] = adapter_val adap.get(url) - self.assertEqual(adapter_val, - self.requests_mock.last_request.headers[header]) + self.assertEqual( + adapter_val, self.requests_mock.last_request.headers[header] + ) adap.get(url, headers={header: request_val}) - self.assertEqual(request_val, - self.requests_mock.last_request.headers[header]) + self.assertEqual( + request_val, self.requests_mock.last_request.headers[header] + ) def test_adapter_user_agent_session_adapter(self): sess = client_session.Session(app_name='ksatest', app_version='1.2.3') - adap = adapter.Adapter(client_name='testclient', - client_version='4.5.6', - session=sess) + adap = adapter.Adapter( + client_name='testclient', client_version='4.5.6', session=sess + ) url = 'http://keystone.test.com' self.requests_mock.get(url) @@ -1721,13 +1917,13 @@ def test_adapter_user_agent_session_adapter(self): adap.get(url) agent = 'ksatest/1.2.3 testclient/4.5.6' - self.assertEqual(agent + ' ' + client_session.DEFAULT_USER_AGENT, - self.requests_mock.last_request.headers['User-Agent']) + self.assertEqual( + agent + ' ' + client_session.DEFAULT_USER_AGENT, + self.requests_mock.last_request.headers['User-Agent'], + ) def test_adapter_user_agent_session_version_on_adapter(self): - class TestAdapter(adapter.Adapter): - client_name = 'testclient' client_version = '4.5.6' @@ -1740,14 +1936,16 @@ class TestAdapter(adapter.Adapter): adap.get(url) agent = 'ksatest/1.2.3 testclient/4.5.6' - self.assertEqual(agent + ' ' + client_session.DEFAULT_USER_AGENT, - self.requests_mock.last_request.headers['User-Agent']) + self.assertEqual( + agent + ' ' + client_session.DEFAULT_USER_AGENT, + self.requests_mock.last_request.headers['User-Agent'], + ) def test_adapter_user_agent_session_adapter_no_app_version(self): sess = client_session.Session(app_name='ksatest') - adap = adapter.Adapter(client_name='testclient', - client_version='4.5.6', - session=sess) + adap = adapter.Adapter( + client_name='testclient', client_version='4.5.6', session=sess + ) url = 'http://keystone.test.com' self.requests_mock.get(url) @@ -1755,8 +1953,10 @@ def test_adapter_user_agent_session_adapter_no_app_version(self): adap.get(url) agent = 'ksatest testclient/4.5.6' - self.assertEqual(agent + ' ' + client_session.DEFAULT_USER_AGENT, - self.requests_mock.last_request.headers['User-Agent']) + self.assertEqual( + agent + ' ' + client_session.DEFAULT_USER_AGENT, + self.requests_mock.last_request.headers['User-Agent'], + ) def test_adapter_user_agent_session_adapter_no_client_version(self): sess = client_session.Session(app_name='ksatest', app_version='1.2.3') @@ -1768,17 +1968,20 @@ def test_adapter_user_agent_session_adapter_no_client_version(self): adap.get(url) agent = 'ksatest/1.2.3 testclient' - self.assertEqual(agent + ' ' + client_session.DEFAULT_USER_AGENT, - self.requests_mock.last_request.headers['User-Agent']) + self.assertEqual( + agent + ' ' + client_session.DEFAULT_USER_AGENT, + self.requests_mock.last_request.headers['User-Agent'], + ) def test_adapter_user_agent_session_adapter_additional(self): - sess = client_session.Session(app_name='ksatest', - app_version='1.2.3', - additional_user_agent=[('one', '1.1.1'), - ('two', '2.2.2')]) - adap = adapter.Adapter(client_name='testclient', - client_version='4.5.6', - session=sess) + sess = client_session.Session( + app_name='ksatest', + app_version='1.2.3', + additional_user_agent=[('one', '1.1.1'), ('two', '2.2.2')], + ) + adap = adapter.Adapter( + client_name='testclient', client_version='4.5.6', session=sess + ) url = 'http://keystone.test.com' self.requests_mock.get(url) @@ -1786,8 +1989,10 @@ def test_adapter_user_agent_session_adapter_additional(self): adap.get(url) agent = 'ksatest/1.2.3 testclient/4.5.6 one/1.1.1 two/2.2.2' - self.assertEqual(agent + ' ' + client_session.DEFAULT_USER_AGENT, - self.requests_mock.last_request.headers['User-Agent']) + self.assertEqual( + agent + ' ' + client_session.DEFAULT_USER_AGENT, + self.requests_mock.last_request.headers['User-Agent'], + ) def test_adapter_user_agent_session(self): sess = client_session.Session(app_name='ksatest', app_version='1.2.3') @@ -1799,14 +2004,16 @@ def test_adapter_user_agent_session(self): adap.get(url) agent = 'ksatest/1.2.3' - self.assertEqual(agent + ' ' + client_session.DEFAULT_USER_AGENT, - self.requests_mock.last_request.headers['User-Agent']) + self.assertEqual( + agent + ' ' + client_session.DEFAULT_USER_AGENT, + self.requests_mock.last_request.headers['User-Agent'], + ) def test_adapter_user_agent_adapter(self): sess = client_session.Session() - adap = adapter.Adapter(client_name='testclient', - client_version='4.5.6', - session=sess) + adap = adapter.Adapter( + client_name='testclient', client_version='4.5.6', session=sess + ) url = 'http://keystone.test.com' self.requests_mock.get(url) @@ -1814,26 +2021,31 @@ def test_adapter_user_agent_adapter(self): adap.get(url) agent = 'testclient/4.5.6' - self.assertEqual(agent + ' ' + client_session.DEFAULT_USER_AGENT, - self.requests_mock.last_request.headers['User-Agent']) + self.assertEqual( + agent + ' ' + client_session.DEFAULT_USER_AGENT, + self.requests_mock.last_request.headers['User-Agent'], + ) def test_adapter_user_agent_session_override(self): - sess = client_session.Session(app_name='ksatest', - app_version='1.2.3', - additional_user_agent=[('one', '1.1.1'), - ('two', '2.2.2')]) - adap = adapter.Adapter(client_name='testclient', - client_version='4.5.6', - session=sess) + sess = client_session.Session( + app_name='ksatest', + app_version='1.2.3', + additional_user_agent=[('one', '1.1.1'), ('two', '2.2.2')], + ) + adap = adapter.Adapter( + client_name='testclient', client_version='4.5.6', session=sess + ) url = 'http://keystone.test.com' self.requests_mock.get(url) - override_user_agent = '%s/%s' % (uuid.uuid4().hex, uuid.uuid4().hex) + override_user_agent = f'{uuid.uuid4().hex}/{uuid.uuid4().hex}' adap.get(url, user_agent=override_user_agent) - self.assertEqual(override_user_agent, - self.requests_mock.last_request.headers['User-Agent']) + self.assertEqual( + override_user_agent, + self.requests_mock.last_request.headers['User-Agent'], + ) def test_nested_adapters(self): text = uuid.uuid4().hex @@ -1845,11 +2057,10 @@ def test_nested_adapters(self): auth.ENDPOINT = url auth.TOKEN = token - adap1 = adapter.Adapter(session=sess, - interface='public') - adap2 = adapter.Adapter(session=adap1, - service_type='identity', - auth=auth) + adap1 = adapter.Adapter(session=sess, interface='public') + adap2 = adapter.Adapter( + session=adap1, service_type='identity', auth=auth + ) self.requests_mock.get(url + '/test', text=text) @@ -1871,9 +2082,14 @@ def test_default_microversion(self): def validate(adap_kwargs, get_kwargs, exp_kwargs): with mock.patch.object(sess, 'request') as m: adapter.Adapter(sess, **adap_kwargs).get(url, **get_kwargs) - m.assert_called_once_with(url, 'GET', endpoint_filter={}, - headers={}, rate_semaphore=mock.ANY, - **exp_kwargs) + m.assert_called_once_with( + url, + 'GET', + endpoint_filter={}, + headers={}, + rate_semaphore=mock.ANY, + **exp_kwargs, + ) # No default_microversion in Adapter, no microversion in get() validate({}, {}, {}) @@ -1885,8 +2101,11 @@ def validate(adap_kwargs, get_kwargs, exp_kwargs): validate({}, {'microversion': '1.2'}, {'microversion': '1.2'}) # microversion in get() overrides default_microversion in Adapter - validate({'default_microversion': '1.2'}, {'microversion': '1.5'}, - {'microversion': '1.5'}) + validate( + {'default_microversion': '1.2'}, + {'microversion': '1.5'}, + {'microversion': '1.5'}, + ) def test_raise_exc_override(self): sess = client_session.Session() @@ -1895,9 +2114,14 @@ def test_raise_exc_override(self): def validate(adap_kwargs, get_kwargs, exp_kwargs): with mock.patch.object(sess, 'request') as m: adapter.Adapter(sess, **adap_kwargs).get(url, **get_kwargs) - m.assert_called_once_with(url, 'GET', endpoint_filter={}, - headers={}, rate_semaphore=mock.ANY, - **exp_kwargs) + m.assert_called_once_with( + url, + 'GET', + endpoint_filter={}, + headers={}, + rate_semaphore=mock.ANY, + **exp_kwargs, + ) # No raise_exc in Adapter or get() validate({}, {}, {}) @@ -1911,21 +2135,23 @@ def validate(adap_kwargs, get_kwargs, exp_kwargs): validate({}, {'raise_exc': False}, {'raise_exc': False}) # Setting in get() overrides the one in Adapter - validate({'raise_exc': True}, {'raise_exc': False}, - {'raise_exc': False}) - validate({'raise_exc': False}, {'raise_exc': True}, - {'raise_exc': True}) + validate( + {'raise_exc': True}, {'raise_exc': False}, {'raise_exc': False} + ) + validate( + {'raise_exc': False}, {'raise_exc': True}, {'raise_exc': True} + ) class TCPKeepAliveAdapterTest(utils.TestCase): - def setUp(self): - super(TCPKeepAliveAdapterTest, self).setUp() + super().setUp() self.init_poolmanager = self.patch( - client_session.requests.adapters.HTTPAdapter, - 'init_poolmanager') + client_session.requests.adapters.HTTPAdapter, 'init_poolmanager' + ) self.constructor = self.patch( - client_session.TCPKeepAliveAdapter, '__init__', lambda self: None) + client_session.TCPKeepAliveAdapter, '__init__', lambda self: None + ) def test_init_poolmanager_with_requests_lesser_than_2_4_1(self): self.patch(client_session, 'REQUESTS_VERSION', (2, 4, 0)) @@ -1940,7 +2166,8 @@ def test_init_poolmanager_with_requests_lesser_than_2_4_1(self): def test_init_poolmanager_with_basic_options(self): self.patch(client_session, 'REQUESTS_VERSION', (2, 4, 1)) socket = self.patch_socket_with_options( - ['IPPROTO_TCP', 'TCP_NODELAY', 'SOL_SOCKET', 'SO_KEEPALIVE']) + ['IPPROTO_TCP', 'TCP_NODELAY', 'SOL_SOCKET', 'SO_KEEPALIVE'] + ) given_adapter = client_session.TCPKeepAliveAdapter() # when pool manager is initialized @@ -1948,15 +2175,26 @@ def test_init_poolmanager_with_basic_options(self): # then no socket_options are given self.init_poolmanager.assert_called_once_with( - 1, 2, 3, socket_options=[ + 1, + 2, + 3, + socket_options=[ (socket.IPPROTO_TCP, socket.TCP_NODELAY, 1), - (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)]) + (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1), + ], + ) def test_init_poolmanager_with_tcp_keepidle(self): self.patch(client_session, 'REQUESTS_VERSION', (2, 4, 1)) socket = self.patch_socket_with_options( - ['IPPROTO_TCP', 'TCP_NODELAY', 'SOL_SOCKET', 'SO_KEEPALIVE', - 'TCP_KEEPIDLE']) + [ + 'IPPROTO_TCP', + 'TCP_NODELAY', + 'SOL_SOCKET', + 'SO_KEEPALIVE', + 'TCP_KEEPIDLE', + ] + ) given_adapter = client_session.TCPKeepAliveAdapter() # when pool manager is initialized @@ -1964,17 +2202,28 @@ def test_init_poolmanager_with_tcp_keepidle(self): # then socket_options are given self.init_poolmanager.assert_called_once_with( - 1, 2, 3, socket_options=[ + 1, + 2, + 3, + socket_options=[ (socket.IPPROTO_TCP, socket.TCP_NODELAY, 1), (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1), - (socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 60)]) + (socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 60), + ], + ) def test_init_poolmanager_with_tcp_keepcnt(self): self.patch(client_session, 'REQUESTS_VERSION', (2, 4, 1)) self.patch(client_session.utils, 'is_windows_linux_subsystem', False) socket = self.patch_socket_with_options( - ['IPPROTO_TCP', 'TCP_NODELAY', 'SOL_SOCKET', 'SO_KEEPALIVE', - 'TCP_KEEPCNT']) + [ + 'IPPROTO_TCP', + 'TCP_NODELAY', + 'SOL_SOCKET', + 'SO_KEEPALIVE', + 'TCP_KEEPCNT', + ] + ) given_adapter = client_session.TCPKeepAliveAdapter() # when pool manager is initialized @@ -1982,17 +2231,28 @@ def test_init_poolmanager_with_tcp_keepcnt(self): # then socket_options are given self.init_poolmanager.assert_called_once_with( - 1, 2, 3, socket_options=[ + 1, + 2, + 3, + socket_options=[ (socket.IPPROTO_TCP, socket.TCP_NODELAY, 1), (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1), - (socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 4)]) + (socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 4), + ], + ) def test_init_poolmanager_with_tcp_keepcnt_on_windows(self): self.patch(client_session, 'REQUESTS_VERSION', (2, 4, 1)) self.patch(client_session.utils, 'is_windows_linux_subsystem', True) socket = self.patch_socket_with_options( - ['IPPROTO_TCP', 'TCP_NODELAY', 'SOL_SOCKET', 'SO_KEEPALIVE', - 'TCP_KEEPCNT']) + [ + 'IPPROTO_TCP', + 'TCP_NODELAY', + 'SOL_SOCKET', + 'SO_KEEPALIVE', + 'TCP_KEEPCNT', + ] + ) given_adapter = client_session.TCPKeepAliveAdapter() # when pool manager is initialized @@ -2000,15 +2260,26 @@ def test_init_poolmanager_with_tcp_keepcnt_on_windows(self): # then socket_options are given self.init_poolmanager.assert_called_once_with( - 1, 2, 3, socket_options=[ + 1, + 2, + 3, + socket_options=[ (socket.IPPROTO_TCP, socket.TCP_NODELAY, 1), - (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)]) + (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1), + ], + ) def test_init_poolmanager_with_tcp_keepintvl(self): self.patch(client_session, 'REQUESTS_VERSION', (2, 4, 1)) socket = self.patch_socket_with_options( - ['IPPROTO_TCP', 'TCP_NODELAY', 'SOL_SOCKET', 'SO_KEEPALIVE', - 'TCP_KEEPINTVL']) + [ + 'IPPROTO_TCP', + 'TCP_NODELAY', + 'SOL_SOCKET', + 'SO_KEEPALIVE', + 'TCP_KEEPINTVL', + ] + ) given_adapter = client_session.TCPKeepAliveAdapter() # when pool manager is initialized @@ -2016,10 +2287,15 @@ def test_init_poolmanager_with_tcp_keepintvl(self): # then socket_options are given self.init_poolmanager.assert_called_once_with( - 1, 2, 3, socket_options=[ + 1, + 2, + 3, + socket_options=[ (socket.IPPROTO_TCP, socket.TCP_NODELAY, 1), (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1), - (socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 15)]) + (socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 15), + ], + ) def test_init_poolmanager_with_given_optionsl(self): self.patch(client_session, 'REQUESTS_VERSION', (2, 4, 1)) @@ -2031,13 +2307,17 @@ def test_init_poolmanager_with_given_optionsl(self): # then socket_options are given self.init_poolmanager.assert_called_once_with( - 1, 2, 3, socket_options=given_options) + 1, 2, 3, socket_options=given_options + ) def patch_socket_with_options(self, option_names): # to mock socket module with exactly the attributes I want I create # a class with that attributes - socket = type('socket', (object,), - {name: 'socket.' + name for name in option_names}) + socket = type( + 'socket', + (object,), + {name: 'socket.' + name for name in option_names}, + ) return self.patch(client_session, 'socket', socket) def patch(self, target, name, *args, **kwargs): diff --git a/keystoneauth1/tests/unit/test_token_endpoint.py b/keystoneauth1/tests/unit/test_token_endpoint.py index ff28c051..13cd3a11 100644 --- a/keystoneauth1/tests/unit/test_token_endpoint.py +++ b/keystoneauth1/tests/unit/test_token_endpoint.py @@ -19,7 +19,6 @@ class TokenEndpointTest(utils.TestCase): - TEST_TOKEN = 'aToken' TEST_URL = 'http://server/prefix' @@ -39,9 +38,9 @@ def test_basic_endpoint_case(self): a = token_endpoint.Token(self.TEST_URL, self.TEST_TOKEN) s = session.Session(auth=a) - data = s.get('/p', - authenticated=True, - endpoint_filter={'service': 'identity'}) + data = s.get( + '/p', authenticated=True, endpoint_filter={'service': 'identity'} + ) self.assertEqual(self.TEST_URL, a.get_endpoint(s)) self.assertEqual('body', data.text) @@ -57,7 +56,6 @@ def test_token_endpoint_user_id(self): class AdminTokenTest(utils.TestCase): - def test_token_endpoint_options(self): opt_names = [opt.name for opt in loader.AdminToken().get_options()] @@ -68,8 +66,10 @@ def test_token_endpoint_options(self): def test_token_endpoint_deprecated_options(self): endpoint_opt = [ - opt for opt in loader.AdminToken().get_options() - if opt.name == 'endpoint'][0] + opt + for opt in loader.AdminToken().get_options() + if opt.name == 'endpoint' + ][0] opt_names = [opt.name for opt in endpoint_opt.deprecated] diff --git a/keystoneauth1/tests/unit/test_utils.py b/keystoneauth1/tests/unit/test_utils.py index 8ec9edc5..daba95ae 100644 --- a/keystoneauth1/tests/unit/test_utils.py +++ b/keystoneauth1/tests/unit/test_utils.py @@ -16,7 +16,8 @@ class UtilsTests(testtools.TestCase): - def test_get_logger(self): - self.assertEqual('keystoneauth.tests.unit.test_utils', - _utils.get_logger(__name__).name) + self.assertEqual( + 'keystoneauth.tests.unit.test_utils', + _utils.get_logger(__name__).name, + ) diff --git a/keystoneauth1/tests/unit/utils.py b/keystoneauth1/tests/unit/utils.py index 8c7404a4..268f02e3 100644 --- a/keystoneauth1/tests/unit/utils.py +++ b/keystoneauth1/tests/unit/utils.py @@ -23,7 +23,6 @@ class TestCase(testtools.TestCase): - TEST_DOMAIN_ID = uuid.uuid4().hex TEST_DOMAIN_NAME = uuid.uuid4().hex TEST_GROUP_ID = uuid.uuid4().hex @@ -39,7 +38,7 @@ class TestCase(testtools.TestCase): TEST_ROOT_URL = 'http://127.0.0.1:5000/' def setUp(self): - super(TestCase, self).setUp() + super().setUp() self.logger = self.useFixture(fixtures.FakeLogger(level=logging.DEBUG)) fixtures.MockPatchObject(time, 'time', lambda: 1234) @@ -83,7 +82,7 @@ def assertQueryStringIs(self, qs=''): expected = urllib.parse.parse_qs(qs, keep_blank_values=True) parts = urllib.parse.urlparse(self.requests_mock.last_request.url) querystring = urllib.parse.parse_qs( - parts.query, keep_blank_values=True, + parts.query, keep_blank_values=True ) self.assertEqual(expected, querystring) @@ -129,7 +128,7 @@ class TestResponse(requests.Response): def __init__(self, data): self._text = None - super(TestResponse, self).__init__() + super().__init__() if isinstance(data, dict): self.status_code = data.get('status_code', 200) headers = data.get('headers') diff --git a/keystoneauth1/token_endpoint.py b/keystoneauth1/token_endpoint.py index 9c90eb49..1b688e9c 100644 --- a/keystoneauth1/token_endpoint.py +++ b/keystoneauth1/token_endpoint.py @@ -21,7 +21,7 @@ class Token(plugin.BaseAuthPlugin): """ def __init__(self, endpoint, token): - super(Token, self).__init__() + super().__init__() # NOTE(jamielennox): endpoint is reserved for when plugins # can be used to provide that information self.endpoint = endpoint @@ -30,9 +30,9 @@ def __init__(self, endpoint, token): def get_token(self, session): return self.token - def get_endpoint_data(self, session, - endpoint_override=None, - discover_versions=True, **kwargs): + def get_endpoint_data( + self, session, endpoint_override=None, discover_versions=True, **kwargs + ): """Return a valid endpoint data for a the service. :param session: A session object that can be used for communication. @@ -53,9 +53,12 @@ def get_endpoint_data(self, session, :return: Valid EndpointData or None if not available. :rtype: `keystoneauth1.discover.EndpointData` or None """ - return super(Token, self).get_endpoint_data( - session, endpoint_override=endpoint_override or self.endpoint, - discover_versions=discover_versions, **kwargs) + return super().get_endpoint_data( + session, + endpoint_override=endpoint_override or self.endpoint, + discover_versions=discover_versions, + **kwargs, + ) def get_endpoint(self, session, **kwargs): """Return the supplied endpoint. diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py index 75faf00e..a9f78e69 100644 --- a/releasenotes/source/conf.py +++ b/releasenotes/source/conf.py @@ -5,10 +5,7 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = [ - 'openstackdocstheme', - 'reno.sphinxext', -] +extensions = ['openstackdocstheme', 'reno.sphinxext'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -64,7 +61,7 @@ 'keystoneauth Release Notes Documentation', 'Keystone Developers', 'manual', - ), + ) ] diff --git a/setup.py b/setup.py index cd35c3c3..481505b0 100644 --- a/setup.py +++ b/setup.py @@ -15,6 +15,4 @@ import setuptools -setuptools.setup( - setup_requires=['pbr>=2.0.0'], - pbr=True) +setuptools.setup(setup_requires=['pbr>=2.0.0'], pbr=True) diff --git a/tox.ini b/tox.ini index ec72534b..64c707c6 100644 --- a/tox.ini +++ b/tox.ini @@ -95,9 +95,11 @@ commands = # D107: Missing docstring in __init__ # D203: 1 blank line required before class docstring (deprecated in pep257) # D401: First line should be in imperative mood; try rephrasing -# W503 line break before binary operator -# W504 line break after binary operator -ignore = D100,D101,D102,D103,D104,D107,D203,D401,W503,W504 +# E501: line too long +# E203: whitespace before ':' +# W503: line break before binary operator +# W504: line break after binary operator +ignore = D100,D101,D102,D103,D104,D107,D203,D401,E203,E501,W503,W504 # H106: Don’t put vim configuration in source files # H203: Use assertIs(Not)None to check for None enable-extensions=H106,H203