Support property 'domain' for keystone role

Adds property 'domain' for keystone role
resource:
1. the default value of the property is 'default'
2. the property is non-updatalbe

Change-Id: I829921dc35e2754eb6c6ccc293423c755806b0df
Closes-Bug: #1684558
This commit is contained in:
huangtianhua 2017-04-22 10:16:14 +08:00
parent d2cb548fa4
commit 6a18fb0d43
2 changed files with 71 additions and 33 deletions

View File

@ -12,9 +12,11 @@
# under the License. # under the License.
from heat.common.i18n import _ from heat.common.i18n import _
from heat.engine import constraints
from heat.engine import properties from heat.engine import properties
from heat.engine import resource from heat.engine import resource
from heat.engine import support from heat.engine import support
from heat.engine import translation
class KeystoneRole(resource.Resource): class KeystoneRole(resource.Resource):
@ -22,7 +24,8 @@ class KeystoneRole(resource.Resource):
Roles dictate the level of authorization the end user can obtain. Roles can Roles dictate the level of authorization the end user can obtain. Roles can
be granted at either the domain or project level. Role can be assigned to be granted at either the domain or project level. Role can be assigned to
the individual user or at the group level. Role names are globally unique. the individual user or at the group level. Role name is unique within the
owning domain.
""" """
support_status = support.SupportStatus( support_status = support.SupportStatus(
@ -34,9 +37,9 @@ class KeystoneRole(resource.Resource):
entity = 'roles' entity = 'roles'
PROPERTIES = ( PROPERTIES = (
NAME NAME, DOMAIN,
) = ( ) = (
'name' 'name', 'domain',
) )
properties_schema = { properties_schema = {
@ -44,17 +47,36 @@ class KeystoneRole(resource.Resource):
properties.Schema.STRING, properties.Schema.STRING,
_('Name of keystone role.'), _('Name of keystone role.'),
update_allowed=True update_allowed=True
),
DOMAIN: properties.Schema(
properties.Schema.STRING,
_('Name or id of keystone domain.'),
default='default',
constraints=[constraints.CustomConstraint('keystone.domain')],
support_status=support.SupportStatus(version='10.0.0')
) )
} }
def translation_rules(self, properties):
return [
translation.TranslationRule(
properties,
translation.TranslationRule.RESOLVE,
[self.DOMAIN],
client_plugin=self.client_plugin(),
finder='get_domain_id'
)
]
def client(self): def client(self):
return super(KeystoneRole, self).client().client return super(KeystoneRole, self).client().client
def handle_create(self): def handle_create(self):
role_name = (self.properties[self.NAME] or role_name = (self.properties[self.NAME] or
self.physical_resource_name()) self.physical_resource_name())
domain = self.properties[self.DOMAIN]
role = self.client().roles.create(name=role_name) role = self.client().roles.create(name=role_name,
domain=domain)
self.resource_id_set(role.id) self.resource_id_set(role.id)

View File

@ -11,6 +11,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import copy
import mock import mock
from heat.engine import resource from heat.engine import resource
@ -41,14 +42,6 @@ class KeystoneRoleTest(common.HeatTestCase):
super(KeystoneRoleTest, self).setUp() super(KeystoneRoleTest, self).setUp()
self.ctx = utils.dummy_context() self.ctx = utils.dummy_context()
self.stack = stack.Stack(
self.ctx, 'test_stack_keystone',
template.Template(keystone_role_template)
)
self.test_role = self.stack['test_role']
# Mock client # Mock client
self.keystoneclient = mock.Mock() self.keystoneclient = mock.Mock()
self.patchobject(resource.Resource, 'client', self.patchobject(resource.Resource, 'client',
@ -56,53 +49,75 @@ class KeystoneRoleTest(common.HeatTestCase):
client=self.keystoneclient)) client=self.keystoneclient))
self.roles = self.keystoneclient.roles self.roles = self.keystoneclient.roles
def _get_mock_role(self): def _get_rsrc(self, domain='default', without_name=False):
t = template.Template(keystone_role_template)
tmpl = copy.deepcopy(t)
tmpl['resources']['test_role']['Properties']['domain'] = domain
if without_name:
tmpl['resources']['test_role']['Properties'].pop('name')
test_stack = stack.Stack(self.ctx, 'test_keystone_role', tmpl)
test_role = test_stack['test_role']
return test_role
def _get_mock_role(self, domain='default'):
value = mock.MagicMock() value = mock.MagicMock()
role_id = '477e8273-60a7-4c41-b683-fdb0bc7cd151' role_id = '477e8273-60a7-4c41-b683-fdb0bc7cd151'
domain_id = domain
value.id = role_id value.id = role_id
value.domain_id = domain_id
return value return value
def test_role_handle_create(self): def _test_handle_create(self, domain='default'):
mock_role = self._get_mock_role() test_role = self._get_rsrc(domain)
mock_role = self._get_mock_role(domain)
self.roles.create.return_value = mock_role self.roles.create.return_value = mock_role
# validate the properties # validate the properties
self.assertEqual('test_role_1', self.assertEqual('test_role_1',
self.test_role.properties.get(role.KeystoneRole.NAME)) test_role.properties.get(role.KeystoneRole.NAME))
self.assertEqual(domain,
test_role.properties.get(role.KeystoneRole.DOMAIN))
self.test_role.handle_create() test_role.handle_create()
# validate role creation with given name # validate role creation with given name
self.roles.create.assert_called_once_with(name='test_role_1') self.roles.create.assert_called_once_with(name='test_role_1',
domain=domain)
# validate physical resource id # validate physical resource id
self.assertEqual(mock_role.id, self.test_role.resource_id) self.assertEqual(mock_role.id, test_role.resource_id)
def test_role_handle_create(self):
self._test_handle_create()
def test_role_handle_create_with_domain(self):
self._test_handle_create(domain='d_test')
def test_role_handle_create_default_name(self): def test_role_handle_create_default_name(self):
# reset the NAME value to None, to make sure role is # reset the NAME value to None, to make sure role is
# created with physical_resource_name # created with physical_resource_name
self.test_role.properties = mock.MagicMock() test_role = self._get_rsrc(without_name=True)
self.test_role.properties.__getitem__.return_value = None test_role.physical_resource_name = mock.Mock(
return_value='phy_role_name')
self.test_role.handle_create() test_role.handle_create()
# validate role creation with default name # validate role creation with default name
physical_resource_name = self.test_role.physical_resource_name() self.roles.create.assert_called_once_with(name='phy_role_name',
self.roles.create.assert_called_once_with(name=physical_resource_name) domain='default')
def test_role_handle_update(self): def test_role_handle_update(self):
self.test_role.resource_id = '477e8273-60a7-4c41-b683-fdb0bc7cd151' test_role = self._get_rsrc()
test_role.resource_id = '477e8273-60a7-4c41-b683-fdb0bc7cd151'
# update the name property # update the name property
prop_diff = {role.KeystoneRole.NAME: 'test_role_1_updated'} prop_diff = {role.KeystoneRole.NAME: 'test_role_1_updated'}
self.test_role.handle_update(json_snippet=None, test_role.handle_update(json_snippet=None,
tmpl_diff=None, tmpl_diff=None,
prop_diff=prop_diff) prop_diff=prop_diff)
self.roles.update.assert_called_once_with( self.roles.update.assert_called_once_with(
role=self.test_role.resource_id, role=test_role.resource_id,
name=prop_diff[role.KeystoneRole.NAME] name=prop_diff[role.KeystoneRole.NAME]
) )
@ -110,5 +125,6 @@ class KeystoneRoleTest(common.HeatTestCase):
role = mock.Mock() role = mock.Mock()
role.to_dict.return_value = {'attr': 'val'} role.to_dict.return_value = {'attr': 'val'}
self.roles.get.return_value = role self.roles.get.return_value = role
res = self.test_role._show_resource() test_role = self._get_rsrc()
res = test_role._show_resource()
self.assertEqual({'attr': 'val'}, res) self.assertEqual({'attr': 'val'}, res)