summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYaguang Tang <yaguang.tang@canonical.com>2014-03-20 18:48:38 +0800
committerYaguang Tang <yaguang.tang@canonical.com>2014-06-09 10:31:36 +0800
commit864be88ef9b33e1f74e13c225f1a3b4cbf17bce3 (patch)
treee7446a54feceae8f528a000e9264ec4f759b7a6b
parent4ac92ccef1eb260a9fe4bc9df93f8d841443605c (diff)
downloadpython-neutronclient-864be88ef9b33e1f74e13c225f1a3b4cbf17bce3.tar.gz
Make neutronclient parse keystone v3 endpoints correctly
Import keystone access module to handle various verion of keystone catalog. Change-Id: Ie8de15da6341cdb3af73c0fa8753f7e754bf6275 Closes-bug: 1295056
-rw-r--r--neutronclient/client.py64
-rw-r--r--neutronclient/tests/unit/test_auth.py83
-rw-r--r--requirements.txt1
3 files changed, 10 insertions, 138 deletions
diff --git a/neutronclient/client.py b/neutronclient/client.py
index cd71e1b..7379edb 100644
--- a/neutronclient/client.py
+++ b/neutronclient/client.py
@@ -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,
diff --git a/neutronclient/tests/unit/test_auth.py b/neutronclient/tests/unit/test_auth.py
index 585458e..ae077c8 100644
--- a/neutronclient/tests/unit/test_auth.py
+++ b/neutronclient/tests/unit/test_auth.py
@@ -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)
diff --git a/requirements.txt b/requirements.txt
index 7c118d3..c09cd7b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -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