Support the reading of default values of domain configuration options
The whitelisted configuration options, that are supported as part of the domain specific configuration functionality, can now have their defualt values read via the Identity API. DocImpact Change-Id: I9b1073f4d43c69f03fc920eee2712305524c1300 Implements: blueprint domain-config-default
This commit is contained in:

committed by
Steve Martinelli

parent
08ce1a504b
commit
a06bfe8be3
@@ -186,7 +186,9 @@ identity:update_domain_config - PATCH /v3/domains/{
|
||||
identity:delete_domain_config - DELETE /v3/domains/{domain_id}/config
|
||||
- DELETE /v3/domains/{domain_id}/config/{group}
|
||||
- DELETE /v3/domains/{domain_id}/config/{group}/{option}
|
||||
|
||||
identity:get_domain_config_default - GET /v3/domains/config/default
|
||||
- GET /v3/domains/config/{group}/default
|
||||
- GET /v3/domains/config/{group}/{option}/default
|
||||
========================================================= ===
|
||||
|
||||
.. _grant_resources:
|
||||
|
@@ -181,5 +181,6 @@
|
||||
"identity:create_domain_config": "rule:admin_required",
|
||||
"identity:get_domain_config": "rule:admin_required",
|
||||
"identity:update_domain_config": "rule:admin_required",
|
||||
"identity:delete_domain_config": "rule:admin_required"
|
||||
"identity:delete_domain_config": "rule:admin_required",
|
||||
"identity:get_domain_config_default": "rule:admin_required"
|
||||
}
|
||||
|
@@ -193,5 +193,6 @@
|
||||
"identity:create_domain_config": "rule:cloud_admin",
|
||||
"identity:get_domain_config": "rule:cloud_admin",
|
||||
"identity:update_domain_config": "rule:cloud_admin",
|
||||
"identity:delete_domain_config": "rule:cloud_admin"
|
||||
"identity:delete_domain_config": "rule:cloud_admin",
|
||||
"identity:get_domain_config_default": "rule:cloud_admin"
|
||||
}
|
||||
|
@@ -206,6 +206,11 @@ class DomainConfigV3(controller.V3Controller):
|
||||
self.resource_api.get_domain(domain_id)
|
||||
self.domain_config_api.delete_config(domain_id, group, option)
|
||||
|
||||
@controller.protected()
|
||||
def get_domain_config_default(self, context, group=None, option=None):
|
||||
ref = self.domain_config_api.get_config_default(group, option)
|
||||
return {self.member_name: ref}
|
||||
|
||||
|
||||
@dependency.requires('resource_api')
|
||||
class ProjectV3(controller.V3Controller):
|
||||
|
@@ -1519,6 +1519,59 @@ class DomainConfigManager(manager.Manager):
|
||||
"""
|
||||
return self._get_config_with_sensitive_info(domain_id)
|
||||
|
||||
def get_config_default(self, group=None, option=None):
|
||||
"""Get default config, or partial default config
|
||||
|
||||
:param group: an optional specific group of options
|
||||
:param option: an optional specific option within the group
|
||||
|
||||
:returns: a dict of group dicts containing the default options,
|
||||
filtered by group and option if specified
|
||||
:raises keystone.exception.InvalidDomainConfig: when the config
|
||||
and group/option parameters specify an option we do not
|
||||
support (or one that is not whitelisted).
|
||||
|
||||
An example response::
|
||||
|
||||
{
|
||||
'ldap': {
|
||||
'url': 'myurl',
|
||||
'user_tree_dn': 'OU=myou',
|
||||
....},
|
||||
'identity': {
|
||||
'driver': 'ldap'}
|
||||
|
||||
}
|
||||
|
||||
"""
|
||||
def _option_dict(group, option):
|
||||
group_attr = getattr(CONF, group)
|
||||
if group_attr is None:
|
||||
msg = _('Group %s not found in config') % group
|
||||
raise exception.UnexpectedError(msg)
|
||||
return {'group': group, 'option': option,
|
||||
'value': getattr(group_attr, option)}
|
||||
|
||||
self._assert_valid_group_and_option(group, option)
|
||||
config_list = []
|
||||
if group:
|
||||
if option:
|
||||
if option not in self.whitelisted_options[group]:
|
||||
msg = _('Reading the default for option %(option)s in '
|
||||
'group %(group)s is not supported') % {
|
||||
'option': option, 'group': group}
|
||||
raise exception.InvalidDomainConfig(reason=msg)
|
||||
config_list.append(_option_dict(group, option))
|
||||
else:
|
||||
for each_option in self.whitelisted_options[group]:
|
||||
config_list.append(_option_dict(group, each_option))
|
||||
else:
|
||||
for each_group in self.whitelisted_options:
|
||||
for each_option in self.whitelisted_options[each_group]:
|
||||
config_list.append(_option_dict(each_group, each_option))
|
||||
|
||||
return self._list_to_config(config_list, req_option=option)
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class DomainConfigDriverV8(object):
|
||||
|
@@ -88,6 +88,37 @@ class Routers(wsgi.RoutersBase):
|
||||
'config_option')
|
||||
})
|
||||
|
||||
self._add_resource(
|
||||
mapper, config_controller,
|
||||
path='/domains/config/default',
|
||||
get_action='get_domain_config_default',
|
||||
rel=json_home.build_v3_resource_relation('domain_config_default'),
|
||||
status=json_home.Status.EXPERIMENTAL)
|
||||
|
||||
self._add_resource(
|
||||
mapper, config_controller,
|
||||
path='/domains/config/{group}/default',
|
||||
get_action='get_domain_config_default',
|
||||
rel=json_home.build_v3_resource_relation(
|
||||
'domain_config_default_group'),
|
||||
status=json_home.Status.EXPERIMENTAL,
|
||||
path_vars={
|
||||
'group': config_group_param
|
||||
})
|
||||
|
||||
self._add_resource(
|
||||
mapper, config_controller,
|
||||
path='/domains/config/{group}/{option}/default',
|
||||
get_action='get_domain_config_default',
|
||||
rel=json_home.build_v3_resource_relation(
|
||||
'domain_config_default_option'),
|
||||
status=json_home.Status.EXPERIMENTAL,
|
||||
path_vars={
|
||||
'group': config_group_param,
|
||||
'option': json_home.build_v3_parameter_relation(
|
||||
'config_option')
|
||||
})
|
||||
|
||||
routers.append(
|
||||
router.Router(controllers.ProjectV3(),
|
||||
'projects', 'project',
|
||||
|
@@ -401,3 +401,59 @@ class DomainConfigTestCase(test_v3.RestfulTestCase):
|
||||
'invalid_option': invalid_option},
|
||||
body={'config': new_config},
|
||||
expected_status=exception.DomainNotFound.code)
|
||||
|
||||
def test_get_config_default(self):
|
||||
"""Call ``GET /domains/config/default``."""
|
||||
# Create a config that overrides a few of the options so that we can
|
||||
# check that only the defaults are returned.
|
||||
self.domain_config_api.create_config(self.domain['id'], self.config)
|
||||
url = '/domains/config/default'
|
||||
r = self.get(url)
|
||||
default_config = r.result['config']
|
||||
for group in default_config:
|
||||
for option in default_config[group]:
|
||||
self.assertEqual(getattr(getattr(CONF, group), option),
|
||||
default_config[group][option])
|
||||
|
||||
def test_get_config_default_by_group(self):
|
||||
"""Call ``GET /domains/config/{group}/default``."""
|
||||
# Create a config that overrides a few of the options so that we can
|
||||
# check that only the defaults are returned.
|
||||
self.domain_config_api.create_config(self.domain['id'], self.config)
|
||||
url = '/domains/config/ldap/default'
|
||||
r = self.get(url)
|
||||
default_config = r.result['config']
|
||||
for option in default_config['ldap']:
|
||||
self.assertEqual(getattr(CONF.ldap, option),
|
||||
default_config['ldap'][option])
|
||||
|
||||
def test_get_config_default_by_option(self):
|
||||
"""Call ``GET /domains/config/{group}/{option}/default``."""
|
||||
# Create a config that overrides a few of the options so that we can
|
||||
# check that only the defaults are returned.
|
||||
self.domain_config_api.create_config(self.domain['id'], self.config)
|
||||
url = '/domains/config/ldap/url/default'
|
||||
r = self.get(url)
|
||||
default_config = r.result['config']
|
||||
self.assertEqual(CONF.ldap.url, default_config['url'])
|
||||
|
||||
def test_get_config_default_by_invalid_group(self):
|
||||
"""Call ``GET for /domains/config/{bad-group}/default``."""
|
||||
# First try a valid group, but one we don't support for domain config
|
||||
self.get('/domains/config/resouce/default',
|
||||
expected_status=http_client.FORBIDDEN)
|
||||
|
||||
# Now try a totally invalid group
|
||||
url = '/domains/config/%s/default' % uuid.uuid4().hex
|
||||
self.get(url, expected_status=http_client.FORBIDDEN)
|
||||
|
||||
def test_get_config_default_by_invalid_option(self):
|
||||
"""Call ``GET for /domains/config/{group}/{bad-option}/default``."""
|
||||
# First try a valid option, but one we don't support for domain config,
|
||||
# i.e. one that is in the sensitive options list
|
||||
self.get('/domains/config/ldap/password/default',
|
||||
expected_status=http_client.FORBIDDEN)
|
||||
|
||||
# Now try a totally invalid option
|
||||
url = '/domains/config/ldap/%s/default' % uuid.uuid4().hex
|
||||
self.get(url, expected_status=http_client.FORBIDDEN)
|
||||
|
@@ -584,6 +584,20 @@ V3_JSON_HOME_RESOURCES = {
|
||||
'group': json_home.build_v3_parameter_relation('config_group'),
|
||||
'option': json_home.build_v3_parameter_relation('config_option')},
|
||||
'hints': {'status': 'experimental'}},
|
||||
json_home.build_v3_resource_relation('domain_config_default'): {
|
||||
'href': '/domains/config/default',
|
||||
'hints': {'status': 'experimental'}},
|
||||
json_home.build_v3_resource_relation('domain_config_default_group'): {
|
||||
'href-template': '/domains/config/{group}/default',
|
||||
'href-vars': {
|
||||
'group': json_home.build_v3_parameter_relation('config_group')},
|
||||
'hints': {'status': 'experimental'}},
|
||||
json_home.build_v3_resource_relation('domain_config_default_option'): {
|
||||
'href-template': '/domains/config/{group}/{option}/default',
|
||||
'href-vars': {
|
||||
'group': json_home.build_v3_parameter_relation('config_group'),
|
||||
'option': json_home.build_v3_parameter_relation('config_option')},
|
||||
'hints': {'status': 'experimental'}},
|
||||
}
|
||||
|
||||
|
||||
|
@@ -0,0 +1,7 @@
|
||||
---
|
||||
features:
|
||||
- >
|
||||
[`blueprint domain-config-default <https://blueprints.launchpad.net/keystone/+spec/domain-config-default>`_]
|
||||
The Identity API now supports retrieving the default values for the
|
||||
configuration options that can be overriden via the domain specific
|
||||
configuration API.
|
Reference in New Issue
Block a user