Add 'parent' property for keystone project

Keystone v3 supports the tenant hierarchy, so add
'parent' property for project resource in heat to
allow user specify the parent when creating a project
with heat template.

Change-Id: Ia7a2d68be5fe333809eefcbf74d6b56272b2af03
Closes-Bug: #1505117
This commit is contained in:
huangtianhua 2015-10-15 10:07:36 +08:00
parent 20e986d88a
commit 9d5bdde09b
2 changed files with 34 additions and 11 deletions

View File

@ -30,9 +30,9 @@ class KeystoneProject(resource.Resource):
entity = 'projects' entity = 'projects'
PROPERTIES = ( PROPERTIES = (
NAME, DOMAIN, DESCRIPTION, ENABLED NAME, DOMAIN, DESCRIPTION, ENABLED, PARENT,
) = ( ) = (
'name', 'domain', 'description', 'enabled' 'name', 'domain', 'description', 'enabled', 'parent',
) )
properties_schema = { properties_schema = {
@ -59,7 +59,14 @@ class KeystoneProject(resource.Resource):
_('This project is enabled or disabled.'), _('This project is enabled or disabled.'),
default=True, default=True,
update_allowed=True update_allowed=True
) ),
PARENT: properties.Schema(
properties.Schema.STRING,
_('The name or ID of parent of this keystone project '
'in hierarchy.'),
support_status=support.SupportStatus(version='6.0.0'),
constraints=[constraints.CustomConstraint('keystone.project')]
),
} }
def client(self): def client(self):
@ -72,12 +79,15 @@ class KeystoneProject(resource.Resource):
domain = self.client_plugin().get_domain_id( domain = self.client_plugin().get_domain_id(
self.properties[self.DOMAIN]) self.properties[self.DOMAIN])
enabled = self.properties[self.ENABLED] enabled = self.properties[self.ENABLED]
pp = self.properties[self.PARENT]
parent = self.client_plugin().get_project_id(pp)
project = self.client().projects.create( project = self.client().projects.create(
name=project_name, name=project_name,
domain=domain, domain=domain,
description=description, description=description,
enabled=enabled) enabled=enabled,
parent=parent)
self.resource_id_set(project.id) self.resource_id_set(project.id)

View File

@ -30,7 +30,8 @@ keystone_project_template = {
'name': 'test_project_1', 'name': 'test_project_1',
'description': 'Test project', 'description': 'Test project',
'domain': 'default', 'domain': 'default',
'enabled': 'True' 'enabled': 'True',
'parent': 'my_father'
} }
} }
} }
@ -59,11 +60,12 @@ class KeystoneProjectTest(common.HeatTestCase):
self.projects = self.keystoneclient.projects self.projects = self.keystoneclient.projects
# Mock client plugin # Mock client plugin
def _domain_side_effect(value): def _id_side_effect(value):
return value return value
keystone_client_plugin = mock.MagicMock() keystone_client_plugin = mock.MagicMock()
keystone_client_plugin.get_domain_id.side_effect = _domain_side_effect keystone_client_plugin.get_domain_id.side_effect = _id_side_effect
keystone_client_plugin.get_project_id.side_effect = _id_side_effect
self.test_project.client_plugin = mock.MagicMock() self.test_project.client_plugin = mock.MagicMock()
self.test_project.client_plugin.return_value = keystone_client_plugin self.test_project.client_plugin.return_value = keystone_client_plugin
@ -98,6 +100,9 @@ class KeystoneProjectTest(common.HeatTestCase):
self.assertEqual( self.assertEqual(
True, True,
self.test_project.properties.get(project.KeystoneProject.ENABLED)) self.test_project.properties.get(project.KeystoneProject.ENABLED))
self.assertEqual(
'my_father',
self.test_project.properties.get(project.KeystoneProject.PARENT))
self.test_project.handle_create() self.test_project.handle_create()
@ -106,7 +111,8 @@ class KeystoneProjectTest(common.HeatTestCase):
name='test_project_1', name='test_project_1',
description='Test project', description='Test project',
domain='default', domain='default',
enabled=True) enabled=True,
parent='my_father')
# validate physical resource id # validate physical resource id
self.assertEqual(mock_project.id, self.test_project.resource_id) self.assertEqual(mock_project.id, self.test_project.resource_id)
@ -116,7 +122,8 @@ class KeystoneProjectTest(common.HeatTestCase):
project.KeystoneProject.NAME: 'name', project.KeystoneProject.NAME: 'name',
project.KeystoneProject.DESCRIPTION: 'description', project.KeystoneProject.DESCRIPTION: 'description',
project.KeystoneProject.DOMAIN: 'domain', project.KeystoneProject.DOMAIN: 'domain',
project.KeystoneProject.ENABLED: 'enabled' project.KeystoneProject.ENABLED: 'enabled',
project.KeystoneProject.PARENT: 'parent'
} }
for actual_title, expected_title in property_title_map.items(): for actual_title, expected_title in property_title_map.items():
@ -241,7 +248,10 @@ class KeystoneProjectTest(common.HeatTestCase):
project.KeystoneProject.DOMAIN)), project.KeystoneProject.DOMAIN)),
project.KeystoneProject.ENABLED: project.KeystoneProject.ENABLED:
(self._get_property_schema_value_default( (self._get_property_schema_value_default(
project.KeystoneProject.ENABLED)) project.KeystoneProject.ENABLED)),
project.KeystoneProject.PARENT:
(self._get_property_schema_value_default(
project.KeystoneProject.PARENT))
} }
def _side_effect(key): def _side_effect(key):
@ -270,6 +280,8 @@ class KeystoneProjectTest(common.HeatTestCase):
self.assertEqual( self.assertEqual(
True, True,
self.test_project.properties.get(project.KeystoneProject.ENABLED)) self.test_project.properties.get(project.KeystoneProject.ENABLED))
self.assertIsNone(
self.test_project.properties.get(project.KeystoneProject.PARENT))
self.test_project.handle_create() self.test_project.handle_create()
@ -278,7 +290,8 @@ class KeystoneProjectTest(common.HeatTestCase):
name='foo', name='foo',
description='', description='',
domain='default', domain='default',
enabled=True) enabled=True,
parent=None)
def test_project_handle_update(self): def test_project_handle_update(self):
self.test_project.resource_id = '477e8273-60a7-4c41-b683-fdb0bc7cd151' self.test_project.resource_id = '477e8273-60a7-4c41-b683-fdb0bc7cd151'