summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortermie <github@anarkystic.com>2011-11-02 13:35:27 -0700
committertermie <github@anarkystic.com>2011-11-02 13:35:27 -0700
commit4ba33be08e2ef24f61ec9a840df3f28cdb569818 (patch)
treecd4a2c4d7cfe2886e80c4fff7f9212d2d01394ee
parent2ac753edfd662d0e5a24531f47c8f16feab16de8 (diff)
add templated catalog backend
Fix a few other issues, and adds passive aggressive comments and documentation.
-rw-r--r--keystonelight/backends/templated.py81
-rw-r--r--keystonelight/keystone_compat.py5
-rw-r--r--keystonelight/test.py9
-rw-r--r--tests/keystone_compat_diablo.conf3
-rw-r--r--tests/keystoneclient_compat_master.conf31
-rw-r--r--tests/test_keystone_compat.py11
-rw-r--r--tests/test_keystoneclient_compat.py11
7 files changed, 142 insertions, 9 deletions
diff --git a/keystonelight/backends/templated.py b/keystonelight/backends/templated.py
new file mode 100644
index 00000000..e8406dc0
--- /dev/null
+++ b/keystonelight/backends/templated.py
@@ -0,0 +1,81 @@
+class TemplatedCatalog(object):
+ """A backend that generates endpoints for the Catalog based on templates.
+
+ It is usually configured via config entries that look like:
+
+ catalog.$REGION.$SERVICE.$key = $value
+
+ and is stored in a similar looking hierarchy. Where a value can contain
+ values to be interpolated by standard python string interpolation that look
+ like (the % is replaced by a $ due to paste attmepting to interpolate on its
+ own:
+
+ http://localhost:$(public_port)s/
+
+ When expanding the template it will pass in a dict made up of the options
+ instance plus a few additional key-values, notably tenant_id and user_id.
+
+ It does not care what the keys and values are but it is worth noting that
+ keystone_compat will expect certain keys to be there so that it can munge
+ them into the output format keystone expects. These keys are:
+
+ name - the name of the service, most likely repeated for all services of
+ the same type, across regions.
+ adminURL - the url of the admin endpoint
+ publicURL - the url of the public endpoint
+ internalURL - the url of the internal endpoint
+
+ """
+
+ def __init__(self, options, templates=None):
+ self.options = options
+
+ if templates:
+ self.templates = templates
+ else:
+ self._load_templates(options)
+
+
+ def _load_templates(self, options):
+ o = {}
+ for k, v in options.iteritems():
+ if not k.startswith('catalog.'):
+ continue
+
+ parts = k.split('.')
+
+ region = parts[1]
+ service = parts[2]
+ key = parts[3]
+
+ region_ref = o.get(region, {})
+ service_ref = region_ref.get(service, {})
+ service_ref[key] = v
+
+ region_ref[service] = service_ref
+ o[region] = region_ref
+
+ self.templates = o
+
+ def get_catalog(self, user_id, tenant_id, extras=None):
+ d = self.options.copy()
+ d.update({'tenant_id': tenant_id,
+ 'user_id': user_id})
+
+ o = {}
+ for region, region_ref in self.templates.iteritems():
+ o[region] = {}
+ for service, service_ref in region_ref.iteritems():
+ o[region][service] = {}
+ for k, v in service_ref.iteritems():
+ v = v.replace('$(', '%(')
+ o[region][service][k] = v % d
+
+ return o
+
+
+
+
+
+
+
diff --git a/keystonelight/keystone_compat.py b/keystonelight/keystone_compat.py
index 403fac74..22451b4b 100644
--- a/keystonelight/keystone_compat.py
+++ b/keystonelight/keystone_compat.py
@@ -71,7 +71,10 @@ class KeystoneController(service.BaseApplication):
# more compat
if tenant_name:
- tenant_id = self.identity_api.get_tenant_by_name(tenant_name)
+ tenant_ref = self.identity_api.get_tenant_by_name(
+ context=context, tenant_name=tenant_name)
+ tenant_id = tenant_ref['id']
+ logging.debug('RENANT: %s', tenant_ref)
else:
tenant_id = auth.get('tenantId', None)
diff --git a/keystonelight/test.py b/keystonelight/test.py
index 570b9ecc..9f28b1df 100644
--- a/keystonelight/test.py
+++ b/keystonelight/test.py
@@ -1,3 +1,4 @@
+import ConfigParser
import os
import unittest
import sys
@@ -67,6 +68,9 @@ class TestCase(unittest.TestCase):
super(TestCase, self).__init__(*args, **kw)
self._paths = []
+ def setUp(self):
+ super(TestCase, self).setUp()
+
def tearDown(self):
for path in self._paths:
if path in sys.path:
@@ -87,6 +91,11 @@ class TestCase(unittest.TestCase):
app = self.loadapp(config)
server = wsgi.Server()
server.start(app, 0, key='socket')
+
+ # Service catalog tests need to know the port we ran on.
+ options = self.appconfig(config)
+ port = server.socket_info['socket'][1]
+ options['public_port'] = port
return server
def client(self, app, *args, **kw):
diff --git a/tests/keystone_compat_diablo.conf b/tests/keystone_compat_diablo.conf
index 36c88964..8318a0ca 100644
--- a/tests/keystone_compat_diablo.conf
+++ b/tests/keystone_compat_diablo.conf
@@ -2,8 +2,7 @@
catalog_driver = keystonelight.backends.kvs.KvsCatalog
identity_driver = keystonelight.backends.kvs.KvsIdentity
token_driver = keystonelight.backends.kvs.KvsToken
-public_port = 8080
-
+public_port = 5000
[filter:debug]
paste.filter_factory = keystonelight.wsgi:Debug.factory
diff --git a/tests/keystoneclient_compat_master.conf b/tests/keystoneclient_compat_master.conf
new file mode 100644
index 00000000..e0595b8c
--- /dev/null
+++ b/tests/keystoneclient_compat_master.conf
@@ -0,0 +1,31 @@
+[DEFAULT]
+catalog_driver = keystonelight.backends.templated.TemplatedCatalog
+identity_driver = keystonelight.backends.kvs.KvsIdentity
+token_driver = keystonelight.backends.kvs.KvsToken
+public_port = 5000
+
+# config for TemplatedCatalog, using camelCase because I don't want to do
+# translations for keystone compat
+catalog.RegionOne.identity.publicURL = http://localhost:$(public_port)s/v2.0/$(tenant_id)s
+catalog.RegionOne.identity.adminURL = http://localhost:$(public_port)s/v2.0/$(tenant_id)s
+catalog.RegionOne.identity.internalURL = http://localhost:$(public_port)s/v2.0/$(tenant_id)s
+
+
+# in old config:
+# first 1 == public
+# second 1 == enabled
+
+[filter:debug]
+paste.filter_factory = keystonelight.wsgi:Debug.factory
+
+[filter:token_auth]
+paste.filter_factory = keystonelight.service:TokenAuthMiddleware.factory
+
+[filter:json_body]
+paste.filter_factory = keystonelight.service:JsonBodyMiddleware.factory
+
+[app:keystone]
+paste.app_factory = keystonelight.keystone_compat:app_factory
+
+[pipeline:main]
+pipeline = token_auth json_body debug keystone
diff --git a/tests/test_keystone_compat.py b/tests/test_keystone_compat.py
index 2d956f1d..3577122b 100644
--- a/tests/test_keystone_compat.py
+++ b/tests/test_keystone_compat.py
@@ -19,6 +19,15 @@ KEYSTONE_SAMPLE_DIR = 'keystone/content/common/samples'
class CompatTestCase(test.TestCase):
+ """Test compatibility against various versions of keystone's docs.
+
+ It should be noted that the docs for any given revision have rarely, if ever,
+ reflected the actual usage or reliable sample output of the system, so these
+ tests are largely a study of frustration and its effects on developer
+ productivity.
+
+ """
+
def setUp(self):
super(CompatTestCase, self).setUp()
@@ -120,7 +129,7 @@ class DiabloCompatTestCase(CompatTestCase):
{'auth': {'passwordCredentials': {'username': self.user_123['id'],
'password': self.user_123['password'],
},
- 'tenantName': self.tenant_345['id']}})
+ 'tenantName': self.tenant_345['name']}})
resp = client.post('/v2.0/tokens', body=post_data)
data = json.loads(resp.body)
diff --git a/tests/test_keystoneclient_compat.py b/tests/test_keystoneclient_compat.py
index 2ef470de..11e32812 100644
--- a/tests/test_keystoneclient_compat.py
+++ b/tests/test_keystoneclient_compat.py
@@ -18,15 +18,17 @@ class CompatTestCase(test.TestCase):
super(CompatTestCase, self).setUp()
-class DiabloCompatTestCase(CompatTestCase):
+class MasterCompatTestCase(CompatTestCase):
def setUp(self):
+ super(MasterCompatTestCase, self).setUp()
+
revdir = test.checkout_vendor(KEYSTONECLIENT_REPO, 'master')
self.add_path(revdir)
from keystoneclient.v2_0 import client as ks_client
reload(ks_client)
- self.app = self.loadapp('keystone_compat_diablo')
- self.options = self.appconfig('keystone_compat_diablo')
+ self.app = self.loadapp('keystoneclient_compat_master')
+ self.options = self.appconfig('keystoneclient_compat_master')
self.identity_backend = utils.import_object(
self.options['identity_driver'], options=self.options)
@@ -35,7 +37,7 @@ class DiabloCompatTestCase(CompatTestCase):
self.catalog_backend = utils.import_object(
self.options['catalog_driver'], options=self.options)
- self.server = self.serveapp('keystone_compat_diablo')
+ self.server = self.serveapp('keystoneclient_compat_master')
self.tenant_bar = self.identity_backend._create_tenant(
'bar',
@@ -53,7 +55,6 @@ class DiabloCompatTestCase(CompatTestCase):
dict(roles=[],
roles_links=[]))
- super(DiabloCompatTestCase, self).setUp()
def test_pass(self):
from keystoneclient.v2_0 import client as ks_client