From dc22e9fd30ea678edaf0a3237ed10c49128e87d9 Mon Sep 17 00:00:00 2001 From: Chris Dent Date: Sun, 31 Jan 2016 02:05:40 +0000 Subject: [PATCH] Remove clobbering of passed oslo_config_config Calling a ConfigOpts instance with new args will implicitly reset the config values in the instance. This means that in the previous revision of the code, any assignment of oslo_config_config to self._local_oslo_config would be instantly clobbered by calling self._local_oslo_config() to read from default_config_files. Now, if oslo_config_config is set to a non-None value it will be left unmolested. This is useful because oslo_config_config turns out to be the ideal way to pass config to AuthProtocol when the caller already has access to the project config object and neither global conf nor paste is being used. Change-Id: I0beb809bc5ace609561f10dc52800a8a6e03f7e6 Closes-Bug: #1540022 --- keystonemiddleware/auth_token/__init__.py | 21 +++--- .../tests/unit/auth_token/base.py | 2 +- .../auth_token/test_auth_token_middleware.py | 70 ++++++++++++++++--- ...s-oslo-config-config-a37212b60f58e154.yaml | 10 +++ 4 files changed, 82 insertions(+), 21 deletions(-) create mode 100644 releasenotes/notes/authprotocol-accepts-oslo-config-config-a37212b60f58e154.yaml diff --git a/keystonemiddleware/auth_token/__init__.py b/keystonemiddleware/auth_token/__init__.py index 4d2faf5b..29253edb 100644 --- a/keystonemiddleware/auth_token/__init__.py +++ b/keystonemiddleware/auth_token/__init__.py @@ -639,25 +639,26 @@ class AuthProtocol(BaseAuthProtocol): # conf value into correct type. self._conf = _conf_values_type_convert(conf) - # NOTE(sileht): If we don't want to use oslo.config global object - # we can set the paste "oslo_config_project" and the middleware - # will load the configuration with a local oslo.config object. - self._local_oslo_config = None - if 'oslo_config_project' in conf: + # NOTE(sileht, cdent): If we don't want to use oslo.config global + # object there are two options: set "oslo_config_project" in + # paste.ini and the middleware will load the configuration with a + # local oslo.config object or the caller which instantiates + # AuthProtocol can pass in an existing oslo.config as the + # value of the "oslo_config_config" key in conf. If both are + # set "olso_config_config" is used. + self._local_oslo_config = conf.get('oslo_config_config') + if (not self._local_oslo_config) and ('oslo_config_project' in conf): if 'oslo_config_file' in conf: default_config_files = [conf['oslo_config_file']] else: default_config_files = None - - # For unit tests, support passing in a ConfigOpts in - # oslo_config_config. - self._local_oslo_config = conf.get('oslo_config_config', - cfg.ConfigOpts()) + self._local_oslo_config = cfg.ConfigOpts() self._local_oslo_config( {}, project=conf['oslo_config_project'], default_config_files=default_config_files, validate_default_values=True) + if self._local_oslo_config: self._local_oslo_config.register_opts(_OPTS, group=_base.AUTHTOKEN_GROUP) self._local_oslo_config.register_opts(_auth.OPTS, diff --git a/keystonemiddleware/tests/unit/auth_token/base.py b/keystonemiddleware/tests/unit/auth_token/base.py index ed9b1f5d..06115cee 100644 --- a/keystonemiddleware/tests/unit/auth_token/base.py +++ b/keystonemiddleware/tests/unit/auth_token/base.py @@ -31,6 +31,7 @@ class BaseAuthTokenTestCase(utils.BaseTestCase): self.requests_mock = self.useFixture(rm_fixture.Fixture()) self.logger = fixtures.FakeLogger(level=logging.DEBUG) self.cfg = self.useFixture(cfg_fixture.Config(conf=cfg.ConfigOpts())) + self.cfg.conf(args=[]) def create_middleware(self, cb, conf=None, use_global_conf=False): @@ -42,7 +43,6 @@ class BaseAuthTokenTestCase(utils.BaseTestCase): opts = conf or {} else: opts = { - 'oslo_config_project': 'keystonemiddleware', 'oslo_config_config': self.cfg.conf, } opts.update(conf or {}) diff --git a/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py b/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py index 23e26a16..15138ce7 100644 --- a/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py +++ b/keystonemiddleware/tests/unit/auth_token/test_auth_token_middleware.py @@ -2468,8 +2468,33 @@ class TestAuthPluginUserAgentGeneration(BaseAuthTokenMiddlewareTest): class TestAuthPluginLocalOsloConfig(BaseAuthTokenMiddlewareTest): - def test_project_in_local_oslo_configuration(self): - options = { + + def setUp(self): + super(TestAuthPluginLocalOsloConfig, self).setUp() + self.project = uuid.uuid4().hex + + # NOTE(cdent): The options below are selected from those + # which are statically registered by auth_token middleware + # in the 'keystone_authtoken' group. Additional options, from + # plugins, are registered dynamically so must not be used here. + self.oslo_options = { + 'auth_uri': uuid.uuid4().hex, + 'identity_uri': uuid.uuid4().hex, + } + + self.local_oslo_config = cfg.ConfigOpts() + self.local_oslo_config.register_group(cfg.OptGroup( + name='keystone_authtoken')) + self.local_oslo_config.register_opts(auth_token._OPTS, + group='keystone_authtoken') + self.local_oslo_config.register_opts(auth_token._auth.OPTS, + group='keystone_authtoken') + for option, value in self.oslo_options.items(): + self.local_oslo_config.set_override(option, value, + 'keystone_authtoken') + self.local_oslo_config(args=[], project=self.project) + + self.file_options = { 'auth_type': 'password', 'auth_uri': uuid.uuid4().hex, 'password': uuid.uuid4().hex, @@ -2479,14 +2504,36 @@ class TestAuthPluginLocalOsloConfig(BaseAuthTokenMiddlewareTest): "auth_type=%(auth_type)s\n" "auth_uri=%(auth_uri)s\n" "auth_url=%(auth_uri)s\n" - "password=%(password)s\n" % options) - conf_file_fixture = self.useFixture( - createfile.CreateFileWithContent("my_app", content)) - conf = {'oslo_config_project': 'my_app', - 'oslo_config_file': conf_file_fixture.path} + "password=%(password)s\n" % self.file_options) + self.conf_file_fixture = self.useFixture( + createfile.CreateFileWithContent(self.project, content)) + + def test_project_in_local_oslo_configuration(self): + conf = {'oslo_config_project': self.project, + 'oslo_config_file': self.conf_file_fixture.path} app = self._create_app(conf, uuid.uuid4().hex) - for option in options: - self.assertEqual(options[option], app._conf_get(option)) + for option in self.file_options: + self.assertEqual(self.file_options[option], + app._conf_get(option), option) + + def test_passed_oslo_configuration(self): + conf = {'oslo_config_config': self.local_oslo_config} + app = self._create_app(conf, uuid.uuid4().hex) + for option in self.oslo_options: + self.assertEqual(self.oslo_options[option], + app._conf_get(option)) + + def test_passed_olso_configuration_wins(self): + """oslo_config_config has precedence over oslo_config_project.""" + conf = {'oslo_config_project': self.project, + 'oslo_config_config': self.local_oslo_config, + 'oslo_config_file': self.conf_file_fixture.path} + app = self._create_app(conf, uuid.uuid4().hex) + for option in self.oslo_options: + self.assertEqual(self.oslo_options[option], + app._conf_get(option)) + self.assertNotEqual(self.file_options['auth_uri'], + app._conf_get('auth_uri')) def _create_app(self, conf, project_version): fake_pkg_resources = mock.Mock() @@ -2495,7 +2542,10 @@ class TestAuthPluginLocalOsloConfig(BaseAuthTokenMiddlewareTest): body = uuid.uuid4().hex with mock.patch('keystonemiddleware.auth_token.pkg_resources', new=fake_pkg_resources): - return self.create_simple_middleware(body=body, conf=conf) + # use_global_conf is poorly named. What it means is + # don't use the config created in test setUp. + return self.create_simple_middleware(body=body, conf=conf, + use_global_conf=True) def load_tests(loader, tests, pattern): diff --git a/releasenotes/notes/authprotocol-accepts-oslo-config-config-a37212b60f58e154.yaml b/releasenotes/notes/authprotocol-accepts-oslo-config-config-a37212b60f58e154.yaml new file mode 100644 index 00000000..c844833b --- /dev/null +++ b/releasenotes/notes/authprotocol-accepts-oslo-config-config-a37212b60f58e154.yaml @@ -0,0 +1,10 @@ +--- +features: + - > + [`bug 1540022 `_] + The auth_token middleware will now accept a conf setting named + ``oslo_config_config``. If this is set its value must be an existing + oslo_config `ConfigOpts`. ``olso_config_config`` takes precedence over + ``oslo_config_project``. This feature is useful to applications that + are instantiating the auth_token middleware themselves and wish to + use an existing configuration.