Remove oslo_config from auth plugin loading

There is still the possibility of a dependency in session, however this
is the main usage. Defines a new option type schema.

Change-Id: Ie508dff449a92c9ea01c46285c10888135e93a97
This commit is contained in:
Jamie Lennox 2015-08-05 13:42:12 +10:00
parent efcadd6937
commit 5e74fed6b5
14 changed files with 177 additions and 110 deletions

@ -13,6 +13,7 @@
from keystoneauth1.loading.base import * # noqa from keystoneauth1.loading.base import * # noqa
from keystoneauth1.loading.cli import * # noqa from keystoneauth1.loading.cli import * # noqa
from keystoneauth1.loading.conf import * # noqa from keystoneauth1.loading.conf import * # noqa
from keystoneauth1.loading.opts import * # noqa
__all__ = [ __all__ = [
@ -32,4 +33,7 @@ __all__ = [
'get_plugin_options', 'get_plugin_options',
'load_from_conf_options', 'load_from_conf_options',
'register_conf_options', 'register_conf_options',
# loading.opts
'Opt',
] ]

@ -10,8 +10,6 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from oslo_config import cfg
from keystoneauth1 import loading from keystoneauth1 import loading
@ -21,7 +19,7 @@ class BaseIdentityLoader(loading.BaseLoader):
options = super(BaseIdentityLoader, self).get_options() options = super(BaseIdentityLoader, self).get_options()
options.extend([ options.extend([
cfg.StrOpt('auth-url', help='Authentication URL'), loading.Opt('auth-url', help='Authentication URL'),
]) ])
return options return options

@ -10,9 +10,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from oslo_config import cfg
from keystoneauth1 import identity from keystoneauth1 import identity
from keystoneauth1 import loading
from keystoneauth1.loading._plugins.identity import base from keystoneauth1.loading._plugins.identity import base
@ -22,17 +21,17 @@ class GenericBaseLoader(base.BaseIdentityLoader):
options = super(GenericBaseLoader, self).get_options() options = super(GenericBaseLoader, self).get_options()
options.extend([ options.extend([
cfg.StrOpt('domain-id', help='Domain ID to scope to'), loading.Opt('domain-id', help='Domain ID to scope to'),
cfg.StrOpt('domain-name', help='Domain name to scope to'), loading.Opt('domain-name', help='Domain name to scope to'),
cfg.StrOpt('tenant-id', help='Tenant ID to scope to'), loading.Opt('tenant-id', help='Tenant ID to scope to'),
cfg.StrOpt('tenant-name', help='Tenant name to scope to'), loading.Opt('tenant-name', help='Tenant name to scope to'),
cfg.StrOpt('project-id', help='Project ID to scope to'), loading.Opt('project-id', help='Project ID to scope to'),
cfg.StrOpt('project-name', help='Project name to scope to'), loading.Opt('project-name', help='Project name to scope to'),
cfg.StrOpt('project-domain-id', loading.Opt('project-domain-id',
help='Domain ID containing project'), help='Domain ID containing project'),
cfg.StrOpt('project-domain-name', loading.Opt('project-domain-name',
help='Domain name containing project'), help='Domain name containing project'),
cfg.StrOpt('trust-id', help='Trust ID'), loading.Opt('trust-id', help='Trust ID'),
]) ])
return options return options
@ -48,7 +47,7 @@ class Token(GenericBaseLoader):
options = super(Token, self).get_options() options = super(Token, self).get_options()
options.extend([ options.extend([
cfg.StrOpt('token', help='Token to authenticate with'), loading.Opt('token', help='Token to authenticate with'),
]) ])
return options return options
@ -63,13 +62,13 @@ class Password(GenericBaseLoader):
def get_options(cls): def get_options(cls):
options = super(Password, cls).get_options() options = super(Password, cls).get_options()
options.extend([ options.extend([
cfg.StrOpt('user-id', help='User id'), loading.Opt('user-id', help='User id'),
cfg.StrOpt('user-name', loading.Opt('user-name',
dest='username', dest='username',
help='Username', help='Username',
deprecated_name='username'), deprecated=[loading.Opt('username')]),
cfg.StrOpt('user-domain-id', help="User's domain id"), loading.Opt('user-domain-id', help="User's domain id"),
cfg.StrOpt('user-domain-name', help="User's domain name"), loading.Opt('user-domain-name', help="User's domain name"),
cfg.StrOpt('password', help="User's password"), loading.Opt('password', help="User's password"),
]) ])
return options return options

@ -10,9 +10,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from oslo_config import cfg
from keystoneauth1 import identity from keystoneauth1 import identity
from keystoneauth1 import loading
from keystoneauth1.loading._plugins.identity import base from keystoneauth1.loading._plugins.identity import base
@ -22,9 +21,9 @@ class BaseV2Loader(base.BaseIdentityLoader):
options = super(BaseV2Loader, self).get_options() options = super(BaseV2Loader, self).get_options()
options.extend([ options.extend([
cfg.StrOpt('tenant-id', help='Tenant ID'), loading.Opt('tenant-id', help='Tenant ID'),
cfg.StrOpt('tenant-name', help='Tenant Name'), loading.Opt('tenant-name', help='Tenant Name'),
cfg.StrOpt('trust-id', help='Trust ID'), loading.Opt('trust-id', help='Trust ID'),
]) ])
return options return options
@ -40,7 +39,7 @@ class V2Token(BaseV2Loader):
options = super(V2Token, self).get_options() options = super(V2Token, self).get_options()
options.extend([ options.extend([
cfg.StrOpt('token', secret=True, help='Token'), loading.Opt('token', secret=True, help='Token'),
]) ])
return options return options
@ -56,12 +55,12 @@ class V2Password(BaseV2Loader):
options = super(V2Password, self).get_options() options = super(V2Password, self).get_options()
options.extend([ options.extend([
cfg.StrOpt('user-name', loading.Opt('user-name',
dest='username', dest='username',
deprecated_name='username', deprecated=[loading.Opt('username')],
help='Username to login with'), help='Username to login with'),
cfg.StrOpt('user-id', help='User ID to longin with'), loading.Opt('user-id', help='User ID to longin with'),
cfg.StrOpt('password', secret=True, help='Password to use'), loading.Opt('password', secret=True, help='Password to use'),
]) ])
return options return options

@ -10,9 +10,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from oslo_config import cfg
from keystoneauth1 import identity from keystoneauth1 import identity
from keystoneauth1 import loading
from keystoneauth1.loading._plugins.identity import base from keystoneauth1.loading._plugins.identity import base
@ -22,15 +21,15 @@ class BaseV3Loader(base.BaseIdentityLoader):
options = super(BaseV3Loader, self).get_options() options = super(BaseV3Loader, self).get_options()
options.extend([ options.extend([
cfg.StrOpt('domain-id', help='Domain ID to scope to'), loading.Opt('domain-id', help='Domain ID to scope to'),
cfg.StrOpt('domain-name', help='Domain name to scope to'), loading.Opt('domain-name', help='Domain name to scope to'),
cfg.StrOpt('project-id', help='Project ID to scope to'), loading.Opt('project-id', help='Project ID to scope to'),
cfg.StrOpt('project-name', help='Project name to scope to'), loading.Opt('project-name', help='Project name to scope to'),
cfg.StrOpt('project-domain-id', loading.Opt('project-domain-id',
help='Domain ID containing project'), help='Domain ID containing project'),
cfg.StrOpt('project-domain-name', loading.Opt('project-domain-name',
help='Domain name containing project'), help='Domain name containing project'),
cfg.StrOpt('trust-id', help='Trust ID'), loading.Opt('trust-id', help='Trust ID'),
]) ])
return options return options
@ -46,14 +45,14 @@ class Password(BaseV3Loader):
options = super(Password, self).get_options() options = super(Password, self).get_options()
options.extend([ options.extend([
cfg.StrOpt('user-id', help='User ID'), loading.Opt('user-id', help='User ID'),
cfg.StrOpt('user-name', loading.Opt('user-name',
dest='username', dest='username',
help='Username', help='Username',
deprecated_name='username'), deprecated=[loading.Opt('username')]),
cfg.StrOpt('user-domain-id', help="User's domain id"), loading.Opt('user-domain-id', help="User's domain id"),
cfg.StrOpt('user-domain-name', help="User's domain name"), loading.Opt('user-domain-name', help="User's domain name"),
cfg.StrOpt('password', secret=True, help="User's password"), loading.Opt('password', secret=True, help="User's password"),
]) ])
return options return options
@ -69,7 +68,7 @@ class Token(BaseV3Loader):
options = super(Token, self).get_options() options = super(Token, self).get_options()
options.extend([ options.extend([
cfg.StrOpt('token', loading.Opt('token',
secret=True, secret=True,
help='Token to authenticate with'), help='Token to authenticate with'),
]) ])
@ -83,9 +82,9 @@ class FederatedBase(BaseV3Loader):
options = super(FederatedBase, self).get_options() options = super(FederatedBase, self).get_options()
options.extend([ options.extend([
cfg.StrOpt('identity-provider', loading.Opt('identity-provider',
help="Identity Provider's name"), help="Identity Provider's name"),
cfg.StrOpt('protocol', loading.Opt('protocol',
help='Protocol for federated plugin'), help='Protocol for federated plugin'),
]) ])

@ -10,8 +10,6 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from oslo_config import cfg
from keystoneauth1 import loading from keystoneauth1 import loading
from keystoneauth1 import token_endpoint from keystoneauth1 import token_endpoint
@ -26,9 +24,9 @@ class TokenEndpoint(loading.BaseLoader):
options = super(TokenEndpoint, self).get_options() options = super(TokenEndpoint, self).get_options()
options.extend([ options.extend([
cfg.StrOpt('endpoint', loading.Opt('endpoint',
help='The endpoint that will always be used'), help='The endpoint that will always be used'),
cfg.StrOpt('token', loading.Opt('token',
secret=True, secret=True,
help='The token that will always be used'), help='The token that will always be used'),
]) ])

@ -11,7 +11,6 @@
# under the License. # under the License.
import abc import abc
import os
import six import six
import stevedore import stevedore
@ -104,27 +103,9 @@ class BaseLoader(object):
:param parser: the parser to attach argparse options. :param parser: the parser to attach argparse options.
:type parser: argparse.ArgumentParser :type parser: argparse.ArgumentParser
""" """
# NOTE(jamielennox): ideally oslo_config would be smart enough to
# handle all the Opt manipulation that goes on in this file. However it
# is currently not. Options are handled in as similar a way as
# possible to oslo_config such that when available we should be able to
# transition.
for opt in self.get_options(): for opt in self.get_options():
args = [] parser.add_argument(*opt.argparse_args,
envs = [] default=opt.argparse_default,
for o in [opt] + opt.deprecated_opts:
args.append('--os-%s' % o.name)
envs.append('OS_%s' % o.name.replace('-', '_').upper())
# select the first ENV that is not false-y or return None
env_vars = (os.environ.get(e) for e in envs)
default = six.next(six.moves.filter(None, env_vars), None)
parser.add_argument(*args,
default=default or opt.default,
metavar=opt.metavar, metavar=opt.metavar,
help=opt.help, help=opt.help,
dest='os_%s' % opt.dest) dest='os_%s' % opt.dest)
@ -153,7 +134,7 @@ class BaseLoader(object):
:type conf: oslo_config.cfg.ConfigOpts :type conf: oslo_config.cfg.ConfigOpts
:param string group: The group name that options should be read from. :param string group: The group name that options should be read from.
""" """
plugin_opts = self.get_options() plugin_opts = [o._to_oslo_opt() for o in self.get_options()]
conf.register_opts(plugin_opts, group=group) conf.register_opts(plugin_opts, group=group)
def load_from_conf_options(self, conf, group, **kwargs): def load_from_conf_options(self, conf, group, **kwargs):
@ -181,8 +162,8 @@ class BaseLoader(object):
specify a custom loader function that will be queried for the option specify a custom loader function that will be queried for the option
value. value.
The getter is a function that takes one value, an The getter is a function that takes one value, a
:py:class:`oslo_config.cfg.Opt` and returns a value to load with. :py:class:`keystoneauth1.loading.Opt` and returns a value to load with.
:param getter: A function that returns a value for the given opt. :param getter: A function that returns a value for the given opt.
:type getter: callable :type getter: callable

@ -10,14 +10,13 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from oslo_config import cfg
from keystoneauth1.loading import base from keystoneauth1.loading import base
from keystoneauth1.loading import opts
_AUTH_PLUGIN_OPT = cfg.StrOpt('auth_plugin', help='Name of the plugin to load') _AUTH_PLUGIN_OPT = opts.Opt('auth_plugin', help='Name of the plugin to load')
_section_help = 'Config Section from which to load plugin specific options' _section_help = 'Config Section from which to load plugin specific options'
_AUTH_SECTION_OPT = cfg.StrOpt('auth_section', help=_section_help) _AUTH_SECTION_OPT = opts.Opt('auth_section', help=_section_help)
def get_common_conf_options(): def get_common_conf_options():
@ -64,7 +63,7 @@ def register_conf_options(conf, group):
:type conf: oslo_config.cfg.ConfigOpts :type conf: oslo_config.cfg.ConfigOpts
:param string group: The ini group to register options in. :param string group: The ini group to register options in.
""" """
conf.register_opt(_AUTH_SECTION_OPT, group=group) conf.register_opt(_AUTH_SECTION_OPT._to_oslo_opt(), group=group)
# NOTE(jamielennox): plugins are allowed to specify a 'section' which is # NOTE(jamielennox): plugins are allowed to specify a 'section' which is
# the group that auth options should be taken from. If not present they # the group that auth options should be taken from. If not present they
@ -74,7 +73,7 @@ def register_conf_options(conf, group):
if conf[group].auth_section: if conf[group].auth_section:
group = conf[group].auth_section group = conf[group].auth_section
conf.register_opt(_AUTH_PLUGIN_OPT, group=group) conf.register_opt(_AUTH_PLUGIN_OPT._to_oslo_opt(), group=group)
def load_from_conf_options(conf, group, **kwargs): def load_from_conf_options(conf, group, **kwargs):

@ -0,0 +1,87 @@
# 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 itertools
import os
try:
from oslo_config import cfg
except ImportError:
cfg = None
from keystoneauth1 import _utils as utils
class Opt(object):
@utils.positional()
def __init__(self,
name,
type=str,
help=None,
secret=False,
dest=None,
deprecated=None,
default=None,
metavar=None):
if not callable(type):
raise TypeError('type must be callable')
if dest is None:
dest = name.replace('-', '_')
self.name = name
self.type = type
self.help = help
self.secret = secret
self.dest = dest
self.deprecated = [] if deprecated is None else deprecated
self.default = default
self.metavar = metavar
def __repr__(self):
return '<Opt: %s>' % self.name
def _to_oslo_opt(self):
if not cfg:
raise ImportError("oslo.config is not an automatic dependency of "
"keystoneauth. If you wish to use oslo.config "
"you need to import it into your application's "
"requirements file. ")
deprecated_opts = [o._to_oslo_opt() for o in self.deprecated]
return cfg.Opt(name=self.name,
type=self.type,
help=self.help,
secret=self.secret,
dest=self.dest,
deprecated_opts=deprecated_opts,
metavar=self.metavar)
@property
def _all_opts(self):
return itertools.chain([self], self.deprecated)
@property
def argparse_args(self):
return ['--os-%s' % o.name for o in self._all_opts]
@property
def argparse_default(self):
# select the first ENV that is not false-y or return None
for o in self._all_opts:
v = os.environ.get('OS_%s' % self.name.replace('-', '_').upper())
if v:
return v
return self.default

@ -14,7 +14,6 @@ import functools
import uuid import uuid
import mock import mock
from oslo_config import cfg
import six import six
from keystoneauth1 import access from keystoneauth1 import access
@ -41,6 +40,12 @@ class MockPlugin(plugin.BaseAuthPlugin):
return 'http://test' return 'http://test'
class BoolType(object):
def __call__(self, value):
return value.lower() in ('1', 'true', 't', 'yes', 'y')
class MockLoader(loading.BaseLoader): class MockLoader(loading.BaseLoader):
INT_DESC = 'test int' INT_DESC = 'test int'
@ -55,10 +60,10 @@ class MockLoader(loading.BaseLoader):
def get_options(self): def get_options(self):
return [ return [
cfg.IntOpt('a-int', default='3', help=self.INT_DESC), loading.Opt('a-int', default=3, type=int, help=self.INT_DESC),
cfg.BoolOpt('a-bool', help=self.BOOL_DESC), loading.Opt('a-bool', type=BoolType(), help=self.BOOL_DESC),
cfg.FloatOpt('a-float', help=self.FLOAT_DESC), loading.Opt('a-float', type=float, help=self.FLOAT_DESC),
cfg.StrOpt('a-str', help=self.STR_DESC, default=self.STR_DEFAULT), loading.Opt('a-str', help=self.STR_DESC, default=self.STR_DEFAULT),
] ]

@ -15,7 +15,6 @@ import uuid
import fixtures import fixtures
import mock import mock
from oslo_config import cfg
from keystoneauth1 import base from keystoneauth1 import base
from keystoneauth1 import loading from keystoneauth1 import loading
@ -38,9 +37,9 @@ class TesterLoader(loading.BaseLoader):
# NOTE(jamielennox): this is kind of horrible. If you specify this as # NOTE(jamielennox): this is kind of horrible. If you specify this as
# a deprecated_name= value it will convert - to _ which is not what we # a deprecated_name= value it will convert - to _ which is not what we
# want for a CLI option. # want for a CLI option.
deprecated = [cfg.DeprecatedOpt('test-other')] deprecated = [loading.Opt('test-other')]
return [ return [
cfg.StrOpt('test-opt', help='tester', deprecated_opts=deprecated) loading.Opt('test-opt', help='tester', deprecated=deprecated)
] ]

@ -13,7 +13,6 @@
import uuid import uuid
import mock import mock
from oslo_config import cfg
from oslo_config import fixture as config from oslo_config import fixture as config
import stevedore import stevedore
@ -157,14 +156,14 @@ class ConfTests(utils.TestCase):
def inner(driver): def inner(driver):
for p in driver.plugin().get_options(): for p in driver.plugin().get_options():
self.assertIsInstance(p, cfg.Opt) self.assertIsInstance(p, loading.Opt)
manager.map(inner) manager.map(inner)
def test_get_common(self): def test_get_common(self):
opts = loading.get_common_conf_options() opts = loading.get_common_conf_options()
for opt in opts: for opt in opts:
self.assertIsInstance(opt, cfg.Opt) self.assertIsInstance(opt, loading.Opt)
self.assertEqual(2, len(opts)) self.assertEqual(2, len(opts))
def test_get_named(self): def test_get_named(self):

@ -4,7 +4,6 @@
argparse argparse
iso8601>=0.1.9 iso8601>=0.1.9
oslo.config>=1.11.0 # Apache-2.0
requests>=2.5.2 requests>=2.5.2
six>=1.9.0 six>=1.9.0
stevedore>=1.5.0 # Apache-2.0 stevedore>=1.5.0 # Apache-2.0

@ -11,6 +11,7 @@ keyring!=3.3,>=2.1
mock>=1.2 mock>=1.2
mox3>=0.7.0 mox3>=0.7.0
oauthlib>=0.6 oauthlib>=0.6
oslo.config>=1.11.0 # Apache-2.0
oslosphinx>=2.5.0 # Apache-2.0 oslosphinx>=2.5.0 # Apache-2.0
oslotest>=1.10.0 # Apache-2.0 oslotest>=1.10.0 # Apache-2.0
pycrypto>=2.6 pycrypto>=2.6