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:
Henry Nash
2015-12-20 22:35:28 +00:00
committed by Steve Martinelli
parent 08ce1a504b
commit a06bfe8be3
9 changed files with 173 additions and 3 deletions

View File

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

View File

@@ -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"
}

View File

@@ -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"
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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