keystonemiddleware/keystonemiddleware/_common/config.py

160 lines
5.7 KiB
Python

# 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 pkg_resources
from oslo_config import cfg
from oslo_log import log as logging
import pbr
from keystonemiddleware import exceptions
from keystonemiddleware.i18n import _
CONF = cfg.CONF
_NOT_SET = object()
_LOG = logging.getLogger(__name__)
def _conf_values_type_convert(group_name, all_options, conf):
"""Convert conf values into correct type."""
if not conf:
return {}
opts = {}
opt_types = {}
for group, options in all_options:
# only accept paste overrides for the primary group
if group != group_name:
continue
for o in options:
type_dest = (getattr(o, 'type', str), o.dest)
opt_types[o.dest] = type_dest
# Also add the deprecated name with the same type and dest.
for d_o in o.deprecated_opts:
opt_types[d_o.name] = type_dest
break
for k, v in conf.items():
dest = k
try:
# 'here' and '__file__' come from paste.deploy
# 'configkey' is added by panko and gnocchi
if v is not None and k not in ['here', '__file__', 'configkey']:
type_, dest = opt_types[k]
v = type_(v)
except KeyError: # nosec
_LOG.warning(
'The option "%s" is not known to keystonemiddleware', k)
except ValueError as e:
raise exceptions.ConfigurationError(
_('Unable to convert the value of option "%(key)s" into '
'correct type: %(ex)s') % {'key': k, 'ex': e})
opts[dest] = v
return opts
class Config(object):
def __init__(self, name, group_name, all_options, conf):
local_oslo_config = conf.pop('oslo_config_config', None)
local_config_project = conf.pop('oslo_config_project', None)
local_config_file = conf.pop('oslo_config_file', None)
# NOTE(wanghong): If options are set in paste file, all the option
# values passed into conf are string type. So, we should convert the
# conf value into correct type.
self.paste_overrides = _conf_values_type_convert(group_name,
all_options,
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.
if local_config_project and not local_oslo_config:
config_files = [local_config_file] if local_config_file else None
local_oslo_config = cfg.ConfigOpts()
local_oslo_config([],
project=local_config_project,
default_config_files=config_files,
validate_default_values=True)
if local_oslo_config:
for group, opts in all_options:
local_oslo_config.register_opts(opts, group=group)
self.name = name
self.oslo_conf_obj = local_oslo_config or cfg.CONF
self.group_name = group_name
self._user_agent = None
def get(self, name, group=_NOT_SET):
# try config from paste-deploy first
try:
return self.paste_overrides[name]
except KeyError:
if group is _NOT_SET:
group = self.group_name
return self.oslo_conf_obj[group][name]
@property
def project(self):
"""Determine a project name from all available config sources.
The sources are checked in the following order:
1. The paste-deploy config for auth_token middleware
2. The keystone_authtoken or base group in the project's config
3. The oslo.config CONF.project property
"""
try:
return self.get('project', group=self.group_name)
except cfg.NoSuchOptError:
try:
# CONF.project will exist only if the service uses
# oslo.config. It will only be set when the project
# calls CONF(...) and when not set oslo.config oddly
# raises a NoSuchOptError exception.
return self.oslo_conf_obj.project
except cfg.NoSuchOptError:
return None
@property
def user_agent(self):
if not self._user_agent:
project = self.project or ''
if project:
try:
version = pkg_resources.get_distribution(project).version
except pkg_resources.DistributionNotFound:
version = "unknown"
project = "%s/%s " % (project, version)
self._user_agent = "%skeystonemiddleware.%s/%s" % (
project,
self.name,
pbr.version.VersionInfo('keystonemiddleware').version_string())
return self._user_agent