diff --git a/keystone/tests/unit/core.py b/keystone/tests/unit/core.py index 0c5776a646..c58d2c7444 100644 --- a/keystone/tests/unit/core.py +++ b/keystone/tests/unit/core.py @@ -307,16 +307,19 @@ def new_domain_ref(**kwargs): return ref -def new_project_ref(domain_id=None, parent_id=None, is_domain=False, **kwargs): +def new_project_ref(domain_id=None, is_domain=False, **kwargs): ref = { 'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex, 'description': uuid.uuid4().hex, 'enabled': True, 'domain_id': domain_id, - 'parent_id': parent_id, 'is_domain': is_domain, } + # NOTE(henry-nash): We don't include parent_id in the initial list above + # since specifying it is optional depending on where the project sits in + # the hierarchy (and a parent_id of None has meaning - i.e. it's a top + # level project). ref.update(kwargs) return ref diff --git a/keystone/tests/unit/test_backend.py b/keystone/tests/unit/test_backend.py index 79d2b7615f..fd0edf09a0 100644 --- a/keystone/tests/unit/test_backend.py +++ b/keystone/tests/unit/test_backend.py @@ -2212,7 +2212,7 @@ class IdentityTests(AssignmentTestHelperMixin): project = unit.new_project_ref( name=unicode_project_name, domain_id=CONF.identity.default_domain_id) - self.resource_api.create_project(project['id'], project) + project = self.resource_api.create_project(project['id'], project) self.resource_api.update_project(project['id'], project) self.resource_api.delete_project(project['id']) @@ -2474,7 +2474,7 @@ class IdentityTests(AssignmentTestHelperMixin): def test_list_projects_with_multiple_filters(self): # Create a project project = unit.new_project_ref(domain_id=DEFAULT_DOMAIN_ID) - self.resource_api.create_project(project['id'], project) + project = self.resource_api.create_project(project['id'], project) # Build driver hints with the project's name and inexistent description hints = driver_hints.Hints() @@ -2548,7 +2548,7 @@ class IdentityTests(AssignmentTestHelperMixin): project = unit.new_project_ref(domain_id=domain_id, is_domain=is_domain) project_id = project['id'] - self.resource_api.create_project(project_id, project) + project = self.resource_api.create_project(project_id, project) projects = [project] for i in range(1, hierarchy_size): @@ -2665,18 +2665,11 @@ class IdentityTests(AssignmentTestHelperMixin): @unit.skip_if_no_multiple_domains_support def test_create_subproject_acting_as_domain_fails(self): - root_project = {'id': uuid.uuid4().hex, - 'domain_id': DEFAULT_DOMAIN_ID, - 'name': uuid.uuid4().hex, - 'parent_id': None, - 'is_domain': True} + root_project = unit.new_project_ref(is_domain=True) self.resource_api.create_project(root_project['id'], root_project) - sub_project = {'id': uuid.uuid4().hex, - 'domain_id': DEFAULT_DOMAIN_ID, - 'name': uuid.uuid4().hex, - 'parent_id': root_project['id'], - 'is_domain': True} + sub_project = unit.new_project_ref(is_domain=True, + parent_id=root_project['id']) # Creation of sub projects acting as domains is not allowed yet self.assertRaises(exception.ValidationError, @@ -2719,8 +2712,7 @@ class IdentityTests(AssignmentTestHelperMixin): @unit.skip_if_no_multiple_domains_support def test_create_project_passing_is_domain_flag_true(self): - project = unit.new_project_ref(domain_id=DEFAULT_DOMAIN_ID, - is_domain=True) + project = unit.new_project_ref(is_domain=True) ref = self.resource_api.create_project(project['id'], project) self.assertTrue(ref['is_domain']) @@ -2732,11 +2724,12 @@ class IdentityTests(AssignmentTestHelperMixin): ref = self.resource_api.create_project(project['id'], project) self.assertIs(False, ref['is_domain']) - @test_utils.wip('waiting for projects acting as domains implementation') + @test_utils.wip('waiting for support for parent_id to imply domain_id') def test_create_project_with_parent_id_and_without_domain_id(self): - project = unit.new_project_ref(domain_id=None) + # First create a domain + project = unit.new_project_ref(is_domain=True) self.resource_api.create_project(project['id'], project) - + # Now create a child by just naming the parent_id sub_project = unit.new_project_ref(parent_id=project['id']) ref = self.resource_api.create_project(sub_project['id'], sub_project) @@ -2745,9 +2738,10 @@ class IdentityTests(AssignmentTestHelperMixin): @test_utils.wip('waiting for projects acting as domains implementation') def test_create_project_with_domain_id_and_without_parent_id(self): - project = unit.new_project_ref(parent_id=None) + # First create a domain + project = unit.new_project_ref(is_domain=True) self.resource_api.create_project(project['id'], project) - + # Now create a child by just naming the domain_id sub_project = unit.new_project_ref(domain_id=project['id']) ref = self.resource_api.create_project(sub_project['id'], sub_project) @@ -2796,7 +2790,7 @@ class IdentityTests(AssignmentTestHelperMixin): def test_list_projects_in_subtree_with_circular_reference(self): project1 = unit.new_project_ref(domain_id=DEFAULT_DOMAIN_ID) - self.resource_api.create_project(project1['id'], project1) + project1 = self.resource_api.create_project(project1['id'], project1) project2 = unit.new_project_ref(domain_id=DEFAULT_DOMAIN_ID, parent_id=project1['id']) @@ -3674,7 +3668,7 @@ class IdentityTests(AssignmentTestHelperMixin): # Creating a project with no description attribute. project = unit.new_project_ref(domain_id=DEFAULT_DOMAIN_ID) del project['description'] - self.resource_api.create_project(project['id'], project) + project = self.resource_api.create_project(project['id'], project) # Add a description attribute. project['description'] = uuid.uuid4().hex @@ -3687,7 +3681,7 @@ class IdentityTests(AssignmentTestHelperMixin): # Creating a project with no description attribute. project = unit.new_project_ref(domain_id=DEFAULT_DOMAIN_ID) del project['description'] - self.resource_api.create_project(project['id'], project) + project = self.resource_api.create_project(project['id'], project) # Add a description attribute. project['description'] = '' @@ -3698,12 +3692,14 @@ class IdentityTests(AssignmentTestHelperMixin): def test_domain_crud(self): domain = unit.new_domain_ref() - self.resource_api.create_domain(domain['id'], domain) + domain_ref = self.resource_api.create_domain(domain['id'], domain) + self.assertDictEqual(domain, domain_ref) domain_ref = self.resource_api.get_domain(domain['id']) self.assertDictEqual(domain, domain_ref) domain['name'] = uuid.uuid4().hex - self.resource_api.update_domain(domain['id'], domain) + domain_ref = self.resource_api.update_domain(domain['id'], domain) + self.assertDictEqual(domain, domain_ref) domain_ref = self.resource_api.get_domain(domain['id']) self.assertDictEqual(domain, domain_ref) @@ -6365,10 +6361,12 @@ class InheritanceTests(AssignmentTestHelperMixin): # Enable OS-INHERIT extension self.config_fixture.config(group='os_inherit', enabled=True) root_project = unit.new_project_ref(domain_id=DEFAULT_DOMAIN_ID) - self.resource_api.create_project(root_project['id'], root_project) + root_project = self.resource_api.create_project(root_project['id'], + root_project) leaf_project = unit.new_project_ref(domain_id=DEFAULT_DOMAIN_ID, parent_id=root_project['id']) - self.resource_api.create_project(leaf_project['id'], leaf_project) + leaf_project = self.resource_api.create_project(leaf_project['id'], + leaf_project) user = unit.new_user_ref(domain_id=DEFAULT_DOMAIN_ID) user = self.identity_api.create_user(user) @@ -6557,10 +6555,12 @@ class InheritanceTests(AssignmentTestHelperMixin): """ self.config_fixture.config(group='os_inherit', enabled=True) root_project = unit.new_project_ref(domain_id=DEFAULT_DOMAIN_ID) - self.resource_api.create_project(root_project['id'], root_project) + root_project = self.resource_api.create_project(root_project['id'], + root_project) leaf_project = unit.new_project_ref(domain_id=DEFAULT_DOMAIN_ID, parent_id=root_project['id']) - self.resource_api.create_project(leaf_project['id'], leaf_project) + leaf_project = self.resource_api.create_project(leaf_project['id'], + leaf_project) user = unit.new_user_ref(domain_id=DEFAULT_DOMAIN_ID) user = self.identity_api.create_user(user) diff --git a/keystone/tests/unit/test_backend_ldap.py b/keystone/tests/unit/test_backend_ldap.py index 36ccecf40b..46349196dd 100644 --- a/keystone/tests/unit/test_backend_ldap.py +++ b/keystone/tests/unit/test_backend_ldap.py @@ -1477,7 +1477,7 @@ class LDAPIdentity(BaseLDAPIdentity, unit.TestCase): project = unit.new_project_ref( domain_id=CONF.identity.default_domain_id) - self.resource_api.create_project(project['id'], project) + project = self.resource_api.create_project(project['id'], project) project_ref = self.resource_api.get_project(project['id']) self.assertDictEqual(project, project_ref) @@ -1501,7 +1501,7 @@ class LDAPIdentity(BaseLDAPIdentity, unit.TestCase): domain_id=CONF.identity.default_domain_id) project_id = project['id'] # Create a project - self.resource_api.create_project(project_id, project) + project = self.resource_api.create_project(project_id, project) self.resource_api.get_project(project_id) updated_project = copy.deepcopy(project) updated_project['description'] = uuid.uuid4().hex @@ -1548,7 +1548,7 @@ class LDAPIdentity(BaseLDAPIdentity, unit.TestCase): def test_update_is_domain_field(self): domain = self._get_domain_fixture() project = unit.new_project_ref(domain_id=domain['id']) - self.resource_api.create_project(project['id'], project) + project = self.resource_api.create_project(project['id'], project) # Try to update the is_domain field to True project['is_domain'] = True @@ -1908,7 +1908,7 @@ class LDAPIdentityEnabledEmulation(LDAPIdentity): project = unit.new_project_ref( domain_id=CONF.identity.default_domain_id) - self.resource_api.create_project(project['id'], project) + project = self.resource_api.create_project(project['id'], project) project_ref = self.resource_api.get_project(project['id']) # self.resource_api.create_project adds an enabled @@ -2512,7 +2512,7 @@ class MultiLDAPandSQLIdentity(BaseLDAPIdentity, unit.SQLDriverOverrides, domain = unit.new_domain_ref() project = unit.new_project_ref(domain_id=domain['id']) self.resource_api.create_domain(domain['id'], domain) - self.resource_api.create_project(project['id'], project) + project = self.resource_api.create_project(project['id'], project) project_ref = self.resource_api.get_project(project['id']) self.assertDictEqual(project, project_ref) diff --git a/keystone/tests/unit/test_backend_sql.py b/keystone/tests/unit/test_backend_sql.py index 265325d86a..f23358daba 100644 --- a/keystone/tests/unit/test_backend_sql.py +++ b/keystone/tests/unit/test_backend_sql.py @@ -270,8 +270,8 @@ class SqlIdentity(SqlTests, test_backend.IdentityTests): self.assertEqual(arbitrary_value, ref[arbitrary_key]) self.assertIsNone(ref.get('extra')) - project['name'] = uuid.uuid4().hex - ref = self.resource_api.update_project(project['id'], project) + ref['name'] = uuid.uuid4().hex + ref = self.resource_api.update_project(ref['id'], ref) self.assertEqual(arbitrary_value, ref[arbitrary_key]) self.assertEqual(arbitrary_value, ref['extra'][arbitrary_key]) diff --git a/keystone/tests/unit/test_v3.py b/keystone/tests/unit/test_v3.py index efd2ad94a8..5013ad765c 100644 --- a/keystone/tests/unit/test_v3.py +++ b/keystone/tests/unit/test_v3.py @@ -315,7 +315,8 @@ class RestfulTestCase(unit.SQLDriverOverrides, rest.RestfulTestCase, self.project = unit.new_project_ref(domain_id=self.domain_id) self.project_id = self.project['id'] - self.resource_api.create_project(self.project_id, self.project) + self.project = self.resource_api.create_project(self.project_id, + self.project) self.user = unit.create_user(self.identity_api, domain_id=self.domain_id) diff --git a/keystone/tests/unit/test_v3_resource.py b/keystone/tests/unit/test_v3_resource.py index 7946c9a5ca..2a0ab12c19 100644 --- a/keystone/tests/unit/test_v3_resource.py +++ b/keystone/tests/unit/test_v3_resource.py @@ -20,6 +20,7 @@ from keystone.common import controller from keystone import exception from keystone.tests import unit from keystone.tests.unit import test_v3 +from keystone.tests.unit import utils as test_utils CONF = cfg.CONF @@ -92,6 +93,42 @@ class ResourceTestCase(test_v3.RestfulTestCase, '/domains', body={'domain': ref}) + @test_utils.wip('waiting for projects acting as domains implementation') + def test_create_domain_creates_is_domain_project(self): + """Call ``POST /domains`` and check a project that acts as a domain + is created. + """ + # Create a new domain + domain_ref = unit.new_domain_ref() + r = self.post('/domains', body={'domain': domain_ref}) + self.assertValidDomainResponse(r, domain_ref) + + # Retrieve its correspondent project + r = self.get('/projects/%(project_id)s' % { + 'project_id': r.result['domain']['id']}) + self.assertValidProjectResponse(r) + + # The created project has is_domain flag as True + self.assertTrue(r.result['project']['is_domain']) + + # And its parent_id and domain_id attributes are equal + self.assertIsNone(r.result['project']['parent_id']) + self.assertIsNone(r.result['project']['domain_id']) + + @test_utils.wip('waiting for projects acting as domains implementation') + def test_create_is_domain_project_creates_domain(self): + """Call ``POST /projects`` is_domain and check a domain is created.""" + # Create a new project that acts as a domain + project_ref = unit.new_project_ref(domain_id=None, is_domain=True) + r = self.post('/projects', body={'project': project_ref}) + self.assertValidProjectResponse(r) + + # Retrieve its correspondent domain + r = self.get('/domains/%(domain_id)s' % { + 'domain_id': r.result['project']['id']}) + self.assertValidDomainResponse(r) + self.assertIsNotNone(r.result['domain']) + def test_list_domains(self): """Call ``GET /domains``.""" resource_url = '/domains' @@ -148,6 +185,28 @@ class ResourceTestCase(test_v3.RestfulTestCase, 'domain_id': self.domain_id}, body={'domain': ref}) + @test_utils.wip('waiting for projects acting as domains implementation') + def test_update_domain_updates_is_domain_project(self): + """Call ``PATCH /domains`` and check the project that acts as a domain + is updated. + """ + # Create a new domain + domain_ref = unit.new_domain_ref() + r = self.post('/domains', body={'domain': domain_ref}) + self.assertValidDomainResponse(r, domain_ref) + + # Disable it + self.patch('/domains/%s' % r.result['domain']['id'], + body={'domain': {'enabled': False}}) + + # Retrieve its correspondent project + r = self.get('/projects/%(project_id)s' % { + 'project_id': r.result['domain']['id']}) + self.assertValidProjectResponse(r) + + # The created project is disabled as well + self.assertFalse(r.result['project']['enabled']) + def test_disable_domain(self): """Call ``PATCH /domains/{domain_id}`` (set enabled=False).""" # Create a 2nd set of entities in a 2nd domain @@ -261,7 +320,7 @@ class ResourceTestCase(test_v3.RestfulTestCase, self.resource_api.create_domain(domain2['id'], domain2) project2 = unit.new_project_ref(domain_id=domain2['id']) - self.resource_api.create_project(project2['id'], project2) + project2 = self.resource_api.create_project(project2['id'], project2) user2 = unit.new_user_ref(domain_id=domain2['id'], project_id=project2['id']) @@ -313,6 +372,29 @@ class ResourceTestCase(test_v3.RestfulTestCase, r = self.credential_api.get_credential(credential['id']) self.assertDictEqual(credential, r) + @test_utils.wip('waiting for projects acting as domains implementation') + def test_delete_domain_deletes_is_domain_project(self): + """Call ``DELETE /domains`` and check the project that acts as a domain + is deleted. + """ + # Create a new domain + domain_ref = unit.new_domain_ref() + r = self.post('/domains', body={'domain': domain_ref}) + self.assertValidDomainResponse(r, domain_ref) + + # Retrieve its correspondent project + self.get('/projects/%(project_id)s' % { + 'project_id': r.result['domain']['id']}) + + # Delete the domain + self.patch('/domains/%s' % r.result['domain']['id'], + body={'domain': {'enabled': False}}) + self.delete('/domains/%s' % r.result['domain']['id']) + + # The created project is deleted as well + self.get('/projects/%(project_id)s' % { + 'project_id': r.result['domain']['id']}, expected_status=404) + def test_delete_default_domain(self): # Need to disable it first. self.patch('/domains/%(domain_id)s' % { @@ -369,7 +451,8 @@ class ResourceTestCase(test_v3.RestfulTestCase, self.resource_api.create_domain(domain['id'], domain) root_project = unit.new_project_ref(domain_id=domain['id']) - self.resource_api.create_project(root_project['id'], root_project) + root_project = self.resource_api.create_project(root_project['id'], + root_project) leaf_project = unit.new_project_ref( domain_id=domain['id'], @@ -984,7 +1067,8 @@ class ResourceTestCase(test_v3.RestfulTestCase, def test_update_project(self): """Call ``PATCH /projects/{project_id}``.""" - ref = unit.new_project_ref(domain_id=self.domain_id) + ref = unit.new_project_ref(domain_id=self.domain_id, + parent_id=self.project['parent_id']) del ref['id'] r = self.patch( '/projects/%(project_id)s' % { @@ -999,7 +1083,8 @@ class ResourceTestCase(test_v3.RestfulTestCase, self.config_fixture.config(group='resource', project_name_url_safe='off') ref = unit.new_project_ref(name=unsafe_name, - domain_id=self.domain_id) + domain_id=self.domain_id, + parent_id=self.project['parent_id']) del ref['id'] self.patch( '/projects/%(project_id)s' % { @@ -1011,7 +1096,8 @@ class ResourceTestCase(test_v3.RestfulTestCase, self.config_fixture.config(group='resource', project_name_url_safe=config_setting) ref = unit.new_project_ref(name=unsafe_name, - domain_id=self.domain_id) + domain_id=self.domain_id, + parent_id=self.project['parent_id']) del ref['id'] self.patch( '/projects/%(project_id)s' % { @@ -1025,7 +1111,8 @@ class ResourceTestCase(test_v3.RestfulTestCase, # By default, we should be able to create unsafe names ref = unit.new_project_ref(name=unsafe_name, - domain_id=self.domain_id) + domain_id=self.domain_id, + parent_id=self.project['parent_id']) del ref['id'] self.patch( '/projects/%(project_id)s' % { @@ -1035,7 +1122,7 @@ class ResourceTestCase(test_v3.RestfulTestCase, def test_update_project_domain_id(self): """Call ``PATCH /projects/{project_id}`` with domain_id.""" project = unit.new_project_ref(domain_id=self.domain['id']) - self.resource_api.create_project(project['id'], project) + project = self.resource_api.create_project(project['id'], project) project['domain_id'] = CONF.identity.default_domain_id r = self.patch('/projects/%(project_id)s' % { 'project_id': project['id']}, @@ -1069,6 +1156,7 @@ class ResourceTestCase(test_v3.RestfulTestCase, body={'project': project}) self.assertFalse(resp.result['project']['is_domain']) + project['parent_id'] = resp.result['project']['parent_id'] project['is_domain'] = True self.patch('/projects/%(project_id)s' % { 'project_id': resp.result['project']['id']},