Make neutronclient parse keystone v3 endpoints correctly
Import keystone access module to handle various verion of keystone catalog. Change-Id: Ie8de15da6341cdb3af73c0fa8753f7e754bf6275 Closes-bug: 1295056
This commit is contained in:
@@ -21,6 +21,7 @@ except ImportError:
|
||||
import logging
|
||||
import os
|
||||
|
||||
from keystoneclient import access
|
||||
import requests
|
||||
|
||||
from neutronclient.common import exceptions
|
||||
@@ -40,55 +41,6 @@ else:
|
||||
logging.getLogger("requests").setLevel(_requests_log_level)
|
||||
|
||||
|
||||
class ServiceCatalog(object):
|
||||
"""Helper methods for dealing with a Keystone Service Catalog."""
|
||||
|
||||
def __init__(self, resource_dict):
|
||||
self.catalog = resource_dict
|
||||
|
||||
def get_token(self):
|
||||
"""Fetch token details from service catalog."""
|
||||
token = {'id': self.catalog['access']['token']['id'],
|
||||
'expires': self.catalog['access']['token']['expires'], }
|
||||
try:
|
||||
token['user_id'] = self.catalog['access']['user']['id']
|
||||
token['tenant_id'] = (
|
||||
self.catalog['access']['token']['tenant']['id'])
|
||||
except Exception:
|
||||
# just leave the tenant and user out if it doesn't exist
|
||||
pass
|
||||
return token
|
||||
|
||||
def url_for(self, attr=None, filter_value=None,
|
||||
service_type='network', endpoint_type='publicURL'):
|
||||
"""Fetch the URL from the Neutron service for
|
||||
a particular endpoint type. If none given, return
|
||||
publicURL.
|
||||
"""
|
||||
|
||||
catalog = self.catalog['access'].get('serviceCatalog', [])
|
||||
matching_endpoints = []
|
||||
for service in catalog:
|
||||
if service['type'] != service_type:
|
||||
continue
|
||||
|
||||
endpoints = service['endpoints']
|
||||
for endpoint in endpoints:
|
||||
if not filter_value or endpoint.get(attr) == filter_value:
|
||||
matching_endpoints.append(endpoint)
|
||||
|
||||
if not matching_endpoints:
|
||||
raise exceptions.EndpointNotFound()
|
||||
elif len(matching_endpoints) > 1:
|
||||
raise exceptions.AmbiguousEndpoints(
|
||||
matching_endpoints=matching_endpoints)
|
||||
else:
|
||||
if endpoint_type not in matching_endpoints[0]:
|
||||
raise exceptions.EndpointTypeNotFound(type_=endpoint_type)
|
||||
|
||||
return matching_endpoints[0][endpoint_type]
|
||||
|
||||
|
||||
class HTTPClient(object):
|
||||
"""Handles the REST calls and responses, include authn."""
|
||||
|
||||
@@ -219,14 +171,12 @@ class HTTPClient(object):
|
||||
|
||||
def _extract_service_catalog(self, body):
|
||||
"""Set the client's service catalog from the response data."""
|
||||
self.service_catalog = ServiceCatalog(body)
|
||||
try:
|
||||
sc = self.service_catalog.get_token()
|
||||
self.auth_token = sc['id']
|
||||
self.auth_tenant_id = sc.get('tenant_id')
|
||||
self.auth_user_id = sc.get('user_id')
|
||||
except KeyError:
|
||||
raise exceptions.Unauthorized()
|
||||
self.auth_ref = access.AccessInfo.factory(body=body)
|
||||
self.service_catalog = self.auth_ref.service_catalog
|
||||
self.auth_token = self.auth_ref.auth_token
|
||||
self.auth_tenant_id = self.auth_ref.tenant_id
|
||||
self.auth_user_id = self.auth_ref.user_id
|
||||
|
||||
if not self.endpoint_url:
|
||||
self.endpoint_url = self.service_catalog.url_for(
|
||||
attr='region', filter_value=self.region_name,
|
||||
|
||||
@@ -18,6 +18,7 @@ import copy
|
||||
import json
|
||||
import uuid
|
||||
|
||||
from keystoneclient import exceptions as k_exceptions
|
||||
import mox
|
||||
import requests
|
||||
import testtools
|
||||
@@ -291,86 +292,6 @@ class CLITestAuthKeystone(testtools.TestCase):
|
||||
self.mox.ReplayAll()
|
||||
self.client.do_request('/resource', 'GET')
|
||||
|
||||
def test_url_for(self):
|
||||
resources = copy.deepcopy(KS_TOKEN_RESULT)
|
||||
|
||||
endpoints = resources['access']['serviceCatalog'][0]['endpoints'][0]
|
||||
endpoints['publicURL'] = 'public'
|
||||
endpoints['internalURL'] = 'internal'
|
||||
endpoints['adminURL'] = 'admin'
|
||||
catalog = client.ServiceCatalog(resources)
|
||||
|
||||
# endpoint_type not specified
|
||||
url = catalog.url_for(attr='region',
|
||||
filter_value=REGION)
|
||||
self.assertEqual('public', url)
|
||||
|
||||
# endpoint type specified (3 cases)
|
||||
url = catalog.url_for(attr='region',
|
||||
filter_value=REGION,
|
||||
endpoint_type='adminURL')
|
||||
self.assertEqual('admin', url)
|
||||
|
||||
url = catalog.url_for(attr='region',
|
||||
filter_value=REGION,
|
||||
endpoint_type='publicURL')
|
||||
self.assertEqual('public', url)
|
||||
|
||||
url = catalog.url_for(attr='region',
|
||||
filter_value=REGION,
|
||||
endpoint_type='internalURL')
|
||||
self.assertEqual('internal', url)
|
||||
|
||||
# endpoint_type requested does not exist.
|
||||
self.assertRaises(exceptions.EndpointTypeNotFound,
|
||||
catalog.url_for,
|
||||
attr='region',
|
||||
filter_value=REGION,
|
||||
endpoint_type='privateURL')
|
||||
|
||||
# Test scenario with url_for when the service catalog only has publicURL.
|
||||
def test_url_for_only_public_url(self):
|
||||
resources = copy.deepcopy(KS_TOKEN_RESULT)
|
||||
catalog = client.ServiceCatalog(resources)
|
||||
|
||||
# Remove endpoints from the catalog.
|
||||
endpoints = resources['access']['serviceCatalog'][0]['endpoints'][0]
|
||||
del endpoints['internalURL']
|
||||
del endpoints['adminURL']
|
||||
endpoints['publicURL'] = 'public'
|
||||
|
||||
# Use publicURL when specified explicitly.
|
||||
url = catalog.url_for(attr='region',
|
||||
filter_value=REGION,
|
||||
endpoint_type='publicURL')
|
||||
self.assertEqual('public', url)
|
||||
|
||||
# Use publicURL when specified explicitly.
|
||||
url = catalog.url_for(attr='region',
|
||||
filter_value=REGION)
|
||||
self.assertEqual('public', url)
|
||||
|
||||
# Test scenario with url_for when the service catalog only has adminURL.
|
||||
def test_url_for_only_admin_url(self):
|
||||
resources = copy.deepcopy(KS_TOKEN_RESULT)
|
||||
catalog = client.ServiceCatalog(resources)
|
||||
endpoints = resources['access']['serviceCatalog'][0]['endpoints'][0]
|
||||
del endpoints['internalURL']
|
||||
del endpoints['publicURL']
|
||||
endpoints['adminURL'] = 'admin'
|
||||
|
||||
# Use publicURL when specified explicitly.
|
||||
url = catalog.url_for(attr='region',
|
||||
filter_value=REGION,
|
||||
endpoint_type='adminURL')
|
||||
self.assertEqual('admin', url)
|
||||
|
||||
# But not when nothing is specified.
|
||||
self.assertRaises(exceptions.EndpointTypeNotFound,
|
||||
catalog.url_for,
|
||||
attr='region',
|
||||
filter_value=REGION)
|
||||
|
||||
def test_endpoint_type(self):
|
||||
resources = copy.deepcopy(KS_TOKEN_RESULT)
|
||||
endpoints = resources['access']['serviceCatalog'][0]['endpoints'][0]
|
||||
@@ -415,7 +336,7 @@ class CLITestAuthKeystone(testtools.TestCase):
|
||||
username=USERNAME, tenant_name=TENANT_NAME, password=PASSWORD,
|
||||
auth_url=AUTH_URL, region_name=REGION, endpoint_type='privateURL')
|
||||
|
||||
self.assertRaises(exceptions.EndpointTypeNotFound,
|
||||
self.assertRaises(k_exceptions.EndpointNotFound,
|
||||
self.client._extract_service_catalog,
|
||||
resources)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ cliff>=1.4.3
|
||||
iso8601>=0.1.9
|
||||
netaddr>=0.7.6
|
||||
requests>=1.1
|
||||
python-keystoneclient>=0.9.0
|
||||
simplejson>=2.0.9
|
||||
six>=1.6.0
|
||||
Babel>=1.3
|
||||
|
||||
Reference in New Issue
Block a user