Browse Source

config system overhaul

we're now based on nova's config system which mainly means that you will
have to call config.CONF with a config file at some point during tests
or running an executable
changes/73/3573/1
termie 10 years ago
parent
commit
feadf75760
  1. 8
      keystonelight/backends/kvs.py
  2. 6
      keystonelight/backends/policy.py
  3. 34
      keystonelight/backends/sql/core.py
  4. 24
      keystonelight/backends/sql/migration.py
  5. 25
      keystonelight/backends/templated.py
  6. 10
      keystonelight/catalog.py
  7. 49
      keystonelight/config.py
  8. 11
      keystonelight/identity.py
  9. 103
      keystonelight/keystone_compat.py
  10. 6
      keystonelight/middleware.py
  11. 10
      keystonelight/policy.py
  12. 25
      keystonelight/service.py
  13. 58
      keystonelight/test.py
  14. 10
      keystonelight/token.py
  15. 12
      keystonelight/wsgi.py
  16. 42
      tests/default.conf
  17. 12
      tests/default_catalog.templates
  18. 17
      tests/keystone_compat_diablo.conf
  19. 36
      tests/keystoneclient_compat_master.conf
  20. 9
      tests/test_backend_kvs.py
  21. 20
      tests/test_backend_sql.py
  22. 12
      tests/test_identity_api.py
  23. 9
      tests/test_keystoneclient_compat.py
  24. 35
      tests/test_legacy_compat.py
  25. 6
      tests/test_novaclient_compat.py

8
keystonelight/backends/kvs.py

@ -10,7 +10,7 @@ INMEMDB = DictKvs()
class KvsIdentity(object):
def __init__(self, options, db=None):
def __init__(self, db=None):
if db is None:
db = INMEMDB
elif type(db) is type({}):
@ -189,7 +189,7 @@ class KvsIdentity(object):
class KvsToken(object):
def __init__(self, options, db=None):
def __init__(self, db=None):
if db is None:
db = INMEMDB
elif type(db) is type({}):
@ -209,7 +209,7 @@ class KvsToken(object):
class KvsCatalog(object):
def __init__(self, options, db=None):
def __init__(self, db=None):
if db is None:
db = INMEMDB
elif type(db) is type({}):
@ -251,7 +251,7 @@ class KvsCatalog(object):
class KvsPolicy(object):
def __init__(self, options, db=None):
def __init__(self, db=None):
if db is None:
db = INMEMDB
elif type(db) is type({}):

6
keystonelight/backends/policy.py

@ -2,17 +2,11 @@ import logging
class TrivialTrue(object):
def __init__(self, options):
self.options = options
def can_haz(self, target, credentials):
return True
class SimpleMatch(object):
def __init__(self, options):
self.options = options
def can_haz(self, target, credentials):
"""Check whether key-values in target are present in credentials."""
# TODO(termie): handle ANDs, probably by providing a tuple instead of a

34
keystonelight/backends/sql/core.py

@ -10,9 +10,13 @@ import sqlalchemy.orm
import sqlalchemy.pool
import sqlalchemy.engine.url
from keystonelight import config
from keystonelight import models
CONF = config.CONF
Base = declarative.declarative_base()
@ -121,9 +125,6 @@ class SqlBase(object):
_MAKER = None
_ENGINE = None
def __init__(self, options):
self.options = options
def get_session(self, autocommit=True, expire_on_commit=False):
"""Return a SQLAlchemy session."""
if self._MAKER is None or self._ENGINE is None:
@ -138,36 +139,17 @@ class SqlBase(object):
def get_engine(self):
"""Return a SQLAlchemy engine."""
connection_dict = sqlalchemy.engine.url.make_url(
self.options.get('sql_connection'))
connection_dict = sqlalchemy.engine.url.make_url(CONF.sql.connection)
engine_args = {
"pool_recycle": self.options.get('sql_idle_timeout'),
"pool_recycle": CONF.sql.idle_timeout,
"echo": False,
}
if "sqlite" in connection_dict.drivername:
engine_args["poolclass"] = sqlalchemy.pool.NullPool
#elif MySQLdb and "mysql" in connection_dict.drivername:
# LOG.info(_("Using mysql/eventlet db_pool."))
# # MySQLdb won't accept 'None' in the password field
# password = connection_dict.password or ''
# pool_args = {
# "db": connection_dict.database,
# "passwd": password,
# "host": connection_dict.host,
# "user": connection_dict.username,
# "min_size": self.options.get('sql_min_pool_size'),
# "max_size": self.options.get('sql_max_pool_size'),
# "max_idle": self.options.get('sql_idle_timeout'),
# }
# creator = eventlet.db_pool.ConnectionPool(MySQLdb, **pool_args)
# engine_args["pool_size"] = self.options.get('sql_max_pool_size')
# engine_args["pool_timeout"] = self.options('sql_pool_timeout')
# engine_args["creator"] = creator.create
return sql.create_engine(self.options.get('sql_connection'),
**engine_args)
return sql.create_engine(CONF.sql.connection, **engine_args)
def get_maker(self, engine, autocommit=True, expire_on_commit=False):
"""Return a SQLAlchemy sessionmaker using the given engine."""

24
keystonelight/backends/sql/migration.py

@ -22,6 +22,12 @@ import sys
import sqlalchemy
from migrate.versioning import api as versioning_api
from keystonelight import config
CONF = config.CONF
try:
from migrate.versioning import exceptions as versioning_exceptions
except ImportError:
@ -33,36 +39,36 @@ except ImportError:
sys.exit("python-migrate is not installed. Exiting.")
def db_sync(options, version=None):
def db_sync(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)
current_version = db_version()
repo_path = _find_migrate_repo()
if version is None or version > current_version:
return versioning_api.upgrade(
options.get('sql_connection'), repo_path, version)
CONF.sql.connection, repo_path, version)
else:
return versioning_api.downgrade(
options.get('sql_connection'), repo_path, version)
CONF.sql.connection, repo_path, version)
def db_version(options):
def db_version():
repo_path = _find_migrate_repo()
try:
return versioning_api.db_version(
options.get('sql_connection'), repo_path)
CONF.sql.connection, repo_path)
except versioning_exceptions.DatabaseNotControlledError:
return db_version_control(options, 0)
return db_version_control(0)
def db_version_control(options, version=None):
def db_version_control(version=None):
repo_path = _find_migrate_repo()
versioning_api.version_control(
options.get('sql_connection'), repo_path, version)
CONF.sql.connection, repo_path, version)
return version

25
keystonelight/backends/templated.py

@ -1,7 +1,12 @@
from keystonelight import config
from keystonelight import logging
from keystonelight.backends import kvs
CONF = config.CONF
config.register_str('template_file', group='catalog')
class TemplatedCatalog(kvs.KvsCatalog):
"""A backend that generates endpoints for the Catalog based on templates.
@ -16,7 +21,7 @@ class TemplatedCatalog(kvs.KvsCatalog):
http://localhost:$(public_port)s/
When expanding the template it will pass in a dict made up of the options
When expanding the template it will pass in a dict made up of the conf
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
@ -31,19 +36,21 @@ class TemplatedCatalog(kvs.KvsCatalog):
"""
def __init__(self, options, templates=None):
self.options = options
def __init__(self, templates=None):
if templates:
self.templates = templates
else:
self._load_templates(options)
self._load_templates(CONF.catalog.template_file)
super(TemplatedCatalog, self).__init__(options)
super(TemplatedCatalog, self).__init__()
def _load_templates(self, options):
def _load_templates(self, template_file):
o = {}
for k, v in options.iteritems():
for line in open(template_file):
if ' = ' not in line:
continue
k, v = line.split(' = ')
if not k.startswith('catalog.'):
continue
@ -64,7 +71,7 @@ class TemplatedCatalog(kvs.KvsCatalog):
self.templates = o
def get_catalog(self, user_id, tenant_id, extras=None):
d = self.options.copy()
d = dict(CONF.iteritems())
d.update({'tenant_id': tenant_id,
'user_id': user_id})

10
keystonelight/catalog.py

@ -2,14 +2,16 @@
# the catalog interfaces
from keystonelight import config
from keystonelight import utils
CONF = config.CONF
class Manager(object):
def __init__(self, options):
self.options = options
self.driver = utils.import_object(options['catalog_driver'],
options=options)
def __init__(self):
self.driver = utils.import_object(CONF.catalog.driver)
def get_catalog(self, context, user_id, tenant_id, extras=None):
"""Return info for a catalog if it is valid."""

49
keystonelight/config.py

@ -0,0 +1,49 @@
from keystonelight import cfg
class Config(cfg.ConfigOpts):
def __call__(self, config_files=None, *args, **kw):
if config_files is None:
config_files = []
self.config_file = config_files
super(Config, self).__call__(*args, **kw)
def __getitem__(self, key, default=None):
return getattr(self, key, default)
def __setitem__(self, key, value):
return setattr(self, key, value)
def iteritems(self):
for k in self._opts:
yield (k, getattr(self, k))
def register_str(*args, **kw):
group = kw.pop('group', None)
if group:
CONF.register_group(cfg.OptGroup(name=group))
return CONF.register_opt(cfg.StrOpt(*args, **kw), group=group)
CONF = Config()
register_str('admin_token', default='ADMIN')
register_str('compute_port')
register_str('admin_port')
register_str('public_port')
# sql options
register_str('connection', group='sql')
register_str('idle_timeout', group='sql')
register_str('min_pool_size', group='sql')
register_str('maz_pool_size', group='sql')
register_str('pool_timeout', group='sql')
register_str('driver', group='catalog')
register_str('driver', group='identity')
register_str('driver', group='policy')
register_str('driver', group='token')

11
keystonelight/identity.py

@ -2,15 +2,16 @@
# backends will make use of them to return something that conforms to their
# apis
from keystonelight import config
from keystonelight import utils
CONF = config.CONF
class Manager(object):
def __init__(self, options):
self.driver = utils.import_object(options['identity_driver'],
options=options)
self.options = options
def __init__(self):
self.driver = utils.import_object(CONF.identity.driver)
def authenticate(self, context, **kwargs):
"""Passthru authentication to the identity driver.

103
keystonelight/keystone_compat.py

@ -18,13 +18,11 @@ from keystonelight import wsgi
class KeystoneAdminRouter(wsgi.Router):
def __init__(self, options):
self.options = options
def __init__(self):
mapper = routes.Mapper()
# Token Operations
auth_controller = KeystoneTokenController(self.options)
auth_controller = KeystoneTokenController()
mapper.connect('/tokens',
controller=auth_controller,
action='authenticate',
@ -39,7 +37,7 @@ class KeystoneAdminRouter(wsgi.Router):
conditions=dict(method=['GET']))
# Tenant Operations
tenant_controller = KeystoneTenantController(self.options)
tenant_controller = KeystoneTenantController()
mapper.connect('/tenants',
controller=tenant_controller,
action='get_tenants_for_token',
@ -50,14 +48,14 @@ class KeystoneAdminRouter(wsgi.Router):
conditions=dict(method=['GET']))
# User Operations
user_controller = KeystoneUserController(self.options)
user_controller = KeystoneUserController()
mapper.connect('/users/{user_id}',
controller=user_controller,
action='get_user',
conditions=dict(method=['GET']))
# Role Operations
roles_controller = KeystoneRoleController(self.options)
roles_controller = KeystoneRoleController()
mapper.connect('/tenants/{tenant_id}/users/{user_id}/roles',
controller=roles_controller,
action='get_user_roles',
@ -68,13 +66,13 @@ class KeystoneAdminRouter(wsgi.Router):
conditions=dict(method=['GET']))
# Miscellaneous Operations
version_controller = KeystoneVersionController(self.options)
version_controller = KeystoneVersionController()
mapper.connect('/',
controller=version_controller,
action='get_version_info', module='admin/version',
conditions=dict(method=['GET']))
extensions_controller = KeystoneExtensionsController(self.options)
extensions_controller = KeystoneExtensionsController()
mapper.connect('/extensions',
controller=extensions_controller,
action='get_extensions_info',
@ -84,12 +82,11 @@ class KeystoneAdminRouter(wsgi.Router):
class KeystoneServiceRouter(wsgi.Router):
def __init__(self, options):
self.options = options
def __init__(self):
mapper = routes.Mapper()
# Token Operations
auth_controller = KeystoneTokenController(self.options)
auth_controller = KeystoneTokenController()
mapper.connect('/tokens',
controller=auth_controller,
action='authenticate',
@ -100,21 +97,21 @@ class KeystoneServiceRouter(wsgi.Router):
conditions=dict(methods=['POST']))
# Tenant Operations
tenant_controller = KeystoneTenantController(self.options)
tenant_controller = KeystoneTenantController()
mapper.connect('/tenants',
controller=tenant_controller,
action='get_tenants_for_token',
conditions=dict(methods=['GET']))
# Miscellaneous
version_controller = KeystoneVersionController(self.options)
version_controller = KeystoneVersionController()
mapper.connect('/',
controller=version_controller,
action='get_version_info',
module='service/version',
conditions=dict(method=['GET']))
extensions_controller = KeystoneExtensionsController(self.options)
extensions_controller = KeystoneExtensionsController()
mapper.connect('/extensions',
controller=extensions_controller,
action='get_extensions_info',
@ -130,13 +127,12 @@ class KeystoneAdminCrudExtension(wsgi.ExtensionRouter):
"""
def __init__(self, application, options):
self.options = options
def __init__(self, application):
mapper = routes.Mapper()
tenant_controller = KeystoneTenantController(self.options)
user_controller = KeystoneUserController(self.options)
role_controller = KeystoneRoleController(self.options)
service_controller = KeystoneServiceController(self.options)
tenant_controller = KeystoneTenantController()
user_controller = KeystoneUserController()
role_controller = KeystoneRoleController()
service_controller = KeystoneServiceController()
# Tenant Operations
mapper.connect("/tenants", controller=tenant_controller,
@ -270,16 +266,15 @@ class KeystoneAdminCrudExtension(wsgi.ExtensionRouter):
conditions=dict(method=["DELETE"]))
super(KeystoneAdminCrudExtension, self).__init__(
application, options, mapper)
application, mapper)
class KeystoneTokenController(service.BaseApplication):
def __init__(self, options):
self.options = options
self.catalog_api = catalog.Manager(options)
self.identity_api = identity.Manager(options)
self.token_api = token.Manager(options)
self.policy_api = policy.Manager(options)
def __init__(self):
self.catalog_api = catalog.Manager()
self.identity_api = identity.Manager()
self.token_api = token.Manager()
self.policy_api = policy.Manager()
super(KeystoneTokenController, self).__init__()
def authenticate(self, context, auth=None):
@ -496,11 +491,10 @@ class KeystoneTokenController(service.BaseApplication):
class KeystoneTenantController(service.BaseApplication):
def __init__(self, options):
self.options = options
self.identity_api = identity.Manager(options)
self.policy_api = policy.Manager(options)
self.token_api = token.Manager(options)
def __init__(self):
self.identity_api = identity.Manager()
self.policy_api = policy.Manager()
self.token_api = token.Manager()
super(KeystoneTenantController, self).__init__()
def get_tenants_for_token(self, context, **kw):
@ -578,12 +572,11 @@ class KeystoneTenantController(service.BaseApplication):
class KeystoneUserController(service.BaseApplication):
def __init__(self, options):
self.options = options
self.catalog_api = catalog.Manager(options)
self.identity_api = identity.Manager(options)
self.token_api = token.Manager(options)
self.policy_api = policy.Manager(options)
def __init__(self):
self.catalog_api = catalog.Manager()
self.identity_api = identity.Manager()
self.policy_api = policy.Manager()
self.token_api = token.Manager()
super(KeystoneUserController, self).__init__()
def get_user(self, context, user_id):
@ -644,12 +637,11 @@ class KeystoneUserController(service.BaseApplication):
class KeystoneRoleController(service.BaseApplication):
def __init__(self, options):
self.options = options
self.catalog_api = catalog.Manager(options)
self.identity_api = identity.Manager(options)
self.token_api = token.Manager(options)
self.policy_api = policy.Manager(options)
def __init__(self):
self.catalog_api = catalog.Manager()
self.identity_api = identity.Manager()
self.token_api = token.Manager()
self.policy_api = policy.Manager()
super(KeystoneRoleController, self).__init__()
def get_user_roles(self, context, user_id, tenant_id=None):
@ -748,12 +740,11 @@ class KeystoneRoleController(service.BaseApplication):
class KeystoneServiceController(service.BaseApplication):
def __init__(self, options):
self.options = options
self.catalog_api = catalog.Manager(options)
self.identity_api = identity.Manager(options)
self.token_api = token.Manager(options)
self.policy_api = policy.Manager(options)
def __init__(self):
self.catalog_api = catalog.Manager()
self.identity_api = identity.Manager()
self.token_api = token.Manager()
self.policy_api = policy.Manager()
super(KeystoneServiceController, self).__init__()
# CRUD extensions
@ -783,8 +774,7 @@ class KeystoneServiceController(service.BaseApplication):
class KeystoneVersionController(service.BaseApplication):
def __init__(self, options):
self.options = options
def __init__(self):
super(KeystoneVersionController, self).__init__()
def get_version_info(self, context, module='version'):
@ -792,8 +782,7 @@ class KeystoneVersionController(service.BaseApplication):
class KeystoneExtensionsController(service.BaseApplication):
def __init__(self, options):
self.options = options
def __init__(self):
super(KeystoneExtensionsController, self).__init__()
def get_extensions_info(self, context):
@ -803,10 +792,10 @@ class KeystoneExtensionsController(service.BaseApplication):
def service_app_factory(global_conf, **local_conf):
conf = global_conf.copy()
conf.update(local_conf)
return KeystoneServiceRouter(conf)
return KeystoneServiceRouter()
def admin_app_factory(global_conf, **local_conf):
conf = global_conf.copy()
conf.update(local_conf)
return KeystoneAdminRouter(conf)
return KeystoneAdminRouter()

6
keystonelight/middleware.py

@ -1,8 +1,12 @@
import json
from keystonelight import config
from keystonelight import wsgi
CONF = config.CONF
# Header used to transmit the auth token
AUTH_TOKEN_HEADER = 'X-Auth-Token'
@ -34,7 +38,7 @@ class AdminTokenAuthMiddleware(wsgi.Middleware):
def process_request(self, request):
token = request.headers.get(AUTH_TOKEN_HEADER)
context = request.environ.get(CONTEXT_ENV, {})
context['is_admin'] = (token == self.options['admin_token'])
context['is_admin'] = (token == CONF.admin_token)
request.environ[CONTEXT_ENV] = context

10
keystonelight/policy.py

@ -4,14 +4,16 @@
import uuid
from keystonelight import config
from keystonelight import utils
CONF = config.CONF
class Manager(object):
def __init__(self, options):
self.options = options
self.driver = utils.import_object(options['policy_driver'],
options=options)
def __init__(self):
self.driver = utils.import_object(CONF.policy.driver)
def can_haz(self, context, target, credentials):
"""Check whether the given creds can perform action on target."""

25
keystonelight/service.py

@ -97,9 +97,8 @@ class BaseApplication(wsgi.Application):
class TokenController(BaseApplication):
"""Validate and pass through calls to TokenManager."""
def __init__(self, options):
self.token_api = token.Manager(options=options)
self.options = options
def __init__(self):
self.token_api = token.Manager()
def validate_token(self, context, token_id):
token_info = self.token_api.validate_token(context, token_id)
@ -115,10 +114,9 @@ class IdentityController(BaseApplication):
a specific driver.
"""
def __init__(self, options):
self.identity_api = identity.Manager(options=options)
self.token_api = token.Manager(options=options)
self.options = options
def __init__(self):
self.identity_api = identity.Manager()
self.token_api = token.Manager()
def noop(self, context, *args, **kw):
return ''
@ -207,10 +205,9 @@ class IdentityController(BaseApplication):
class Router(wsgi.Router):
def __init__(self, options):
self.options = options
self.identity_controller = IdentityController(options)
self.token_controller = TokenController(options)
def __init__(self):
self.identity_controller = IdentityController()
self.token_controller = TokenController()
mapper = self._build_map(URLMAP)
mapper.connect('/', controller=self.identity_controller, action='noop')
@ -238,6 +235,6 @@ class Router(wsgi.Router):
def app_factory(global_conf, **local_conf):
conf = global_conf.copy()
conf.update(local_conf)
return Router(conf)
#conf = global_conf.copy()
#conf.update(local_conf)
return Router()

58
keystonelight/test.py

@ -8,6 +8,7 @@ import time
from paste import deploy
from keystonelight import config
from keystonelight import logging
from keystonelight import models
from keystonelight import utils
@ -17,7 +18,7 @@ from keystonelight import wsgi
ROOTDIR = os.path.dirname(os.path.dirname(__file__))
VENDOR = os.path.join(ROOTDIR, 'vendor')
TESTSDIR = os.path.join(ROOTDIR, 'tests')
CONF = config.CONF
cd = os.chdir
@ -94,21 +95,14 @@ class TestCase(unittest.TestCase):
for path in self._paths:
if path in sys.path:
sys.path.remove(path)
CONF.reset()
super(TestCase, self).tearDown()
#TODO(termie): probably make this take an argument and use that for `options`
def load_backends(self):
"""Hacky shortcut to load the backends for data manipulation.
Expects self.options to have already been set.
"""
self.identity_api = utils.import_object(
self.options['identity_driver'], options=self.options)
self.token_api = utils.import_object(
self.options['token_driver'], options=self.options)
self.catalog_api = utils.import_object(
self.options['catalog_driver'], options=self.options)
"""Hacky shortcut to load the backends for data manipulation."""
self.identity_api = utils.import_object(CONF.identity.driver)
self.token_api = utils.import_object(CONF.token.driver)
self.catalog_api = utils.import_object(CONF.catalog.driver)
def load_fixtures(self, fixtures):
"""Hacky basic and naive fixture loading based on a python module.
@ -164,44 +158,10 @@ class TestCase(unittest.TestCase):
# Service catalog tests need to know the port we ran on.
port = server.socket_info['socket'][1]
self._update_server_options(server, 'public_port', port)
self._update_server_options(server, 'admin_port', port)
CONF.public_port = port
CONF.admin_port = port
return server
def _update_server_options(self, server, key, value):
"""Hack to allow us to make changes to the options used by backends.
A possible better solution would be to have a global config registry.
"""
last = server
applications = []
while (hasattr(last, 'applications')
or hasattr(last, 'application')
or hasattr(last, 'options')):
#logging.debug('UPDATE %s: O %s A %s AS %s',
# last.__class__,
# getattr(last, 'options', None),
# getattr(last, 'application', None),
# getattr(last, 'applications', None))
if hasattr(last, 'options'):
last.options[key] = value
# NOTE(termie): paste.urlmap.URLMap stores applications in this format
if hasattr(last, 'applications'):
for app in last.applications:
applications.append(app[1])
if hasattr(last, 'application'):
last = last.application
elif len(applications):
last = applications.pop()
else:
break
def client(self, app, *args, **kw):
return TestClient(app, *args, **kw)

10
keystonelight/token.py

@ -4,15 +4,17 @@
import uuid
from keystonelight import config
from keystonelight import logging
from keystonelight import utils
CONF = config.CONF
class Manager(object):
def __init__(self, options):
self.options = options
self.driver = utils.import_object(options['token_driver'],
options=options)
def __init__(self):
self.driver = utils.import_object(CONF.token.driver)
def create_token(self, context, data):
token = uuid.uuid4().hex

12
keystonelight/wsgi.py

@ -107,7 +107,7 @@ class Application(object):
but using the kwarg passing it shouldn't be necessary.
"""
return cls(**local_config)
return cls()
def __call__(self, environ, start_response):
r"""Subclasses will probably want to implement __call__ like this:
@ -182,12 +182,11 @@ class Middleware(Application):
def _factory(app):
conf = global_config.copy()
conf.update(local_config)
return cls(app, conf)
return cls(app)
return _factory
def __init__(self, application, options):
def __init__(self, application):
self.application = application
self.options = options
def process_request(self, req):
"""Called on each request.
@ -315,8 +314,7 @@ class ExtensionRouter(Router):
Expects to be subclassed.
"""
def __init__(self, application, options, mapper):
self.options = options
def __init__(self, application, mapper):
self.application = application
mapper.connect('{path_info:.*}', controller=self.application)
@ -348,5 +346,5 @@ class ExtensionRouter(Router):
def _factory(app):
conf = global_config.copy()
conf.update(local_config)
return cls(app, conf)
return cls(app)
return _factory

42
tests/default.conf

@ -1,32 +1,28 @@
[DEFAULT]
catalog_driver = keystonelight.backends.templated.TemplatedCatalog
identity_driver = keystonelight.backends.kvs.KvsIdentity
token_driver = keystonelight.backends.kvs.KvsToken
policy_driver = keystonelight.backends.policy.SimpleMatch
public_port = 5000
admin_port = 35357
admin_token = ADMIN
compute_port = 3000
# 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
catalog.RegionOne.identity.adminURL = http://localhost:$(admin_port)s/v2.0
catalog.RegionOne.identity.internalURL = http://localhost:$(admin_port)s/v2.0
catalog.RegionOne.identity.name = 'Identity Service'
[sql]
connection = sqlite:///bla.db
idle_timeout = 200
min_pool_size = 5
max_pool_size = 10
pool_timeout = 200
# fake compute service for now to help novaclient tests work
compute_port = 3000
catalog.RegionOne.compute.publicURL = http://localhost:$(compute_port)s/v1.1/$(tenant_id)s
catalog.RegionOne.compute.adminURL = http://localhost:$(compute_port)s/v1.1/$(tenant_id)s
catalog.RegionOne.compute.internalURL = http://localhost:$(compute_port)s/v1.1/$(tenant_id)s
catalog.RegionOne.compute.name = 'Compute Service'
# for sql backends
sql_connection = sqlite:///bla.db
sql_idle_timeout = 200
sql_min_pool_size = 5
sql_max_pool_size = 10
sql_pool_timeout = 200
[identity]
driver = keystonelight.backends.kvs.KvsIdentity
[catalog]
driver = keystonelight.backends.templated.TemplatedCatalog
template_file = default_catalog.templates
[token]
driver = keystonelight.backends.kvs.KvsToken
[policy]
driver = keystonelight.backends.policy.SimpleMatch
[filter:debug]

12
tests/default_catalog.templates

@ -0,0 +1,12 @@
# 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
catalog.RegionOne.identity.adminURL = http://localhost:$(admin_port)s/v2.0
catalog.RegionOne.identity.internalURL = http://localhost:$(admin_port)s/v2.0
catalog.RegionOne.identity.name = 'Identity Service'
# fake compute service for now to help novaclient tests work
catalog.RegionOne.compute.publicURL = http://localhost:$(compute_port)s/v1.1/$(tenant_id)s
catalog.RegionOne.compute.adminURL = http://localhost:$(compute_port)s/v1.1/$(tenant_id)s
catalog.RegionOne.compute.internalURL = http://localhost:$(compute_port)s/v1.1/$(tenant_id)s
catalog.RegionOne.compute.name = 'Compute Service'

17
tests/keystone_compat_diablo.conf

@ -1,12 +1,21 @@
[DEFAULT]
catalog_driver = keystonelight.backends.kvs.KvsCatalog
identity_driver = keystonelight.backends.kvs.KvsIdentity
token_driver = keystonelight.backends.kvs.KvsToken
policy_driver = keystonelight.backends.policy.SimpleMatch
public_port = 5000
admin_port = 35357
admin_token = ADMIN
[identity]
driver = keystonelight.backends.kvs.KvsIdentity
[catalog]
driver = keystonelight.backends.kvs.KvsCatalog
[token]
driver = keystonelight.backends.kvs.KvsToken
[policy]
driver = keystonelight.backends.policy.SimpleMatch
[filter:debug]
paste.filter_factory = keystonelight.wsgi:Debug.factory

36
tests/keystoneclient_compat_master.conf

@ -1,25 +1,27 @@
[DEFAULT]
catalog_driver = keystonelight.backends.templated.TemplatedCatalog
identity_driver = keystonelight.backends.kvs.KvsIdentity
token_driver = keystonelight.backends.kvs.KvsToken
policy_driver = keystonelight.backends.policy.SimpleMatch
public_port = 5000
admin_port = 35357
admin_token = ADMIN
# 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
catalog.RegionOne.identity.adminURL = http://localhost:$(admin_port)s/v2.0
catalog.RegionOne.identity.internalURL = http://localhost:$(public_port)s/v2.0
catalog.RegionOne.identity.name = 'Identity Service'
# fake compute port for now to help novaclient tests work
compute_port = 3000
catalog.RegionOne.compute.publicURL = http://localhost:$(compute_port)s/v2.0
catalog.RegionOne.compute.adminURL = http://localhost:$(compute_port)s/v2.0
catalog.RegionOne.compute.internalURL = http://localhost:$(compute_port)s/v2.0
catalog.RegionOne.compute.name = 'Compute Service'
[sql]
connection = sqlite:///bla.db
idle_timeout = 200
min_pool_size = 5
max_pool_size = 10
pool_timeout = 200
[identity]
driver = keystonelight.backends.kvs.KvsIdentity
[catalog]
driver = keystonelight.backends.templated.TemplatedCatalog
template_file = default_catalog.templates
[token]
driver = keystonelight.backends.kvs.KvsToken
[policy]
driver = keystonelight.backends.policy.SimpleMatch
[filter:debug]

9
tests/test_backend_kvs.py

@ -11,16 +11,14 @@ import default_fixtures
class KvsIdentity(test.TestCase, test_backend.IdentityTests):
def setUp(self):
super(KvsIdentity, self).setUp()
self.options = self.appconfig('default')
self.identity_api = kvs.KvsIdentity(options=self.options, db={})
self.identity_api = kvs.KvsIdentity(db={})
self.load_fixtures(default_fixtures)
class KvsToken(test.TestCase):
def setUp(self):
super(KvsToken, self).setUp()
options = self.appconfig('default')
self.token_api = kvs.KvsToken(options=options, db={})
self.token_api = kvs.KvsToken(db={})
def test_token_crud(self):
token_id = uuid.uuid4().hex
@ -40,8 +38,7 @@ class KvsToken(test.TestCase):
class KvsCatalog(test.TestCase):
def setUp(self):
super(KvsCatalog, self).setUp()
options = self.appconfig('default')
self.catalog_api = kvs.KvsCatalog(options=options, db={})
self.catalog_api = kvs.KvsCatalog(db={})
self._load_fixtures()
def _load_fixtures(self):

20
tests/test_backend_sql.py

@ -1,6 +1,7 @@
import os
import uuid
from keystonelight import config
from keystonelight import models
from keystonelight import test
from keystonelight.backends import sql
@ -10,20 +11,27 @@ import test_backend
import default_fixtures
CONF = config.CONF
class SqlIdentity(test.TestCase, test_backend.IdentityTests):
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)
try:
os.unlink('bla.db')
except Exception:
pass
CONF(config_files=['default.conf'])
migration.db_sync(1)
self.identity_api = sql.SqlIdentity()
self.load_fixtures(default_fixtures)
#class SqlToken(test_backend_kvs.KvsToken):
# def setUp(self):
# super(SqlToken, self).setUp()
# self.token_api = sql.SqlToken(options=options)
# self.token_api = sql.SqlToken()
# self.load_fixtures(default_fixtures)
# def test_token_crud(self):
@ -44,7 +52,7 @@ class SqlIdentity(test.TestCase, test_backend.IdentityTests):
#class SqlCatalog(test_backend_kvs.KvsCatalog):
# def setUp(self):
# super(SqlCatalog, self).setUp()
# self.catalog_api = sql.SqlCatalog(options=options)
# self.catalog_api = sql.SqlCatalog()
# self._load_fixtures()
# def _load_fixtures(self):

12
tests/test_identity_api.py

@ -1,16 +1,20 @@
import json
from keystonelight import client
from keystonelight import config
from keystonelight import models
from keystonelight import test
import default_fixtures
CONF = config.CONF
class IdentityApi(test.TestCase):
def setUp(self):
super(IdentityApi, self).setUp()
self.options = self.appconfig('default')
CONF(config_files=['default.conf'])
self.app = self.loadapp('default')
self.load_backends()
@ -54,7 +58,7 @@ class IdentityApi(test.TestCase):
self.assertDictEquals(self.tenant_bar, data[0])
def test_crud_user(self):
token_id = self.options['admin_token']
token_id = CONF.admin_token
c = client.TestClient(self.app, token=token_id)
user_ref = models.User(name='FOO')
resp = c.create_user(**user_ref)
@ -84,7 +88,7 @@ class IdentityApi(test.TestCase):
#self.assertEquals(delget_resp.status, '404 Not Found')
def test_crud_tenant(self):
token_id = self.options['admin_token']
token_id = CONF.admin_token
c = client.TestClient(self.app, token=token_id)
tenant_ref = models.Tenant(name='BAZ')
resp = c.create_tenant(**tenant_ref)
@ -128,7 +132,7 @@ class IdentityApi(test.TestCase):
#self.assertEquals(delget_resp.status, '404 Not Found')
def test_crud_extras(self):
token_id = self.options['admin_token']
token_id = CONF.admin_token
user_id = 'foo'
tenant_id = 'bar'
c = client.TestClient(self.app, token=token_id)

9
tests/test_keystoneclient_compat.py

@ -1,8 +1,9 @@
from keystonelight import config
from keystonelight import test
import default_fixtures
CONF = config.CONF
KEYSTONECLIENT_REPO = 'git://github.com/openstack/python-keystoneclient.git'
@ -12,12 +13,12 @@ class CompatTestCase(test.TestCase):
def _public_url(self):
public_port = self.public_server.socket_info['socket'][1]
self.options['public_port'] = public_port
CONF.public_port = public_port
return "http://localhost:%s/v2.0" % public_port
def _admin_url(self):
admin_port = self.admin_server.socket_info['socket'][1]
self.options['admin_port'] = admin_port
CONF.admin_port = admin_port
return "http://localhost:%s/v2.0" % admin_port
def _client(self, **kwargs):
@ -41,7 +42,7 @@ class MasterCompatTestCase(CompatTestCase):
from keystoneclient.v2_0 import client as ks_client
reload(ks_client)
self.options = self.appconfig('keystoneclient_compat_master')
CONF(config_files=['keystoneclient_compat_master.conf'])
self.public_app = self.loadapp('keystoneclient_compat_master',
name='main')
self.admin_app = self.loadapp('keystoneclient_compat_master',

35
tests/test_legacy_compat.py

@ -5,12 +5,16 @@ import sys
from nose import exc
from keystonelight import config
from keystonelight import logging
from keystonelight import models
from keystonelight import test
from keystonelight import utils
CONF = config.CONF
IDENTITY_API_REPO = 'git://github.com/openstack/identity-api.git'
KEYSTONE_REPO = 'git://github.com/openstack/keystone.git'
NOVACLIENT_REPO = 'git://github.com/rackspace/python-novaclient.git'
@ -46,16 +50,16 @@ class CompatTestCase(test.TestCase):
os.path.join(self.sampledir, 'auth.json')))
# validate_token call
self.tenant_345 = self.identity_backend.create_tenant(
self.tenant_345 = self.identity_api.create_tenant(
'345',
models.Tenant(id='345', name='My Project'))
self.user_123 = self.identity_backend.create_user(
self.user_123 = self.identity_api.create_user(
'123',
models.User(id='123',
name='jqsmith',
tenants=[self.tenant_345['id']],
password='password'))
self.extras_123 = self.identity_backend.create_extras(
self.extras_123 = self.identity_api.create_extras(
self.user_123['id'], self.tenant_345['id'],
dict(roles=[{'id': '234',
'name': 'compute:admin'},
@ -63,7 +67,7 @@ class CompatTestCase(test.TestCase):
'name': 'object-store:admin',
'tenantId': '1'}],
roles_links=[]))
self.token_123 = self.token_backend.create_token(
self.token_123 = self.token_api.create_token(
'ab48a9efdfedb23ty3494',
models.Token(id='ab48a9efdfedb23ty3494',
expires='2010-11-01T03:32:15-05:00',
@ -79,32 +83,32 @@ class CompatTestCase(test.TestCase):
#catalog = json.load(open(
# os.path.join(os.path.dirname(__file__),
# 'keystone_compat_diablo_sample_catalog.json')))
#self.catalog_backend.create_catalog(self.user_123['id'],
#self.catalog_api.create_catalog(self.user_123['id'],
# self.tenant_345['id'],
# catalog)
# tenants_for_token call
self.user_foo = self.identity_backend.create_user(
self.user_foo = self.identity_api.create_user(
'foo',
models.User(id='foo', name='FOO', tenants=['1234', '3456']))
self.tenant_1234 = self.identity_backend.create_tenant(
self.tenant_1234 = self.identity_api.create_tenant(
'1234',
models.Tenant(id='1234',
name='ACME Corp',
description='A description ...',
enabled=True))
self.tenant_3456 = self.identity_backend.create_tenant(
self.tenant_3456 = self.identity_api.create_tenant(
'3456',
models.Tenant(id='3456',
name='Iron Works',
description='A description ...',
enabled=True))
self.token_foo_unscoped = self.token_backend.create_token(
self.token_foo_unscoped = self.token_api.create_token(
'foo_unscoped',
models.Token(id='foo_unscoped',
user=self.user_foo))
self.token_foo_scoped = self.token_backend.create_token(
self.token_foo_scoped = self.token_api.create_token(
'foo_scoped',
models.Token(id='foo_scoped',
user=self.user_foo,
@ -113,18 +117,13 @@ class CompatTestCase(test.TestCase):
class DiabloCompatTestCase(CompatTestCase):
def setUp(self):
CONF(config_files=['keystone_compat_diablo.conf'])
revdir = test.checkout_vendor(KEYSTONE_REPO, 'stable/diablo')
self.sampledir = os.path.join(revdir, KEYSTONE_SAMPLE_DIR)
self.app = self.loadapp('keystone_compat_diablo')
self.options = self.appconfig('keystone_compat_diablo')
self.identity_backend = utils.import_object(
self.options['identity_driver'], options=self.options)
self.token_backend = utils.import_object(
self.options['token_driver'], options=self.options)
self.catalog_backend = utils.import_object(
self.options['catalog_driver'], options=self.options)
self.load_backends()
super(DiabloCompatTestCase, self).setUp()
def test_authenticate_scoped(self):

6
tests/test_novaclient_compat.py

@ -3,6 +3,7 @@ import json
import os
import sys
from keystonelight import config
from keystonelight import logging
from keystonelight import models
from keystonelight import test
@ -11,6 +12,7 @@ from keystonelight import utils
import default_fixtures
CONF = config.CONF
NOVACLIENT_REPO = 'git://github.com/openstack/python-novaclient.git'
@ -30,8 +32,8 @@ class NovaClientCompatMasterTestCase(CompatTestCase):
reload(ks_client)
reload(base_client)
CONF(config_files=['keystoneclient_compat_master.conf'])
self.app = self.loadapp('keystoneclient_compat_master')
self.options = self.appconfig('keystoneclient_compat_master')
self.load_backends()
self.load_fixtures(default_fixtures)
self.server = self.serveapp('keystoneclient_compat_master')
@ -41,7 +43,7 @@ class NovaClientCompatMasterTestCase(CompatTestCase):
from novaclient import client as base_client
port = self.server.socket_info['socket'][1]
self.options['public_port'] = port
CONF.public_port = port
# NOTE(termie): novaclient wants a "/" TypeErrorat the end, keystoneclient does not
# NOTE(termie): projectid is apparently sent as tenantName, so... that's

Loading…
Cancel
Save