From 9d5bdde09bffe0ad2e79903372476dd13649422d Mon Sep 17 00:00:00 2001 From: huangtianhua Date: Thu, 15 Oct 2015 10:07:36 +0800 Subject: [PATCH] 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 --- .../resources/openstack/keystone/project.py | 18 ++++++++++--- heat/tests/openstack/keystone/test_project.py | 27 ++++++++++++++----- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/heat/engine/resources/openstack/keystone/project.py b/heat/engine/resources/openstack/keystone/project.py index 5b628ebfa8..f79d4c6b9e 100644 --- a/heat/engine/resources/openstack/keystone/project.py +++ b/heat/engine/resources/openstack/keystone/project.py @@ -30,9 +30,9 @@ class KeystoneProject(resource.Resource): entity = 'projects' PROPERTIES = ( - NAME, DOMAIN, DESCRIPTION, ENABLED + NAME, DOMAIN, DESCRIPTION, ENABLED, PARENT, ) = ( - 'name', 'domain', 'description', 'enabled' + 'name', 'domain', 'description', 'enabled', 'parent', ) properties_schema = { @@ -59,7 +59,14 @@ class KeystoneProject(resource.Resource): _('This project is enabled or disabled.'), default=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): @@ -72,12 +79,15 @@ class KeystoneProject(resource.Resource): domain = self.client_plugin().get_domain_id( self.properties[self.DOMAIN]) enabled = self.properties[self.ENABLED] + pp = self.properties[self.PARENT] + parent = self.client_plugin().get_project_id(pp) project = self.client().projects.create( name=project_name, domain=domain, description=description, - enabled=enabled) + enabled=enabled, + parent=parent) self.resource_id_set(project.id) diff --git a/heat/tests/openstack/keystone/test_project.py b/heat/tests/openstack/keystone/test_project.py index 7213756b71..93c343e4d3 100644 --- a/heat/tests/openstack/keystone/test_project.py +++ b/heat/tests/openstack/keystone/test_project.py @@ -30,7 +30,8 @@ keystone_project_template = { 'name': 'test_project_1', 'description': 'Test project', 'domain': 'default', - 'enabled': 'True' + 'enabled': 'True', + 'parent': 'my_father' } } } @@ -59,11 +60,12 @@ class KeystoneProjectTest(common.HeatTestCase): self.projects = self.keystoneclient.projects # Mock client plugin - def _domain_side_effect(value): + def _id_side_effect(value): return value 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.return_value = keystone_client_plugin @@ -98,6 +100,9 @@ class KeystoneProjectTest(common.HeatTestCase): self.assertEqual( True, 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() @@ -106,7 +111,8 @@ class KeystoneProjectTest(common.HeatTestCase): name='test_project_1', description='Test project', domain='default', - enabled=True) + enabled=True, + parent='my_father') # validate physical 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.DESCRIPTION: 'description', 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(): @@ -241,7 +248,10 @@ class KeystoneProjectTest(common.HeatTestCase): project.KeystoneProject.DOMAIN)), project.KeystoneProject.ENABLED: (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): @@ -270,6 +280,8 @@ class KeystoneProjectTest(common.HeatTestCase): self.assertEqual( True, self.test_project.properties.get(project.KeystoneProject.ENABLED)) + self.assertIsNone( + self.test_project.properties.get(project.KeystoneProject.PARENT)) self.test_project.handle_create() @@ -278,7 +290,8 @@ class KeystoneProjectTest(common.HeatTestCase): name='foo', description='', domain='default', - enabled=True) + enabled=True, + parent=None) def test_project_handle_update(self): self.test_project.resource_id = '477e8273-60a7-4c41-b683-fdb0bc7cd151'