diff options
| author | termie <github@anarkystic.com> | 2011-11-02 13:35:27 -0700 |
|---|---|---|
| committer | termie <github@anarkystic.com> | 2011-11-02 13:35:27 -0700 |
| commit | 4ba33be08e2ef24f61ec9a840df3f28cdb569818 (patch) | |
| tree | cd4a2c4d7cfe2886e80c4fff7f9212d2d01394ee | |
| parent | 2ac753edfd662d0e5a24531f47c8f16feab16de8 (diff) | |
add templated catalog backend
Fix a few other issues, and adds passive aggressive comments and
documentation.
| -rw-r--r-- | keystonelight/backends/templated.py | 81 | ||||
| -rw-r--r-- | keystonelight/keystone_compat.py | 5 | ||||
| -rw-r--r-- | keystonelight/test.py | 9 | ||||
| -rw-r--r-- | tests/keystone_compat_diablo.conf | 3 | ||||
| -rw-r--r-- | tests/keystoneclient_compat_master.conf | 31 | ||||
| -rw-r--r-- | tests/test_keystone_compat.py | 11 | ||||
| -rw-r--r-- | tests/test_keystoneclient_compat.py | 11 |
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 |
