diff options
| author | termie <github@anarkystic.com> | 2012-01-05 15:17:22 -0800 |
|---|---|---|
| committer | termie <github@anarkystic.com> | 2012-01-09 10:00:09 -0800 |
| commit | 119808d60247ebe59cf84f89e76a262732da2bd9 (patch) | |
| tree | cf94c3d47b2bd94e0cb4e364e46373fa10d99839 | |
| parent | 775b8ed73415716f55becd7d0c94b48113f148d5 (diff) | |
still wip, got migration mostly working
| -rw-r--r-- | keystonelight/backends/sql/__init__.py | 1 | ||||
| -rw-r--r-- | keystonelight/backends/sql/core.py (renamed from keystonelight/backends/sql.py) | 10 | ||||
| -rw-r--r-- | keystonelight/backends/sql/migrate_repo/README | 4 | ||||
| -rw-r--r-- | keystonelight/backends/sql/migrate_repo/__init__.py | 0 | ||||
| -rw-r--r-- | keystonelight/backends/sql/migrate_repo/manage.py | 5 | ||||
| -rw-r--r-- | keystonelight/backends/sql/migrate_repo/migrate.cfg | 25 | ||||
| -rw-r--r-- | keystonelight/backends/sql/migrate_repo/versions/001_add_initial_tables.py | 14 | ||||
| -rw-r--r-- | keystonelight/backends/sql/migrate_repo/versions/__init__.py | 0 | ||||
| -rw-r--r-- | keystonelight/backends/sql/migration.py | 74 | ||||
| -rw-r--r-- | tests/default.conf | 2 | ||||
| -rw-r--r-- | tests/test_backend_kvs.py | 4 | ||||
| -rw-r--r-- | tests/test_backend_sql.py | 154 |
12 files changed, 287 insertions, 6 deletions
diff --git a/keystonelight/backends/sql/__init__.py b/keystonelight/backends/sql/__init__.py new file mode 100644 index 00000000..38ecafd5 --- /dev/null +++ b/keystonelight/backends/sql/__init__.py @@ -0,0 +1 @@ +from keystonelight.backends.sql.core import * diff --git a/keystonelight/backends/sql.py b/keystonelight/backends/sql/core.py index 38dc57e4..2fee455f 100644 --- a/keystonelight/backends/sql.py +++ b/keystonelight/backends/sql/core.py @@ -27,6 +27,9 @@ class JsonBlob(sql_types.TypeDecorator): class DictBase(object): + def to_dict(self): + return dict(self.iteritems()) + def __setitem__(self, key, value): setattr(self, key, value) @@ -37,7 +40,7 @@ class DictBase(object): return getattr(self, key, default) def __iter__(self): - self._i = iter(object_mapper(self).columns) + self._i = iter(sqlalchemy.orm.object_mapper(self).columns) return self def next(self): @@ -186,7 +189,7 @@ 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 models.Tenant(**tenant_ref) + return tenant_ref def get_tenant_by_name(self, tenant_name): tenant_ref = self.db.get('tenant_name-%s' % tenant_name) @@ -195,7 +198,7 @@ class SqlIdentity(SqlBase): def get_user(self, user_id): session = self.get_session() user_ref = session.query(User).filter_by(id=user_id).first() - return models.User(**user_ref) + return user_ref def get_user_by_name(self, user_name): user_ref = self.db.get('user_name-%s' % user_name) @@ -261,6 +264,7 @@ class SqlIdentity(SqlBase): def create_user(self, id, user): session = self.get_session() session.add(User(**user)) + session.flush() #self.db.set('user-%s' % id, user) #self.db.set('user_name-%s' % user['name'], user) #user_list = set(self.db.get('user_list', [])) diff --git a/keystonelight/backends/sql/migrate_repo/README b/keystonelight/backends/sql/migrate_repo/README new file mode 100644 index 00000000..6218f8ca --- /dev/null +++ b/keystonelight/backends/sql/migrate_repo/README @@ -0,0 +1,4 @@ +This is a database migration repository. + +More information at +http://code.google.com/p/sqlalchemy-migrate/ diff --git a/keystonelight/backends/sql/migrate_repo/__init__.py b/keystonelight/backends/sql/migrate_repo/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/keystonelight/backends/sql/migrate_repo/__init__.py diff --git a/keystonelight/backends/sql/migrate_repo/manage.py b/keystonelight/backends/sql/migrate_repo/manage.py new file mode 100644 index 00000000..39fa3892 --- /dev/null +++ b/keystonelight/backends/sql/migrate_repo/manage.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python +from migrate.versioning.shell import main + +if __name__ == '__main__': + main(debug='False') diff --git a/keystonelight/backends/sql/migrate_repo/migrate.cfg b/keystonelight/backends/sql/migrate_repo/migrate.cfg new file mode 100644 index 00000000..a8be6089 --- /dev/null +++ b/keystonelight/backends/sql/migrate_repo/migrate.cfg @@ -0,0 +1,25 @@ +[db_settings] +# Used to identify which repository this database is versioned under. +# You can use the name of your project. +repository_id=keystone + +# The name of the database table used to track the schema version. +# This name shouldn't already be used by your project. +# If this is changed once a database is under version control, you'll need to +# change the table name in each database too. +version_table=migrate_version + +# When committing a change script, Migrate will attempt to generate the +# sql for all supported databases; normally, if one of them fails - probably +# because you don't have that database installed - it is ignored and the +# commit continues, perhaps ending successfully. +# Databases in this list MUST compile successfully during a commit, or the +# entire commit will fail. List the databases your application will actually +# be using to ensure your updates to that database work properly. +# This must be a list; example: ['postgres','sqlite'] +required_dbs=[] + +# When creating new change scripts, Migrate will stamp the new script with +# a version number. By default this is latest_version + 1. You can set this +# to 'true' to tell Migrate to use the UTC timestamp instead. +use_timestamp_numbering=False diff --git a/keystonelight/backends/sql/migrate_repo/versions/001_add_initial_tables.py b/keystonelight/backends/sql/migrate_repo/versions/001_add_initial_tables.py new file mode 100644 index 00000000..e5410694 --- /dev/null +++ b/keystonelight/backends/sql/migrate_repo/versions/001_add_initial_tables.py @@ -0,0 +1,14 @@ +from sqlalchemy import * +from migrate import * + +from keystonelight.backends import sql + +def upgrade(migrate_engine): + # Upgrade operations go here. Don't create your own engine; bind + # migrate_engine to your metadata + sql.Base.metadata.create_all(migrate_engine) + + +def downgrade(migrate_engine): + # Operations to reverse the above upgrade go here. + pass diff --git a/keystonelight/backends/sql/migrate_repo/versions/__init__.py b/keystonelight/backends/sql/migrate_repo/versions/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/keystonelight/backends/sql/migrate_repo/versions/__init__.py diff --git a/keystonelight/backends/sql/migration.py b/keystonelight/backends/sql/migration.py new file mode 100644 index 00000000..1a4794b7 --- /dev/null +++ b/keystonelight/backends/sql/migration.py @@ -0,0 +1,74 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import os +import sys + +import sqlalchemy +from migrate.versioning import api as versioning_api + +try: + from migrate.versioning import exceptions as versioning_exceptions +except ImportError: + try: + # python-migration changed location of exceptions after 1.6.3 + # See LP Bug #717467 + from migrate import exceptions as versioning_exceptions + except ImportError: + sys.exit("python-migrate is not installed. Exiting.") + + +def db_sync(options, version=None): + if version is not None: + try: + version = int(version) + except ValueError: + raise Exception("version should be an integer") + + current_version = db_version(options) + repo_path = _find_migrate_repo() + if version is None or version > current_version: + return versioning_api.upgrade( + options.get('sql_connection'), repo_path, version) + else: + return versioning_api.downgrade( + options.get('sql_connection'), repo_path, version) + + +def db_version(options): + repo_path = _find_migrate_repo() + try: + return versioning_api.db_version( + options.get('sql_connection'), repo_path) + except versioning_exceptions.DatabaseNotControlledError: + return db_version_control(options, 0) + + +def db_version_control(options, version=None): + repo_path = _find_migrate_repo() + versioning_api.version_control( + options.get('sql_connection'), repo_path, version) + return version + + +def _find_migrate_repo(): + """Get the path for the migrate repository.""" + path = os.path.join(os.path.abspath(os.path.dirname(__file__)), + 'migrate_repo') + assert os.path.exists(path) + return path diff --git a/tests/default.conf b/tests/default.conf index 766b569e..295fe6ff 100644 --- a/tests/default.conf +++ b/tests/default.conf @@ -22,7 +22,7 @@ catalog.RegionOne.compute.internalURL = http://localhost:$(compute_port)s/v1.1/$ catalog.RegionOne.compute.name = 'Compute Service' # for sql backends -sql_connection = sqlite:///:memory: +sql_connection = sqlite:///bla.db sql_idle_timeout = 200 sql_min_pool_size = 5 sql_max_pool_size = 10 diff --git a/tests/test_backend_kvs.py b/tests/test_backend_kvs.py index c88effdd..5c644d10 100644 --- a/tests/test_backend_kvs.py +++ b/tests/test_backend_kvs.py @@ -11,8 +11,8 @@ class KvsIdentity(test.TestCase): def setUp(self): super(KvsIdentity, self).setUp() self.options = self.appconfig('default') - self.identity_api = kvs.KvsIdentity(options=self.options, db={}) - self.load_fixtures(default_fixtures) + #self.identity_api = kvs.KvsIdentity(options=self.options, db={}) + #self.load_fixtures(default_fixtures) def test_authenticate_bad_user(self): self.assertRaises(AssertionError, diff --git a/tests/test_backend_sql.py b/tests/test_backend_sql.py new file mode 100644 index 00000000..96f71eb6 --- /dev/null +++ b/tests/test_backend_sql.py @@ -0,0 +1,154 @@ +import os +import uuid + +from keystonelight import models +from keystonelight import test +from keystonelight.backends import sql +from keystonelight.backends.sql import migration + +import test_backend_kvs +import default_fixtures + + +class SqlIdentity(test_backend_kvs.KvsIdentity): + def setUp(self): + super(SqlIdentity, self).setUp() + self.options = self.appconfig('default') + os.unlink('bla.db') + migration.db_sync(self.options, 1) + self.identity_api = sql.SqlIdentity(options=self.options) + self.load_fixtures(default_fixtures) + + def test_authenticate_bad_user(self): + self.assertRaises(AssertionError, + self.identity_api.authenticate, + user_id=self.user_foo['id'] + 'WRONG', + tenant_id=self.tenant_bar['id'], + password=self.user_foo['password']) + + def test_authenticate_bad_password(self): + self.assertRaises(AssertionError, + self.identity_api.authenticate, + user_id=self.user_foo['id'], + tenant_id=self.tenant_bar['id'], + password=self.user_foo['password'] + 'WRONG') + + def test_authenticate_invalid_tenant(self): + self.assertRaises(AssertionError, + self.identity_api.authenticate, + user_id=self.user_foo['id'], + tenant_id=self.tenant_bar['id'] + 'WRONG', + password=self.user_foo['password']) + + def test_authenticate_no_tenant(self): + user_ref, tenant_ref, extras_ref = self.identity_api.authenticate( + user_id=self.user_foo['id'], + password=self.user_foo['password']) + self.assertDictEquals(user_ref, self.user_foo) + self.assert_(tenant_ref is None) + self.assert_(not extras_ref) + + def test_authenticate(self): + user_ref, tenant_ref, extras_ref = self.identity_api.authenticate( + user_id=self.user_foo['id'], + tenant_id=self.tenant_bar['id'], + password=self.user_foo['password']) + self.assertDictEquals(user_ref, self.user_foo) + self.assertDictEquals(tenant_ref, self.tenant_bar) + self.assertDictEquals(extras_ref, self.extras_foobar) + + def test_get_tenant_bad_tenant(self): + tenant_ref = self.identity_api.get_tenant( + tenant_id=self.tenant_bar['id'] + 'WRONG') + self.assert_(tenant_ref is None) + + def test_get_tenant(self): + tenant_ref = self.identity_api.get_tenant(tenant_id=self.tenant_bar['id']) + self.assertDictEquals(tenant_ref, self.tenant_bar) + + def test_get_tenant_by_name_bad_tenant(self): + tenant_ref = self.identity_api.get_tenant( + tenant_id=self.tenant_bar['name'] + 'WRONG') + self.assert_(tenant_ref is None) + + def test_get_tenant_by_name(self): + tenant_ref = self.identity_api.get_tenant_by_name( + tenant_name=self.tenant_bar['name']) + self.assertDictEquals(tenant_ref, self.tenant_bar) + + def test_get_user_bad_user(self): + user_ref = self.identity_api.get_user( + user_id=self.user_foo['id'] + 'WRONG') + self.assert_(user_ref is None) + + def test_get_user(self): + user_ref = self.identity_api.get_user(user_id=self.user_foo['id']) + self.assertDictEquals(user_ref, self.user_foo) + + def test_get_extras_bad_user(self): + extras_ref = self.identity_api.get_extras( + user_id=self.user_foo['id'] + 'WRONG', + tenant_id=self.tenant_bar['id']) + self.assert_(extras_ref is None) + + def test_get_extras_bad_tenant(self): + extras_ref = self.identity_api.get_extras( + user_id=self.user_foo['id'], + tenant_id=self.tenant_bar['id'] + 'WRONG') + self.assert_(extras_ref is None) + + def test_get_extras(self): + extras_ref = self.identity_api.get_extras( + user_id=self.user_foo['id'], + tenant_id=self.tenant_bar['id']) + self.assertDictEquals(extras_ref, self.extras_foobar) + + def test_get_role(self): + role_ref = self.identity_api.get_role( + role_id=self.role_keystone_admin['id']) + self.assertDictEquals(role_ref, self.role_keystone_admin) + + +class SqlToken(test_backend_kvs.KvsToken): + def setUp(self): + super(SqlToken, self).setUp() + self.token_api = sql.SqlToken(options=options) + self.load_fixtures(default_fixtures) + + def test_token_crud(self): + token_id = uuid.uuid4().hex + data = {'id': token_id, + 'a': 'b'} + data_ref = self.token_api.create_token(token_id, data) + self.assertDictEquals(data_ref, data) + + new_data_ref = self.token_api.get_token(token_id) + self.assertEquals(new_data_ref, data) + + self.token_api.delete_token(token_id) + deleted_data_ref = self.token_api.get_token(token_id) + self.assert_(deleted_data_ref is None) + + +class SqlCatalog(test_backend_kvs.KvsCatalog): + def setUp(self): + super(SqlCatalog, self).setUp() + self.catalog_api = sql.SqlCatalog(options=options) + self._load_fixtures() + + def _load_fixtures(self): + self.catalog_foobar = self.catalog_api._create_catalog( + 'foo', 'bar', + {'RegionFoo': {'service_bar': {'foo': 'bar'}}}) + + def test_get_catalog_bad_user(self): + catalog_ref = self.catalog_api.get_catalog('foo' + 'WRONG', 'bar') + self.assert_(catalog_ref is None) + + def test_get_catalog_bad_tenant(self): + catalog_ref = self.catalog_api.get_catalog('foo', 'bar' + 'WRONG') + self.assert_(catalog_ref is None) + + def test_get_catalog(self): + catalog_ref = self.catalog_api.get_catalog('foo', 'bar') + self.assertDictEquals(catalog_ref, self.catalog_foobar) |
