V2 operations create default domain on demand

To support deployment utilities that are still using v2, create a
default domain for them when they first use the v2 API.

Change-Id: I148dd8094f4146f470ecedac34530a4744bac97c
This commit is contained in:
Brant Knudson 2016-02-25 08:55:01 -06:00 committed by Steve Martinelli
parent faf713e18a
commit 57b4b096fc
7 changed files with 251 additions and 2 deletions

View File

@ -80,6 +80,8 @@ class User(controller.V2Controller):
self.resource_api.get_project(default_project_id)
user['default_project_id'] = default_project_id
self.resource_api.ensure_default_domain_exists()
# The manager layer will generate the unique ID for users
user_ref = self._normalize_domain_id(context, user.copy())
initiator = notifications._get_request_audit_info(context)

View File

@ -43,8 +43,13 @@ class Tenant(controller.V2Controller):
if 'name' in context['query_string']:
return self._get_project_by_name(context['query_string']['name'])
tenant_refs = self.resource_api.list_projects_in_domain(
CONF.identity.default_domain_id)
try:
tenant_refs = self.resource_api.list_projects_in_domain(
CONF.identity.default_domain_id)
except exception.DomainNotFound:
# If the default domain doesn't exist then there are no V2
# projects.
tenant_refs = []
tenant_refs = [self.v3_to_v2_project(tenant_ref)
for tenant_ref in tenant_refs
if not tenant_ref.get('is_domain')]
@ -91,6 +96,9 @@ class Tenant(controller.V2Controller):
raise exception.ValidationError(message=msg)
self.assert_admin(context)
self.resource_api.ensure_default_domain_exists()
tenant_ref['id'] = tenant_ref.get('id', uuid.uuid4().hex)
initiator = notifications._get_request_audit_info(context)
tenant = self.resource_api.create_project(

View File

@ -794,6 +794,32 @@ class Manager(manager.Manager):
# from persistence if persistence is enabled.
pass
def ensure_default_domain_exists(self):
"""Creates the default domain if it doesn't exist.
This is only used for the v2 API and can go away when V2 does.
"""
try:
default_domain_attrs = {
'name': 'Default',
'id': CONF.identity.default_domain_id,
'description': 'Domain created automatically to support V2.0 '
'operations.',
}
self.create_domain(CONF.identity.default_domain_id,
default_domain_attrs)
LOG.warning(_LW(
'The default domain was created automatically to contain V2 '
'resources. This is deprecated in the M release and will not '
'be supported in the O release. Create the default domain '
'manually or use the keystone-manage bootstrap command.'))
except exception.Conflict:
LOG.debug('The default domain already exists.')
except Exception:
LOG.error(_LE('Failed to create the default domain.'))
raise
# The ResourceDriverBase class is the set of driver methods from earlier
# drivers that we still support, that have not been removed or modified. This

View File

@ -0,0 +1,65 @@
# Copyright 2016 IBM Corp.
#
# 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 uuid
from oslo_config import cfg
from keystone import exception
from keystone.identity import controllers
from keystone.tests import unit
from keystone.tests.unit.ksfixtures import database
CONF = cfg.CONF
_ADMIN_CONTEXT = {'is_admin': True, 'query_string': {}}
class UserTestCaseNoDefaultDomain(unit.TestCase):
def setUp(self):
super(UserTestCaseNoDefaultDomain, self).setUp()
self.useFixture(database.Database())
self.load_backends()
self.user_controller = controllers.User()
def test_setup(self):
# Other tests in this class assume there's no default domain, so make
# sure the setUp worked as expected.
self.assertRaises(
exception.DomainNotFound,
self.resource_api.get_domain, CONF.identity.default_domain_id)
def test_get_users(self):
# When list_users is done and there's no default domain, the result is
# an empty list.
res = self.user_controller.get_users(_ADMIN_CONTEXT)
self.assertEqual([], res['users'])
def test_get_user_by_name(self):
# When get_user_by_name is done and there's no default domain, the
# result is 404 Not Found
user_name = uuid.uuid4().hex
self.assertRaises(
exception.UserNotFound,
self.user_controller.get_user_by_name, _ADMIN_CONTEXT, user_name)
def test_create_user(self):
# When a user is created using the v2 controller and there's no default
# domain, it doesn't fail with can't find domain (a default domain is
# created)
user = {'name': uuid.uuid4().hex}
self.user_controller.create_user(_ADMIN_CONTEXT, user)
# If the above doesn't fail then this is successful.

View File

View File

@ -0,0 +1,57 @@
# Copyright 2016 IBM Corp.
#
# 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 uuid
from oslo_config import cfg
from keystone import exception
from keystone.resource import controllers
from keystone.tests import unit
from keystone.tests.unit.ksfixtures import database
CONF = cfg.CONF
_ADMIN_CONTEXT = {'is_admin': True, 'query_string': {}}
class TenantTestCaseNoDefaultDomain(unit.TestCase):
def setUp(self):
super(TenantTestCaseNoDefaultDomain, self).setUp()
self.useFixture(database.Database())
self.load_backends()
self.tenant_controller = controllers.Tenant()
def test_setup(self):
# Other tests in this class assume there's no default domain, so make
# sure the setUp worked as expected.
self.assertRaises(
exception.DomainNotFound,
self.resource_api.get_domain, CONF.identity.default_domain_id)
def test_get_all_projects(self):
# When get_all_projects is done and there's no default domain, the
# result is an empty list.
res = self.tenant_controller.get_all_projects(_ADMIN_CONTEXT)
self.assertEqual([], res['tenants'])
def test_create_project(self):
# When a project is created using the v2 controller and there's no
# default domain, it doesn't fail with can't find domain (a default
# domain is created)
tenant = {'name': uuid.uuid4().hex}
self.tenant_controller.create_project(_ADMIN_CONTEXT, tenant)
# If the above doesn't fail then this is successful.

View File

@ -0,0 +1,91 @@
# 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 uuid
from oslo_config import cfg
from oslotest import mockpatch
from keystone import exception
from keystone.tests import unit
from keystone.tests.unit.ksfixtures import database
CONF = cfg.CONF
class TestResourceManagerNoFixtures(unit.SQLDriverOverrides, unit.TestCase):
def setUp(self):
super(TestResourceManagerNoFixtures, self).setUp()
self.useFixture(database.Database(self.sql_driver_version_overrides))
self.load_backends()
def test_ensure_default_domain_exists(self):
# When there's no default domain, ensure_default_domain_exists creates
# it.
# First make sure there's no default domain.
self.assertRaises(
exception.DomainNotFound,
self.resource_api.get_domain, CONF.identity.default_domain_id)
self.resource_api.ensure_default_domain_exists()
default_domain = self.resource_api.get_domain(
CONF.identity.default_domain_id)
expected_domain = {
'id': CONF.identity.default_domain_id,
'name': 'Default',
'enabled': True,
'description': 'Domain created automatically to support V2.0 '
'operations.',
}
self.assertEqual(expected_domain, default_domain)
def test_ensure_default_domain_exists_already_exists(self):
# When there's already a default domain, ensure_default_domain_exists
# doesn't do anything.
name = uuid.uuid4().hex
description = uuid.uuid4().hex
domain_attrs = {
'id': CONF.identity.default_domain_id,
'name': name,
'description': description,
}
self.resource_api.create_domain(CONF.identity.default_domain_id,
domain_attrs)
self.resource_api.ensure_default_domain_exists()
default_domain = self.resource_api.get_domain(
CONF.identity.default_domain_id)
expected_domain = {
'id': CONF.identity.default_domain_id,
'name': name,
'enabled': True,
'description': description,
}
self.assertEqual(expected_domain, default_domain)
def test_ensure_default_domain_exists_fails(self):
# When there's an unexpected exception creating domain it's passed on.
self.useFixture(mockpatch.PatchObject(
self.resource_api, 'create_domain',
side_effect=exception.UnexpectedError))
self.assertRaises(exception.UnexpectedError,
self.resource_api.ensure_default_domain_exists)