Merge "Use client credentials to retrieve service list"
This commit is contained in:
commit
cba49f38fe
@ -109,21 +109,24 @@ class KeystoneAction(base.OpenStackAction):
|
||||
|
||||
LOG.debug("Keystone action security context: %s" % ctx)
|
||||
|
||||
# TODO(akovi) cacert is deprecated in favor of session
|
||||
# TODO(akovi) this piece of code should be refactored
|
||||
# TODO(akovi) to follow the new guide lines
|
||||
kwargs = {
|
||||
'token': ctx.auth_token,
|
||||
'auth_url': CONF.keystone_authtoken.auth_uri,
|
||||
'auth_url': ctx.auth_uri,
|
||||
'project_id': ctx.project_id,
|
||||
'cacert': CONF.keystone_authtoken.cafile,
|
||||
'cacert': ctx.auth_cacert,
|
||||
}
|
||||
|
||||
# In case of trust-scoped token explicitly pass endpoint parameter.
|
||||
if (ctx.is_trust_scoped
|
||||
or keystone_utils.is_token_trust_scoped(ctx.auth_token)):
|
||||
kwargs['endpoint'] = CONF.keystone_authtoken.auth_uri
|
||||
kwargs['endpoint'] = ctx.auth_uri
|
||||
|
||||
client = self._client_class(**kwargs)
|
||||
|
||||
client.management_url = CONF.keystone_authtoken.auth_uri
|
||||
client.management_url = ctx.auth_uri
|
||||
|
||||
return client
|
||||
|
||||
@ -214,7 +217,7 @@ class NeutronAction(base.OpenStackAction):
|
||||
endpoint_url=neutron_endpoint.url,
|
||||
region_name=neutron_endpoint.region,
|
||||
token=ctx.auth_token,
|
||||
auth_url=CONF.keystone_authtoken.auth_uri
|
||||
auth_url=ctx.auth_uri
|
||||
)
|
||||
|
||||
|
||||
@ -595,7 +598,7 @@ class DesignateAction(base.OpenStackAction):
|
||||
client = self._client_class(
|
||||
endpoint=designate_url,
|
||||
tenant_id=ctx.project_id,
|
||||
auth_url=CONF.keystone_authtoken.auth_uri,
|
||||
auth_url=ctx.auth_uri,
|
||||
region_name=designate_endpoint.region,
|
||||
service_type='dns'
|
||||
)
|
||||
|
@ -68,6 +68,8 @@ class BaseContext(object):
|
||||
class MistralContext(BaseContext):
|
||||
# Use set([...]) since set literals are not supported in Python 2.6.
|
||||
_elements = set([
|
||||
"auth_uri",
|
||||
"auth_cacert",
|
||||
"user_id",
|
||||
"project_id",
|
||||
"auth_token",
|
||||
@ -120,6 +122,8 @@ def spawn(thread_description, func, *args, **kwargs):
|
||||
|
||||
def context_from_headers(headers):
|
||||
return MistralContext(
|
||||
auth_uri=CONF.keystone_authtoken.auth_uri,
|
||||
auth_cacert=CONF.keystone_authtoken.cafile,
|
||||
user_id=headers.get('X-User-Id'),
|
||||
project_id=headers.get('X-Project-Id'),
|
||||
auth_token=headers.get('X-Auth-Token'),
|
||||
|
@ -15,6 +15,57 @@
|
||||
from mistral.tests.unit import base
|
||||
from mistral.utils.openstack import keystone
|
||||
|
||||
SERVICES_CATALOG = [
|
||||
{
|
||||
"type": "compute",
|
||||
"name": "nova",
|
||||
"endpoints": [
|
||||
{
|
||||
"interface": "private",
|
||||
"url": "https://example.com/nova/private",
|
||||
"region": "RegionOne"
|
||||
},
|
||||
{
|
||||
"interface": "public",
|
||||
"url": "https://example.com/nova/public",
|
||||
"region": "RegionOne"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "compute",
|
||||
"name": "nova2",
|
||||
"endpoints": [
|
||||
{
|
||||
"interface": "public",
|
||||
"url": "https://example.com/nova2/public/r1",
|
||||
"region": "RegionOne"
|
||||
},
|
||||
{
|
||||
"interface": "public",
|
||||
"url": "https://example.com/nova2/public/r2",
|
||||
"region": "RegionTwo"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "orchestration",
|
||||
"name": "heat",
|
||||
"endpoints": [
|
||||
{
|
||||
"interface": "private",
|
||||
"url": "https://example.com/heat/private",
|
||||
"region": "RegionOne"
|
||||
},
|
||||
{
|
||||
"interface": "public",
|
||||
"url": "https://example.com/heat/public",
|
||||
"region": "RegionOne"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
class KeystoneUtilsTest(base.BaseTest):
|
||||
def setUp(self):
|
||||
@ -41,3 +92,24 @@ class KeystoneUtilsTest(base.BaseTest):
|
||||
expected,
|
||||
keystone.format_url(url_template, self.values)
|
||||
)
|
||||
|
||||
def test_service_endpoints_select(self):
|
||||
def find(name, typ=None, catalog=SERVICES_CATALOG):
|
||||
return keystone.select_service_endpoints(name, typ, catalog)
|
||||
|
||||
endpoints = find('nova', 'compute')
|
||||
self.assertEqual('https://example.com/nova/public', endpoints[0].url,
|
||||
message='public interface must be selected')
|
||||
|
||||
endpoints = find('nova2')
|
||||
self.assertEqual(2, len(endpoints),
|
||||
message='public endpoints must be selected '
|
||||
'in each region')
|
||||
|
||||
endpoints = find('heat')
|
||||
self.assertEqual('https://example.com/heat/public', endpoints[0].url,
|
||||
message='selection should work without type set')
|
||||
|
||||
endpoints = find('nova', None, [])
|
||||
self.assertEqual([], endpoints,
|
||||
message='empty catalog should be accepted')
|
||||
|
@ -14,6 +14,7 @@
|
||||
# limitations under the License.
|
||||
|
||||
from keystoneclient.v3 import client as ks_client
|
||||
from keystoneclient.v3.endpoints import Endpoint
|
||||
from oslo_config import cfg
|
||||
|
||||
from mistral import context
|
||||
@ -23,7 +24,7 @@ CONF = cfg.CONF
|
||||
|
||||
def client():
|
||||
ctx = context.ctx()
|
||||
auth_url = CONF.keystone_authtoken.auth_uri
|
||||
auth_url = ctx.auth_uri
|
||||
|
||||
cl = ks_client.Client(
|
||||
username=ctx.user_name,
|
||||
@ -62,37 +63,49 @@ def client_for_trusts(trust_id):
|
||||
|
||||
|
||||
def get_endpoint_for_project(service_name=None, service_type=None):
|
||||
admin_project_name = CONF.keystone_authtoken.admin_tenant_name
|
||||
keystone_client = _admin_client(project_name=admin_project_name)
|
||||
service_list = keystone_client.services.list()
|
||||
|
||||
if service_name:
|
||||
service_ids = [s.id for s in service_list if s.name == service_name]
|
||||
elif service_type:
|
||||
service_ids = [s.id for s in service_list if s.type == service_type]
|
||||
else:
|
||||
if service_name is None and service_type is None:
|
||||
raise Exception(
|
||||
"Either 'service_name' or 'service_type' must be provided."
|
||||
)
|
||||
|
||||
if not service_ids:
|
||||
raise Exception("Either service '%s' or service type "
|
||||
"'%s' doesn't exist!" % (service_name, service_type))
|
||||
ctx = context.ctx()
|
||||
|
||||
endpoints = keystone_client.endpoints.list(
|
||||
service=service_ids[0],
|
||||
interface='public'
|
||||
)
|
||||
token = ctx.auth_token
|
||||
response = client().tokens.get_token_data(token, include_catalog=True)
|
||||
|
||||
endpoints = select_service_endpoints(
|
||||
service_name,
|
||||
service_type,
|
||||
response["token"]["catalog"])
|
||||
|
||||
if not endpoints:
|
||||
raise Exception(
|
||||
"No endpoints found [service_name=%s, service_type=%s]"
|
||||
% (service_name, service_type)
|
||||
)
|
||||
else:
|
||||
# TODO(rakhmerov): We may have more than one endpoint because
|
||||
# TODO(rakhmerov): of regions and ideally we need a config option
|
||||
# TODO(rakhmerov): for region
|
||||
return endpoints[0]
|
||||
|
||||
# TODO(rakhmerov): We may have more than one endpoint because of regions
|
||||
# TODO(rakhmerov): and ideally we need a config option for region
|
||||
return endpoints[0]
|
||||
|
||||
def select_service_endpoints(service_name, service_type, services):
|
||||
endpoints = []
|
||||
|
||||
for catalog in services:
|
||||
|
||||
if service_name and catalog["name"] != service_name:
|
||||
continue
|
||||
|
||||
if service_type and catalog["type"] != service_type:
|
||||
continue
|
||||
|
||||
for endpoint in catalog["endpoints"]:
|
||||
if endpoint["interface"] == 'public':
|
||||
endpoints.append(Endpoint(None, endpoint, loaded=True))
|
||||
|
||||
return endpoints
|
||||
|
||||
|
||||
def get_keystone_endpoint_v2():
|
||||
|
Loading…
Reference in New Issue
Block a user