Merge "Use client credentials to retrieve service list"

This commit is contained in:
Jenkins 2016-06-30 09:04:40 +00:00 committed by Gerrit Code Review
commit cba49f38fe
4 changed files with 118 additions and 26 deletions

View File

@ -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'
)

View File

@ -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'),

View File

@ -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')

View File

@ -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():