summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortermie <github@anarkystic.com>2012-01-06 23:10:18 -0800
committertermie <github@anarkystic.com>2012-01-09 10:00:09 -0800
commit13ec79bf48a185a6f359d1e6c013bdfe24b7da53 (patch)
tree6dc147a678ae2790331212e7fce95933caf9160c
parent4b4ada27cadf9bc5fcaaa9ccab79fdd1400fb450 (diff)
downloadkeystone-13ec79bf48a185a6f359d1e6c013bdfe24b7da53.tar.gz
keystone-13ec79bf48a185a6f359d1e6c013bdfe24b7da53.tar.xz
keystone-13ec79bf48a185a6f359d1e6c013bdfe24b7da53.zip
keystoneclient tests working against sql backend
-rw-r--r--keystonelight/backends/kvs.py6
-rw-r--r--keystonelight/backends/sql/core.py197
-rw-r--r--keystonelight/keystone_compat.py27
-rw-r--r--keystonelight/service.py17
-rw-r--r--keystonelight/test.py12
5 files changed, 180 insertions, 79 deletions
diff --git a/keystonelight/backends/kvs.py b/keystonelight/backends/kvs.py
index 4394f347..c15e449c 100644
--- a/keystonelight/backends/kvs.py
+++ b/keystonelight/backends/kvs.py
@@ -64,10 +64,12 @@ class KvsIdentity(object):
return role_ref
def list_users(self):
- return self.db.get('user_list', [])
+ user_ids = self.db.get('user_list', [])
+ return [self.get_user(x) for x in user_ids]
def list_roles(self):
- return self.db.get('role_list', [])
+ role_ids = self.db.get('role_list', [])
+ return [self.get_role(x) for x in role_ids]
# These should probably be part of the high-level API
def add_user_to_tenant(self, tenant_id, user_id):
diff --git a/keystonelight/backends/sql/core.py b/keystonelight/backends/sql/core.py
index 211d9ca2..62528976 100644
--- a/keystonelight/backends/sql/core.py
+++ b/keystonelight/backends/sql/core.py
@@ -63,11 +63,12 @@ class DictBase(object):
Includes attributes from joins.
"""
- local = dict(self)
- joined = dict([(k, v) for k, v in self.__dict__.iteritems()
- if not k[0] == '_'])
- local.update(joined)
- return local.iteritems()
+ return dict([(k, getattr(self, k)) for k in self])
+ #local = dict(self)
+ #joined = dict([(k, v) for k, v in self.__dict__.iteritems()
+ # if not k[0] == '_'])
+ #local.update(joined)
+ #return local.iteritems()
# Tables
@@ -75,13 +76,51 @@ class User(Base, DictBase):
__tablename__ = 'user'
id = sql.Column(sql.String(64), primary_key=True)
name = sql.Column(sql.String(64), unique=True)
- password = sql.Column(sql.String(64))
+ #password = sql.Column(sql.String(64))
+ extra = sql.Column(JsonBlob())
+
+ @classmethod
+ def from_dict(cls, user_dict):
+ # shove any non-indexed properties into extra
+ extra = {}
+ for k, v in user_dict.copy().iteritems():
+ # TODO(termie): infer this somehow
+ if k not in ['id', 'name']:
+ extra[k] = user_dict.pop(k)
+
+ user_dict['extra'] = extra
+ return cls(**user_dict)
+
+ def to_dict(self):
+ extra_copy = self.extra.copy()
+ extra_copy['id'] = self.id
+ extra_copy['name'] = self.name
+ return extra_copy
class Tenant(Base, DictBase):
__tablename__ = 'tenant'
id = sql.Column(sql.String(64), primary_key=True)
name = sql.Column(sql.String(64), unique=True)
+ extra = sql.Column(JsonBlob())
+
+ @classmethod
+ def from_dict(cls, tenant_dict):
+ # shove any non-indexed properties into extra
+ extra = {}
+ for k, v in tenant_dict.copy().iteritems():
+ # TODO(termie): infer this somehow
+ if k not in ['id', 'name']:
+ extra[k] = tenant_dict.pop(k)
+
+ tenant_dict['extra'] = extra
+ return cls(**tenant_dict)
+
+ def to_dict(self):
+ extra_copy = self.extra.copy()
+ extra_copy['id'] = self.id
+ extra_copy['name'] = self.name
+ return extra_copy
class Role(Base, DictBase):
@@ -143,7 +182,7 @@ class SqlBase(object):
engine_args = {
"pool_recycle": CONF.sql.idle_timeout,
- "echo": False,
+ "echo": True,
}
if "sqlite" in connection_dict.drivername:
@@ -177,6 +216,7 @@ class SqlIdentity(SqlBase):
raise AssertionError('Invalid tenant')
tenant_ref = self.get_tenant(tenant_id)
+ print 'ETESTSET', tenant_ref
if tenant_ref:
extras_ref = self.get_extras(user_id, tenant_id)
else:
@@ -186,29 +226,37 @@ class SqlIdentity(SqlBase):
def get_tenant(self, tenant_id):
session = self.get_session()
tenant_ref = session.query(Tenant).filter_by(id=tenant_id).first()
- return tenant_ref
+ if not tenant_ref:
+ return
+ return tenant_ref.to_dict()
def get_tenant_by_name(self, tenant_name):
session = self.get_session()
tenant_ref = session.query(Tenant).filter_by(name=tenant_name).first()
- return tenant_ref
+ if not tenant_ref:
+ return
+ return tenant_ref.to_dict()
def get_user(self, user_id):
session = self.get_session()
user_ref = session.query(User).filter_by(id=user_id).first()
- return user_ref
+ if not user_ref:
+ return
+ return user_ref.to_dict()
def get_user_by_name(self, user_name):
session = self.get_session()
user_ref = session.query(User).filter_by(name=user_name).first()
- return user_ref
+ if not user_ref:
+ return
+ return user_ref.to_dict()
def get_extras(self, user_id, tenant_id):
session = self.get_session()
extras_ref = session.query(Extras)\
- .filter_by(user_id=user_id)\
- .filter_by(tenant_id=tenant_id)\
- .first()
+ .filter_by(user_id=user_id)\
+ .filter_by(tenant_id=tenant_id)\
+ .first()
return getattr(extras_ref, 'data', None)
def get_role(self, role_id):
@@ -219,7 +267,7 @@ class SqlIdentity(SqlBase):
def list_users(self):
session = self.get_session()
user_refs = session.query(User)
- return list(user_refs)
+ return [x.to_dict() for x in user_refs]
def list_roles(self):
session = self.get_session()
@@ -233,11 +281,13 @@ class SqlIdentity(SqlBase):
session.add(UserTenantMembership(user_id=user_id, tenant_id=tenant_id))
def remove_user_from_tenant(self, tenant_id, user_id):
- user_ref = self.get_user(user_id)
- tenants = set(user_ref.get('tenants', []))
- tenants.remove(tenant_id)
- user_ref['tenants'] = list(tenants)
- self.update_user(user_id, user_ref)
+ session = self.get_session()
+ membership_ref = session.query(UserTenantMembership)\
+ .filter_by(user_id=user_id)\
+ .filter_by(tenant_id=tenant_id)\
+ .first()
+ with session.begin():
+ session.delete(membership_ref)
def get_tenants_for_user(self, user_id):
session = self.get_session()
@@ -255,65 +305,84 @@ class SqlIdentity(SqlBase):
def add_role_to_user_and_tenant(self, user_id, tenant_id, role_id):
extras_ref = self.get_extras(user_id, tenant_id)
+ is_new = False
if not extras_ref:
+ is_new = True
extras_ref = {}
roles = set(extras_ref.get('roles', []))
roles.add(role_id)
extras_ref['roles'] = list(roles)
- self.update_extras(user_id, tenant_id, extras_ref)
+ if not is_new:
+ self.update_extras(user_id, tenant_id, extras_ref)
+ else:
+ self.create_extras(user_id, tenant_id, extras_ref)
def remove_role_from_user_and_tenant(self, user_id, tenant_id, role_id):
extras_ref = self.get_extras(user_id, tenant_id)
+ is_new = False
if not extras_ref:
+ is_new = True
extras_ref = {}
roles = set(extras_ref.get('roles', []))
roles.remove(role_id)
extras_ref['roles'] = list(roles)
- self.update_extras(user_id, tenant_id, extras_ref)
+ if not is_new:
+ self.update_extras(user_id, tenant_id, extras_ref)
+ else:
+ self.create_extras(user_id, tenant_id, extras_ref)
# CRUD
def create_user(self, id, user):
session = self.get_session()
with session.begin():
- session.add(User(**user))
- return user
+ user_ref = User.from_dict(user)
+ session.add(user_ref)
+ return user_ref.to_dict()
def update_user(self, id, user):
- # get the old name and delete it too
- old_user = self.db.get('user-%s' % id)
- self.db.delete('user_name-%s' % old_user['name'])
- self.db.set('user-%s' % id, user)
- self.db.set('user_name-%s' % user['name'], user)
- return user
+ session = self.get_session()
+ with session.begin():
+ user_ref = session.query(User).filter_by(id=id).first()
+ old_user_dict = user_ref.to_dict()
+ for k in user:
+ old_user_dict[k] = user[k]
+ new_user = User.from_dict(old_user_dict)
+
+ user_ref.name = new_user.name
+ user_ref.extra = new_user.extra
+ return user_ref
def delete_user(self, id):
- old_user = self.db.get('user-%s' % id)
- self.db.delete('user_name-%s' % old_user['name'])
- self.db.delete('user-%s' % id)
- user_list = set(self.db.get('user_list', []))
- user_list.remove(id)
- self.db.set('user_list', list(user_list))
- return None
+ session = self.get_session()
+ user_ref = session.query(User).filter_by(id=id).first()
+ with session.begin():
+ session.delete(user_ref)
def create_tenant(self, id, tenant):
session = self.get_session()
with session.begin():
- session.add(Tenant(**tenant))
- return tenant
+ tenant_ref = Tenant.from_dict(tenant)
+ session.add(tenant_ref)
+ return tenant_ref.to_dict()
def update_tenant(self, id, tenant):
- # get the old name and delete it too
- old_tenant = self.db.get('tenant-%s' % id)
- self.db.delete('tenant_name-%s' % old_tenant['name'])
- self.db.set('tenant-%s' % id, tenant)
- self.db.set('tenant_name-%s' % tenant['name'], tenant)
- return tenant
+ session = self.get_session()
+ with session.begin():
+ tenant_ref = session.query(Tenant).filter_by(id=id).first()
+ old_tenant_dict = tenant_ref.to_dict()
+ for k in tenant:
+ old_tenant_dict[k] = tenant[k]
+ new_tenant = Tenant.from_dict(old_tenant_dict)
+
+ tenant_ref.name = new_tenant.name
+ tenant_ref.extra = new_tenant.extra
+ return tenant_ref
def delete_tenant(self, id):
- old_tenant = self.db.get('tenant-%s' % id)
- self.db.delete('tenant_name-%s' % old_tenant['name'])
- self.db.delete('tenant-%s' % id)
- return None
+ session = self.get_session()
+ tenant_ref = session.query(Tenant).filter_by(id=id).first()
+ with session.begin():
+ session.delete(tenant_ref)
def create_extras(self, user_id, tenant_id, extras):
session = self.get_session()
@@ -322,8 +391,17 @@ class SqlIdentity(SqlBase):
return extras
def update_extras(self, user_id, tenant_id, extras):
- self.db.set('extras-%s-%s' % (tenant_id, user_id), extras)
- return extras
+ session = self.get_session()
+ with session.begin():
+ extras_ref = session.query(Extras)\
+ .filter_by(user_id=user_id)\
+ .filter_by(tenant_id=tenant_id)\
+ .first()
+ data = extras_ref.data.copy()
+ for k in extras:
+ data[k] = extras[k]
+ extras_ref.data = data
+ return extras_ref
def delete_extras(self, user_id, tenant_id):
self.db.delete('extras-%s-%s' % (tenant_id, user_id))
@@ -336,15 +414,18 @@ class SqlIdentity(SqlBase):
return role
def update_role(self, id, role):
- self.db.set('role-%s' % id, role)
- return role
+ session = self.get_session()
+ with session.begin():
+ role_ref = session.query(Role).filter_by(id=id).first()
+ for k in role:
+ role_ref[k] = role[k]
+ return role_ref
def delete_role(self, id):
- self.db.delete('role-%s' % id)
- role_list = set(self.db.get('role_list', []))
- role_list.remove(id)
- self.db.set('role_list', list(role_list))
- return None
+ session = self.get_session()
+ role_ref = session.query(Role).filter_by(id=id).first()
+ with session.begin():
+ session.delete(role_ref)
class SqlToken(SqlBase):
diff --git a/keystonelight/keystone_compat.py b/keystonelight/keystone_compat.py
index b720477c..c909881d 100644
--- a/keystonelight/keystone_compat.py
+++ b/keystonelight/keystone_compat.py
@@ -511,8 +511,10 @@ class KeystoneTenantController(service.BaseApplication):
assert token_ref is not None
user_ref = token_ref['user']
+ tenant_ids = self.identity_api.get_tenants_for_user(
+ context, user_ref['id'])
tenant_refs = []
- for tenant_id in user_ref['tenants']:
+ for tenant_id in tenant_ids:
tenant_refs.append(self.identity_api.get_tenant(
context=context,
tenant_id=tenant_id))
@@ -537,9 +539,9 @@ class KeystoneTenantController(service.BaseApplication):
return {'tenant': tenant}
# CRUD Extension
- def create_tenant(self, context, **kw):
+ def create_tenant(self, context, tenant):
+ tenant_ref = self._normalize_dict(tenant)
self.assert_admin(context)
- tenant_ref = kw.get('tenant')
tenant_id = (tenant_ref.get('id')
and tenant_ref.get('id')
or uuid.uuid4().hex)
@@ -590,23 +592,21 @@ class KeystoneUserController(service.BaseApplication):
# NOTE(termie): i can't imagine that this really wants all the data
# about every single user in the system...
self.assert_admin(context)
- user_list = self.identity_api.list_users(context)
- return {'users': [{'id': x} for x in user_list]}
+ user_refs = self.identity_api.list_users(context)
+ return {'users': user_refs}
# CRUD extension
def create_user(self, context, user):
+ user = self._normalize_dict(user)
self.assert_admin(context)
- tenant_id = user.get('tenantId')
- tenants = []
- if tenant_id:
- tenants.append(tenant_id)
+ tenant_id = user.get('tenantId', None)
user_id = uuid.uuid4().hex
user_ref = user.copy()
- #user_ref.pop('tenantId', None)
user_ref['id'] = user_id
- user_ref['tenants'] = tenants
new_user_ref = self.identity_api.create_user(
context, user_id, user_ref)
+ if tenant_id:
+ self.identity_api.add_user_to_tenant(tenant_id, user_id)
return {'user': new_user_ref}
# NOTE(termie): this is really more of a patch than a put
@@ -656,6 +656,8 @@ class KeystoneRoleController(service.BaseApplication):
return {'role': role_ref}
def create_role(self, context, role):
+ role = self._normalize_dict(role)
+ self.assert_admin(context)
role_id = uuid.uuid4().hex
role['id'] = role_id
role_ref = self.identity_api.create_role(context, role_id, role)
@@ -669,8 +671,7 @@ class KeystoneRoleController(service.BaseApplication):
self.assert_admin(context)
roles = self.identity_api.list_roles(context)
# TODO(termie): probably inefficient at some point
- return {'roles': [self.identity_api.get_role(context, x)
- for x in roles]}
+ return {'roles': roles}
# COMPAT(diablo): CRUD extension
def get_role_refs(self, context, user_id):
diff --git a/keystonelight/service.py b/keystonelight/service.py
index 50e8377c..0f7dddfe 100644
--- a/keystonelight/service.py
+++ b/keystonelight/service.py
@@ -47,6 +47,13 @@ URLMAP = HIGH_LEVEL_CALLS.copy()
URLMAP.update(LOW_LEVEL_CALLS)
+class SmarterEncoder(json.JSONEncoder):
+ def default(self, obj):
+ if not isinstance(obj, dict) and hasattr(obj, 'iteritems'):
+ return dict(obj.iteritems())
+ return super(SmarterEncoder, self).default(obj)
+
+
class BaseApplication(wsgi.Application):
@webob.dec.wsgify
def __call__(self, req):
@@ -76,11 +83,18 @@ class BaseApplication(wsgi.Application):
elif isinstance(result, webob.exc.WSGIHTTPException):
return result
- return json.dumps(result)
+ return self._serialize(result)
+
+ def _serialize(self, result):
+ return json.dumps(result, cls=SmarterEncoder)
def _normalize_arg(self, arg):
return str(arg).replace(':', '_').replace('-', '_')
+ def _normalize_dict(self, d):
+ return dict([(self._normalize_arg(k), v)
+ for (k, v) in d.iteritems()])
+
def assert_admin(self, context):
if not context['is_admin']:
user_token_ref = self.token_api.get_token(
@@ -88,6 +102,7 @@ class BaseApplication(wsgi.Application):
creds = user_token_ref['extras'].copy()
creds['user_id'] = user_token_ref['user'].get('id')
creds['tenant_id'] = user_token_ref['tenant'].get('id')
+ print creds
# Accept either is_admin or the admin role
assert self.policy_api.can_haz(context,
('is_admin:1', 'roles:admin'),
diff --git a/keystonelight/test.py b/keystonelight/test.py
index 8af08880..1196b78f 100644
--- a/keystonelight/test.py
+++ b/keystonelight/test.py
@@ -8,9 +8,12 @@ import time
from paste import deploy
+from keystonelight import catalog
from keystonelight import config
+from keystonelight import identity
from keystonelight import logging
from keystonelight import models
+from keystonelight import token
from keystonelight import utils
from keystonelight import wsgi
@@ -114,20 +117,19 @@ class TestCase(unittest.TestCase):
# TODO(termie): doing something from json, probably based on Django's
# loaddata will be much preferred.
for tenant in fixtures.TENANTS:
- rv = self.identity_api.create_tenant(
- tenant['id'], models.Tenant(**tenant))
+ rv = self.identity_api.create_tenant(tenant['id'], tenant)
setattr(self, 'tenant_%s' % tenant['id'], rv)
for user in fixtures.USERS:
user_copy = user.copy()
tenants = user_copy.pop('tenants')
- rv = self.identity_api.create_user(user['id'], models.User(**user_copy))
+ rv = self.identity_api.create_user(user['id'], user_copy)
for tenant_id in tenants:
self.identity_api.add_user_to_tenant(tenant_id, user['id'])
setattr(self, 'user_%s' % user['id'], rv)
for role in fixtures.ROLES:
- rv = self.identity_api.create_role(role['id'], models.Role(**role))
+ rv = self.identity_api.create_role(role['id'], role)
setattr(self, 'role_%s' % role['id'], rv)
for extras in fixtures.EXTRAS:
@@ -137,7 +139,7 @@ class TestCase(unittest.TestCase):
del extras_ref['user_id']
del extras_ref['tenant_id']
rv = self.identity_api.create_extras(
- extras['user_id'], extras['tenant_id'], models.Extras(**extras_ref))
+ extras['user_id'], extras['tenant_id'], extras_ref)
setattr(self,
'extras_%s%s' % (extras['user_id'], extras['tenant_id']), rv)