Merge "V2 operations create default domain on demand"
This commit is contained in:
commit
cf8e30e0dd
|
@ -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)
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -909,6 +909,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
|
||||
|
|
|
@ -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.
|
|
@ -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.
|
|
@ -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)
|
Loading…
Reference in New Issue