Add tests in preparation of projects acting as a domain
In subsequent patches projects will start acting as domains. This patch adds REST level tests, protected by the wip decorator, that will validate the external view of projects acting as domains. This patch also modifies the unit.new_project_ref() test helper to better represent that parent_id is an optional parameter for 1st level projects (since their parent is defined by their domain_id). This will allow us to better test the various mixtures of domain_id and parent_id in future patches. This exposed a number of test cases which did not allow for the fact that parent_id may not have been set by new_project_ref(). Co-Authored-By: Henrique Truta <henrique@lsd.ufcg.edu.br> Co-Authored-By: Rodrigo Duarte <rodrigods@lsd.ufcg.edu.br> Partially implements: blueprint reseller Change-Id: Ibd4b6ca35746ad497523c01352b7b6b985ac8a7f
This commit is contained in:
parent
72faa02851
commit
de40ce1e92
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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])
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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']},
|
||||
|
|
Loading…
Reference in New Issue