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
This commit is contained in:
termie 2012-01-06 21:00:41 -08:00
parent 829a96b1e0
commit feadf75760
25 changed files with 304 additions and 281 deletions

View File

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

View File

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

View File

@ -10,9 +10,13 @@ import sqlalchemy.orm
import sqlalchemy.pool import sqlalchemy.pool
import sqlalchemy.engine.url import sqlalchemy.engine.url
from keystonelight import config
from keystonelight import models from keystonelight import models
CONF = config.CONF
Base = declarative.declarative_base() Base = declarative.declarative_base()
@ -121,9 +125,6 @@ class SqlBase(object):
_MAKER = None _MAKER = None
_ENGINE = None _ENGINE = None
def __init__(self, options):
self.options = options
def get_session(self, autocommit=True, expire_on_commit=False): def get_session(self, autocommit=True, expire_on_commit=False):
"""Return a SQLAlchemy session.""" """Return a SQLAlchemy session."""
if self._MAKER is None or self._ENGINE is None: if self._MAKER is None or self._ENGINE is None:
@ -138,36 +139,17 @@ class SqlBase(object):
def get_engine(self): def get_engine(self):
"""Return a SQLAlchemy engine.""" """Return a SQLAlchemy engine."""
connection_dict = sqlalchemy.engine.url.make_url( connection_dict = sqlalchemy.engine.url.make_url(CONF.sql.connection)
self.options.get('sql_connection'))
engine_args = { engine_args = {
"pool_recycle": self.options.get('sql_idle_timeout'), "pool_recycle": CONF.sql.idle_timeout,
"echo": False, "echo": False,
} }
if "sqlite" in connection_dict.drivername: if "sqlite" in connection_dict.drivername:
engine_args["poolclass"] = sqlalchemy.pool.NullPool 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'), return sql.create_engine(CONF.sql.connection, **engine_args)
**engine_args)
def get_maker(self, engine, autocommit=True, expire_on_commit=False): def get_maker(self, engine, autocommit=True, expire_on_commit=False):
"""Return a SQLAlchemy sessionmaker using the given engine.""" """Return a SQLAlchemy sessionmaker using the given engine."""

View File

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

View File

@ -1,7 +1,12 @@
from keystonelight import config
from keystonelight import logging from keystonelight import logging
from keystonelight.backends import kvs from keystonelight.backends import kvs
CONF = config.CONF
config.register_str('template_file', group='catalog')
class TemplatedCatalog(kvs.KvsCatalog): class TemplatedCatalog(kvs.KvsCatalog):
"""A backend that generates endpoints for the Catalog based on templates. """A backend that generates endpoints for the Catalog based on templates.
@ -16,7 +21,7 @@ class TemplatedCatalog(kvs.KvsCatalog):
http://localhost:$(public_port)s/ 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. 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 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): def __init__(self, templates=None):
self.options = options
if templates: if templates:
self.templates = templates self.templates = templates
else: 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 = {} 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.'): if not k.startswith('catalog.'):
continue continue
@ -64,7 +71,7 @@ class TemplatedCatalog(kvs.KvsCatalog):
self.templates = o self.templates = o
def get_catalog(self, user_id, tenant_id, extras=None): def get_catalog(self, user_id, tenant_id, extras=None):
d = self.options.copy() d = dict(CONF.iteritems())
d.update({'tenant_id': tenant_id, d.update({'tenant_id': tenant_id,
'user_id': user_id}) 'user_id': user_id})

View File

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

49
keystonelight/config.py Normal file
View File

@ -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')

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,6 +8,7 @@ import time
from paste import deploy from paste import deploy
from keystonelight import config
from keystonelight import logging from keystonelight import logging
from keystonelight import models from keystonelight import models
from keystonelight import utils from keystonelight import utils
@ -17,7 +18,7 @@ from keystonelight import wsgi
ROOTDIR = os.path.dirname(os.path.dirname(__file__)) ROOTDIR = os.path.dirname(os.path.dirname(__file__))
VENDOR = os.path.join(ROOTDIR, 'vendor') VENDOR = os.path.join(ROOTDIR, 'vendor')
TESTSDIR = os.path.join(ROOTDIR, 'tests') TESTSDIR = os.path.join(ROOTDIR, 'tests')
CONF = config.CONF
cd = os.chdir cd = os.chdir
@ -94,21 +95,14 @@ class TestCase(unittest.TestCase):
for path in self._paths: for path in self._paths:
if path in sys.path: if path in sys.path:
sys.path.remove(path) sys.path.remove(path)
CONF.reset()
super(TestCase, self).tearDown() super(TestCase, self).tearDown()
#TODO(termie): probably make this take an argument and use that for `options`
def load_backends(self): def load_backends(self):
"""Hacky shortcut to load the backends for data manipulation. """Hacky shortcut to load the backends for data manipulation."""
self.identity_api = utils.import_object(CONF.identity.driver)
Expects self.options to have already been set. self.token_api = utils.import_object(CONF.token.driver)
self.catalog_api = utils.import_object(CONF.catalog.driver)
"""
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)
def load_fixtures(self, fixtures): def load_fixtures(self, fixtures):
"""Hacky basic and naive fixture loading based on a python module. """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. # Service catalog tests need to know the port we ran on.
port = server.socket_info['socket'][1] port = server.socket_info['socket'][1]
self._update_server_options(server, 'public_port', port) CONF.public_port = port
self._update_server_options(server, 'admin_port', port) CONF.admin_port = port
return server 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): def client(self, app, *args, **kw):
return TestClient(app, *args, **kw) return TestClient(app, *args, **kw)

View File

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

View File

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

View File

@ -1,32 +1,28 @@
[DEFAULT] [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 public_port = 5000
admin_port = 35357 admin_port = 35357
admin_token = ADMIN 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:$(admin_port)s/v2.0
catalog.RegionOne.identity.name = 'Identity Service'
# fake compute service for now to help novaclient tests work
compute_port = 3000 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]
sql_connection = sqlite:///bla.db connection = sqlite:///bla.db
sql_idle_timeout = 200 idle_timeout = 200
sql_min_pool_size = 5 min_pool_size = 5
sql_max_pool_size = 10 max_pool_size = 10
sql_pool_timeout = 200 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] [filter:debug]

View File

@ -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'

View File

@ -1,12 +1,21 @@
[DEFAULT] [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 public_port = 5000
admin_port = 35357 admin_port = 35357
admin_token = ADMIN 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] [filter:debug]
paste.filter_factory = keystonelight.wsgi:Debug.factory paste.filter_factory = keystonelight.wsgi:Debug.factory

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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