コード例 #1
0
    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.
        :type session: keystoneauth1.session.Session
        :param str endpoint_override: URL to use for version discovery.
        :param bool discover_versions: Whether to get version metadata from
                                       the version discovery document even
                                       if it major api version info can be
                                       inferred from the url.
                                       (optional, defaults to True)
        :param kwargs: Ignored.

        :raises keystoneauth1.exceptions.http.HttpError: An error from an
                                                         invalid HTTP response.

        :return: Valid EndpointData or None if not available.
        :rtype: `keystoneauth1.discover.EndpointData` or None
        """
        if not endpoint_override:
            return None
        endpoint_data = discover.EndpointData(catalog_url=endpoint_override)

        if endpoint_data.api_version and not discover_versions:
            return endpoint_data

        return endpoint_data.get_versioned_data(
            session, cache=self._discovery_cache,
            discover_versions=discover_versions)
コード例 #2
0
    def endpoint_data_for(self, **kwargs):
        kwargs.setdefault('interface', 'public')
        kwargs.setdefault('service_type', None)

        if kwargs['service_type'] == 'object-store':
            return discover.EndpointData(
                service_type='object-store',
                service_name='swift',
                interface=kwargs['interface'],
                region_name='default',
                catalog_url=self.storage_url,
            )

        # Although our "catalog" includes an identity entry, nothing that uses
        # url_for() (including `openstack endpoint list`) will know what to do
        # with it. Better to just raise the exception, cribbing error messages
        # from keystoneauth1/access/service_catalog.py

        if 'service_name' in kwargs and 'region_name' in kwargs:
            msg = ('%(interface)s endpoint for %(service_type)s service '
                   'named %(service_name)s in %(region_name)s region not '
                   'found' % kwargs)
        elif 'service_name' in kwargs:
            msg = ('%(interface)s endpoint for %(service_type)s service '
                   'named %(service_name)s not found' % kwargs)
        elif 'region_name' in kwargs:
            msg = ('%(interface)s endpoint for %(service_type)s service '
                   'in %(region_name)s region not found' % kwargs)
        else:
            msg = ('%(interface)s endpoint for %(service_type)s service '
                   'not found' % kwargs)

        raise exceptions.EndpointNotFound(msg)
コード例 #3
0
 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()
     # Duplicate 'url1' in here to validate the cache behavior
     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')
     # 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')])
コード例 #4
0
 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))
     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}')
     # Works with str()
     self.assertEqual(exp, str(epd))
     # Works with implicit stringification
     self.assertEqual(exp, "%s" % epd)
コード例 #5
0
    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
        the specified type (or all) and region (or all) and service name.

        If there is no name in the service catalog the service_name check will
        be skipped.  This allows compatibility with services that existed
        before the name was available in the catalog.

        Valid interface types: `public` or `publicURL`,
                               `internal` or `internalURL`,
                               `admin` or 'adminURL`

        :param string service_type: Service type of the endpoint.
        :param interface: Type of endpoint. Can be a single value or a list
                          of values. If it's a list of values, they will be
                          looked for in order of preference.
        :param string region_name: Region of the endpoint.
        :param string service_name: The assigned name of the service.
        :param string service_id: The identifier of a service.
        :param string endpoint_id: The identifier of an endpoint.

        :returns: a list of matching EndpointData objects
        :rtype: list(`keystoneauth1.discover.EndpointData`)

        :returns: a dict, keyed by service_type, of lists of EndpointData
        """
        interfaces = self._get_interface_list(interface)

        matching_endpoints = {}

        for service in self.normalize_catalog():

            if service_type and service_type != service['type']:
                continue

            if (service_name and service['name']
                    and service_name != service['name']):
                continue

            if (service_id and service['id'] and service_id != service['id']):
                continue

            matching_endpoints.setdefault(service['type'], [])

            for endpoint in service.get('endpoints', []):
                if interfaces and endpoint['interface'] not in interfaces:
                    continue
                if region_name and region_name != endpoint['region_name']:
                    continue
                if endpoint_id and endpoint_id != endpoint['id']:
                    continue
                if not endpoint['url']:
                    continue

                matching_endpoints[service['type']].append(
                    discover.EndpointData(
                        catalog_url=endpoint['url'],
                        service_type=service['type'],
                        service_name=service['name'],
                        service_id=service['id'],
                        interface=endpoint['interface'],
                        region_name=endpoint['region_name'],
                        endpoint_id=endpoint['id'],
                        raw_endpoint=endpoint['raw_endpoint']))

        if not interfaces:
            return matching_endpoints

        ret = {}
        for service_type, endpoints in matching_endpoints.items():
            if not endpoints:
                ret[service_type] = []
                continue
            matches_by_interface = {}
            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]
            ret[service_type] = matches_by_interface[best_interface]

        return ret
コード例 #6
0
    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
        the session and kwargs.

        version, min_version and max_version can all be given either as a
        string or a tuple.

        Valid interface types: `public` or `publicURL`,
                               `internal` or `internalURL`,
                               `admin` or 'adminURL`

        :param session: A session object that can be used for communication.
        :type session: keystoneauth1.session.Session
        :param string service_type: The type of service to lookup the endpoint
                                    for. This plugin will return None (failure)
                                    if service_type is not provided.
        :param interface: Type of endpoint. Can be a single value or a list
                          of values. If it's a list of values, they will be
                          looked for in order of preference. Can also be
                          `keystoneauth1.plugin.AUTH_INTERFACE` to indicate
                          that the auth_url should be used instead of the
                          value in the catalog. (optional, defaults to public)
        :param string region_name: The region the endpoint should exist in.
                                   (optional)
        :param string service_name: The name of the service in the catalog.
                                   (optional)
        :param dict allow: Extra filters to pass when discovering API
                           versions. (optional)
        :param bool allow_version_hack: Allow keystoneauth to hack up catalog
                                        URLS to support older schemes.
                                        (optional, default True)
        :param bool discover_versions: Whether to get version metadata from
                                       the version discovery document even
                                       if it's not neccessary to fulfill the
                                       major version request. (optional,
                                       defaults to True)
        :param bool skip_discovery: Whether to skip version discovery even
                                    if a version has been given. This is useful
                                    if endpoint_override or similar has been
                                    given and grabbing additional information
                                    about the endpoint is not useful.
        :param min_version: The minimum version that is acceptable. Mutually
                            exclusive with version. If min_version is given
                            with no max_version it is as if max version is
                            'latest'. (optional)
        :param max_version: The maximum version that is acceptable. Mutually
                            exclusive with version. If min_version is given
                            with no max_version it is as if max version is
                            'latest'. (optional)
        :param str endpoint_override: URL to use instead of looking in the
                                      catalog. Catalog lookup will be skipped,
                                      but version discovery will be run.
                                      Sets allow_version_hack to False
                                      (optional)
        :param kwargs: Ignored.

        :raises keystoneauth1.exceptions.http.HttpError: An error from an
                                                         invalid HTTP response.

        :return: Valid EndpointData or None if not available.
        :rtype: `keystoneauth1.discover.EndpointData` or None
        """
        allow = allow or {}

        min_version, max_version = discover._normalize_version_args(
            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
        # are asking for the auth endpoint it means that there is no catalog to
        # query however we still need to support asking for a specific version
        # of the auth_url for generic plugins.
        if interface is plugin.AUTH_INTERFACE:
            endpoint_data = discover.EndpointData(
                service_url=self.auth_url,
                service_type=service_type or 'identity')
            project_id = None
        elif endpoint_override:
            # TODO(mordred) Make a code path that will look for a
            #               matching entry in the catalog if the catalog
            #               exists and fill in the interface, region_name, etc.
            #               For now, just use any information the use has
            #               provided.
            endpoint_data = discover.EndpointData(
                service_url=endpoint_override,
                catalog_url=endpoint_override,
                interface=interface,
                region_name=region_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
            # reasons.
            allow_version_hack = False
            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.')
                return None

            # It's possible for things higher in the stack, because of
            # defaults, to explicitly pass None.
            if not interface:
                interface = 'public'

            service_catalog = self.get_access(session).service_catalog
            project_id = self.get_project_id(session)
            # NOTE(mordred): service_catalog.url_data_for raises if it can't
            # find a match, so this will always be a valid object.
            endpoint_data = service_catalog.endpoint_data_for(
                service_type=service_type,
                interface=interface,
                region_name=region_name,
                service_name=service_name)
            if not endpoint_data:
                return None

        if skip_discovery:
            return endpoint_data

        try:
            return endpoint_data.get_versioned_data(
                session,
                project_id=project_id,
                min_version=min_version,
                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):
            # If a version was requested, we didn't find it, return
            # None.
            if max_version or min_version:
                return None
            # If one wasn't, then the endpoint_data we already have
            # should be fine
            return endpoint_data
コード例 #7
0
 def test_project_id_int_fallback(self):
     bad_url = "https://compute.example.com/v2/123456"
     epd = discover.EndpointData(catalog_url=bad_url)
     self.assertEqual((2, 0), epd.api_version)