diff --git a/keystoneauth1/adapter.py b/keystoneauth1/adapter.py index 13ec12e6..dd152476 100644 --- a/keystoneauth1/adapter.py +++ b/keystoneauth1/adapter.py @@ -267,6 +267,29 @@ class Adapter(object): return self.session.get_endpoint_data(auth or self.auth, **kwargs) + def get_all_version_data( + self, + interface='public', + region_name=None): + """Get data about all versions of a service. + + :param interface: + Type of endpoint to get version data for. Can be a single value + or a list of values. A value of None indicates that all interfaces + should be queried. (optional, defaults to public) + :param string region_name: + Region of endpoints to get version data for. A valueof None + indicates that all regions should be queried. (optional, defaults + to None) + :returns: A dictionary keyed by region_name with values containing + dictionaries keyed by interface with values being a list of + :class:`~keystoneauth1.discover.VersionData`. + """ + return self.session.get_all_version_data( + interface=interface, + region_name=region_name, + 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. diff --git a/keystoneauth1/identity/base.py b/keystoneauth1/identity/base.py index 81498acd..26fd4966 100644 --- a/keystoneauth1/identity/base.py +++ b/keystoneauth1/identity/base.py @@ -509,7 +509,8 @@ class BaseIdentityPlugin(plugin.BaseAuthPlugin): return data.api_version def get_all_version_data(self, session, interface='public', - region_name=None, **kwargs): + 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. @@ -522,6 +523,9 @@ class BaseIdentityPlugin(plugin.BaseAuthPlugin): Region of endpoints to get version data for. A valueof None indicates that all regions should be queried. (optional, defaults to None) + :param string service_type: + Limit the version data to a single service. (optional, defaults + to None) :returns: A dictionary keyed by region_name with values containing dictionaries keyed by interface with values being a list of :class:`~keystoneauth1.discover.VersionData`. @@ -530,11 +534,16 @@ class BaseIdentityPlugin(plugin.BaseAuthPlugin): catalog = self.get_access(session).service_catalog version_data = {} endpoints_data = catalog.get_endpoints_data( - interface=interface, region_name=region_name) + interface=interface, + region_name=region_name, + service_type=service_type, + ) + + 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) - for service_type, services in endpoints_data.items(): - if service_types.is_known(service_type): - service_type = service_types.get_service_type(service_type) for service in services: versions = service.get_all_version_string_data( session=session, @@ -548,7 +557,7 @@ class BaseIdentityPlugin(plugin.BaseAuthPlugin): interface = service.interface.rstrip('URL') if interface not in regions: regions[interface] = {} - regions[interface][service_type] = versions + regions[interface][endpoint_service_type] = versions return version_data diff --git a/keystoneauth1/session.py b/keystoneauth1/session.py index 77bc8973..2e3e8874 100644 --- a/keystoneauth1/session.py +++ b/keystoneauth1/session.py @@ -1146,7 +1146,8 @@ class Session(object): return auth.get_api_major_version(self, **kwargs) def get_all_version_data(self, auth=None, interface='public', - region_name=None, **kwargs): + region_name=None, service_type=None, + **kwargs): """Get version data for all services in the catalog. :param auth: @@ -1161,13 +1162,20 @@ class Session(object): Region of endpoints to get version data for. A valueof None indicates that all regions should be queried. (optional, defaults to None) + :param string service_type: + Limit the version data to a single service. (optional, defaults + to None) :returns: A dictionary keyed by region_name with values containing dictionaries keyed by interface with values being a list of `~keystoneauth1.discover.VersionData`. """ auth = self._auth_required(auth, 'determine endpoint URL') return auth.get_all_version_data( - self, interface=interface, region_name=region_name, **kwargs) + self, + interface=interface, + region_name=region_name, + service_type=service_type, + **kwargs) def get_auth_connection_params(self, auth=None, **kwargs): """Return auth connection params as provided by the auth plugin. diff --git a/keystoneauth1/tests/unit/identity/test_identity_common.py b/keystoneauth1/tests/unit/identity/test_identity_common.py index 9a7c5fb9..40a010e0 100644 --- a/keystoneauth1/tests/unit/identity/test_identity_common.py +++ b/keystoneauth1/tests/unit/identity/test_identity_common.py @@ -19,6 +19,7 @@ from six.moves import urllib from keystoneauth1 import _utils from keystoneauth1 import access +from keystoneauth1 import adapter from keystoneauth1 import discover from keystoneauth1 import exceptions from keystoneauth1 import fixture @@ -865,6 +866,148 @@ class CommonIdentityTests(object): } }, 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.1', + min_version='2.1', max_version='2.35') + + self.stub_url( + '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' + }], + } + } + }, 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.1', + min_version='2.1', max_version='2.35') + + self.stub_url( + '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' + }], + } + } + }, 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') + + # 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') + + self.stub_url( + 'GET', [], + base_url=self.TEST_VOLUME.unversioned.public + '/', + 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' + }], + } + } + }, data) + def test_endpoint_data_no_version_no_discovery(self): a = self.create_auth_plugin() s = session.Session(auth=a) diff --git a/releasenotes/notes/filter-versions-service-type-763af68092344b7a.yaml b/releasenotes/notes/filter-versions-service-type-763af68092344b7a.yaml new file mode 100644 index 00000000..5d7adee9 --- /dev/null +++ b/releasenotes/notes/filter-versions-service-type-763af68092344b7a.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + Added ability to filter the results of ``get_all_version_data`` by + service-type. + - | + Added ``get_all_version_data`` to ``adapter.Adapter`` that uses the + adapter's ``service_type`` to filter the version data fetched.