summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortermie <github@anarkystic.com>2011-11-10 15:57:54 -0800
committertermie <github@anarkystic.com>2011-11-10 15:57:54 -0800
commite10512b2b879e4e70a59722d00dcb21f6a940dff (patch)
treea0835bd03f4a4247f1265ed1fa01672438087520
parent84644998b3d4b6321bd27ca21ded89b371ef1957 (diff)
more dyanmic client
-rw-r--r--keystonelight/client.py33
-rw-r--r--keystonelight/service.py77
-rw-r--r--tests/test_identity_api.py6
3 files changed, 96 insertions, 20 deletions
diff --git a/keystonelight/client.py b/keystonelight/client.py
index 7b971584..25128ba3 100644
--- a/keystonelight/client.py
+++ b/keystonelight/client.py
@@ -6,9 +6,13 @@ import json
import httplib2
import webob
+from keystonelight import service
from keystonelight import wsgi
+URLMAP = service.URLMAP
+
+
class Client(object):
def __init__(self, token=None):
self.token = token
@@ -34,6 +38,35 @@ class Client(object):
return headers
+ def __getattr__(self, key):
+ """Lazy way to define a bunch of dynamic urls based on URLMAP.
+
+ Turns something like
+
+ c.authenticate(user_id='foo', password='bar')
+
+ into
+
+ c.request('POST', '/token', body={'user_id': 'foo', 'password': 'bar'})
+
+ """
+ if key not in URLMAP:
+ raise AttributeError(key)
+
+ method, path = URLMAP[key]
+
+ def _internal(method_=method, path_=path, **kw):
+ path_ = path_ % kw
+ params = {'method': method_,
+ 'path': path_}
+ if method.lower() in ('put', 'post'):
+ params['body'] = kw
+ return self.request(**params)
+
+ setattr(self, key, _internal)
+
+ return getattr(self, key)
+
class HttpClient(Client):
def __init__(self, endpoint=None, token=None):
diff --git a/keystonelight/service.py b/keystonelight/service.py
index a4c46e9e..536a2a05 100644
--- a/keystonelight/service.py
+++ b/keystonelight/service.py
@@ -1,7 +1,3 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# this is the web service frontend
-
import json
import logging
@@ -15,6 +11,41 @@ from keystonelight import utils
from keystonelight import wsgi
+HIGH_LEVEL_CALLS = {
+ 'authenticate': ('POST', '/tokens'),
+ 'get_tenants': ('GET', '/user/%(user_id)s/tenants'),
+ 'get_user': ('GET', '/user/%(user_id)s'),
+ 'get_tenant': ('GET', '/tenant/%(tenant_id)s'),
+ 'get_tenant_by_name': ('GET', '/tenant_name/%(tenant_name)s'),
+ 'get_extras': ('GET', '/extras/%(tenant_id)s-%(user_id)s'),
+ 'get_token': ('GET', '/token/%(token_id)s'),
+ }
+
+# NOTE(termie): creates are seperate from updates to allow duplication checks
+LOW_LEVEL_CALLS = {
+ # tokens
+ 'create_token': ('POST', '/token'),
+ 'delete_token': ('DELETE', '/token/%(token_id)s'),
+ # users
+ 'create_user': ('POST', '/user'),
+ 'update_user': ('PUT', '/user/%(user_id)s'),
+ 'delete_user': ('DELETE', '/user/%(user_id)s'),
+ # tenants
+ 'create_tenant': ('POST', '/tenant'),
+ 'update_tenant': ('PUT', '/tenant/%(tenant_id)s'),
+ 'delete_tenant': ('DELETE', '/tenant/%(tenant_id)s'),
+ # extras
+ # NOTE(termie): these separators are probably going to bite us eventually
+ 'create_extras': ('POST', '/extras'),
+ 'update_extras': ('PUT', '/extras/%(tenant_id)s-%(user_id)s'),
+ 'delete_extras': ('DELETE', '/extras/%(tenant_id)s-%(user_id)s'),
+ }
+
+
+URLMAP = HIGH_LEVEL_CALLS.copy()
+URLMAP.update(LOW_LEVEL_CALLS)
+
+
class BaseApplication(wsgi.Application):
@webob.dec.wsgify
def __call__(self, req):
@@ -81,10 +112,11 @@ class IdentityController(BaseApplication):
logging.debug('TOKEN: %s', token_ref)
return token_ref
- def get_tenants(self, context):
+ def get_tenants(self, context, user_id=None):
token_id = context.get('token_id')
token_ref = self.token_api.get_token(context, token_id)
assert token_ref
+ assert token_ref['user']['id'] == user_id
tenants_ref = []
for tenant_id in token_ref['user']['tenants']:
tenants_ref.append(self.identity_api.get_tenant(context,
@@ -98,20 +130,31 @@ class Router(wsgi.Router):
self.options = options
self.identity_controller = IdentityController(options)
self.token_controller = TokenController(options)
- mapper = routes.Mapper()
- mapper.connect('/tokens',
- controller=self.identity_controller,
- action='authenticate')
- mapper.connect('/tokens/{token_id}',
- controller=self.token_controller,
- action='revoke_token',
- conditions=dict(method=['DELETE']))
- mapper.connect("/tenants",
- controller=self.identity_controller,
- action="get_tenants",
- conditions=dict(method=["GET"]))
+
+ mapper = self._build_map(URLMAP)
super(Router, self).__init__(mapper)
+ def _build_map(self, urlmap):
+ """Build a routes.Mapper based on URLMAP."""
+ mapper = routes.Mapper()
+ for k, v in urlmap.iteritems():
+ # NOTE(termie): hack
+ if 'token' in k:
+ controller = self.token_controller
+ else:
+ controller = self.identity_controller
+ action = k
+ method, path = v
+ path = path.replace('%(', '{').replace(')s', '}')
+ print path
+
+ mapper.connect(path,
+ controller=controller,
+ action=action,
+ conditions=dict(method=[method]))
+
+ return mapper
+
def app_factory(global_conf, **local_conf):
conf = global_conf.copy()
diff --git a/tests/test_identity_api.py b/tests/test_identity_api.py
index 21b25781..885d4314 100644
--- a/tests/test_identity_api.py
+++ b/tests/test_identity_api.py
@@ -51,7 +51,7 @@ class IdentityApi(test.TestCase):
post_data = {'user_id': self.user_foo['id'],
'tenant_id': self.tenant_bar['id'],
'password': self.user_foo['password']}
- resp = c.post('/tokens', body=post_data)
+ resp = c.authenticate(**post_data)
data = json.loads(resp.body)
self.assertEquals(self.user_foo['id'], data['user']['id'])
self.assertEquals(self.tenant_bar['id'], data['tenant']['id'])
@@ -61,7 +61,7 @@ class IdentityApi(test.TestCase):
c = client.TestClient(self.app)
post_data = {'user_id': self.user_foo['id'],
'password': self.user_foo['password']}
- resp = c.post('/tokens', body=post_data)
+ resp = c.authenticate(**post_data)
data = json.loads(resp.body)
self.assertEquals(self.user_foo['id'], data['user']['id'])
self.assertEquals(None, data['tenant'])
@@ -70,6 +70,6 @@ class IdentityApi(test.TestCase):
def test_get_tenants(self):
token = self._login()
c = client.TestClient(self.app, token['id'])
- resp = c.get('/tenants')
+ resp = c.get_tenants(user_id=self.user_foo['id'])
data = json.loads(resp.body)
self.assertDictEquals(self.tenant_bar, data[0])