def get_endpoint(self, session, service_type=None, interface=None,
                     region_name=None, service_name=None, 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
        the session and kwargs.

        :param session: A session object that can be used for communication.
        :type session: keystoneclient.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 string interface: The exposure of the endpoint. Should be
                                 `public`, `internal`, `admin`, or `auth`.
                                 `auth` is special here to use the `auth_url`
                                 rather than a URL extracted from the service
                                 catalog. 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 tuple version: The minimum version number required for this
                              endpoint. (optional)

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

        :return: A valid endpoint URL or None if not available.
        :rtype: string or None
        """
        # 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 base.AUTH_INTERFACE:
            url = self.auth_url
            service_type = service_type or 'identity'

        else:
            if not service_type:
                LOG.warning(_LW(
                    'Plugin cannot return an endpoint without knowing the '
                    'service type that is required. Add service_type to '
                    'endpoint filtering data.'))
                return None

            if not interface:
                interface = 'public'

            service_catalog = self.get_access(session).service_catalog
            url = service_catalog.url_for(service_type=service_type,
                                          endpoint_type=interface,
                                          region_name=region_name,
                                          service_name=service_name)

        if not version:
            # NOTE(jamielennox): This may not be the best thing to default to
            # but is here for backwards compatibility. It may be worth
            # defaulting to the most recent version.
            return url

        # NOTE(jamielennox): For backwards compatibility people might have a
        # versioned endpoint in their catalog even though they want to use
        # other endpoint versions. So we support a list of client defined
        # situations where we can strip the version component from a URL before
        # doing discovery.
        hacked_url = _discover.get_catalog_discover_hack(service_type, url)

        try:
            disc = self.get_discovery(session, hacked_url, authenticated=False)
        except (exceptions.DiscoveryFailure,
                exceptions.HTTPError,
                exceptions.ConnectionError):
            # NOTE(jamielennox): Again if we can't contact the server we fall
            # back to just returning the URL from the catalog. This may not be
            # the best default but we need it for now.
            LOG.warning(_LW(
                'Failed to contact the endpoint at %s for discovery. Fallback '
                'to using that endpoint as the base url.'),
                url)
        else:
            url = disc.url_for(version)

        return url
    def get_endpoint(self, session, service_type=None, interface=None,
                     region_name=None, service_name=None, 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
        the session and kwargs.

        :param session: A session object that can be used for communication.
        :type session: keystoneclient.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 string interface: The exposure of the endpoint. Should be
                                 `public`, `internal`, `admin`, or `auth`.
                                 `auth` is special here to use the `auth_url`
                                 rather than a URL extracted from the service
                                 catalog. 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 tuple version: The minimum version number required for this
                              endpoint. (optional)

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

        :return: A valid endpoint URL or None if not available.
        :rtype: string or None
        """
        # 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 base.AUTH_INTERFACE:
            url = self.auth_url
            service_type = service_type or 'identity'

        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

            if not interface:
                interface = 'public'

            service_catalog = self.get_access(session).service_catalog
            url = service_catalog.url_for(service_type=service_type,
                                          endpoint_type=interface,
                                          region_name=region_name,
                                          service_name=service_name)

        if not version:
            # NOTE(jamielennox): This may not be the best thing to default to
            # but is here for backwards compatibility. It may be worth
            # defaulting to the most recent version.
            return url

        # NOTE(jamielennox): For backwards compatibility people might have a
        # versioned endpoint in their catalog even though they want to use
        # other endpoint versions. So we support a list of client defined
        # situations where we can strip the version component from a URL before
        # doing discovery.
        hacked_url = _discover.get_catalog_discover_hack(service_type, url)

        try:
            disc = self.get_discovery(session, hacked_url, authenticated=False)
        except (exceptions.DiscoveryFailure,
                exceptions.HTTPError,
                exceptions.ConnectionError):
            # NOTE(jamielennox): Again if we can't contact the server we fall
            # back to just returning the URL from the catalog. This may not be
            # the best default but we need it for now.
            LOG.warning(
                'Failed to contact the endpoint at %s for discovery. Fallback '
                'to using that endpoint as the base url.', url)
        else:
            url = disc.url_for(version)

        return url