Keystone::User observe reality implementation

Add override parse_live_resource_data method implementation for
OS::Keystone::User resource.

Also, add translation rule Resolve for correct handling
domain, groups and default_project properties.

implements bp get-reality-for-resources

Change-Id: I6479dc1fb5672c1f2abd5b4272755b057057f3bf
This commit is contained in:
Peter Razumovsky 2016-04-08 17:46:11 +03:00
parent 21af1d55e5
commit da1af078fe
2 changed files with 85 additions and 27 deletions

View File

@ -17,6 +17,7 @@ from heat.engine import properties
from heat.engine import resource
from heat.engine.resources.openstack.keystone import role_assignments
from heat.engine import support
from heat.engine import translation
class KeystoneUser(resource.Resource,
@ -52,7 +53,7 @@ class KeystoneUser(resource.Resource,
),
DOMAIN: properties.Schema(
properties.Schema.STRING,
_('Name of keystone domain.'),
_('Name or ID of keystone domain.'),
default='default',
update_allowed=True,
constraints=[constraints.CustomConstraint('keystone.domain')]
@ -81,7 +82,7 @@ class KeystoneUser(resource.Resource,
),
DEFAULT_PROJECT: properties.Schema(
properties.Schema.STRING,
_('Default project of keystone user.'),
_('Name or ID of default project of keystone user.'),
update_allowed=True,
constraints=[constraints.CustomConstraint('keystone.project')]
),
@ -100,6 +101,31 @@ class KeystoneUser(resource.Resource,
properties_schema.update(
role_assignments.KeystoneRoleAssignmentMixin.mixin_properties_schema)
def translation_rules(self, properties):
return [
translation.TranslationRule(
properties,
translation.TranslationRule.RESOLVE,
[self.DOMAIN],
client_plugin=self.client_plugin(),
finder='get_domain_id'
),
translation.TranslationRule(
properties,
translation.TranslationRule.RESOLVE,
[self.DEFAULT_PROJECT],
client_plugin=self.client_plugin(),
finder='get_project_id'
),
translation.TranslationRule(
properties,
translation.TranslationRule.RESOLVE,
[self.GROUPS],
client_plugin=self.client_plugin(),
finder='get_group_id'
),
]
def validate(self):
super(KeystoneUser, self).validate()
self.validate_assignment_properties()
@ -138,40 +164,27 @@ class KeystoneUser(resource.Resource,
return
values['user'] = user_id
domain = (self.client_plugin().get_domain_id(domain))
values['domain'] = domain
return self.client().users.update(**values)
def _add_user_to_groups(self, user_id, groups):
if groups is not None:
group_ids = [self.client_plugin().get_group_id(group)
for group in groups]
for group_id in group_ids:
for group_id in groups:
self.client().users.add_to_group(user_id,
group_id)
def _remove_user_from_groups(self, user_id, groups):
if groups is not None:
group_ids = [self.client_plugin().get_group_id(group)
for group in groups]
for group_id in group_ids:
for group_id in groups:
self.client().users.remove_from_group(user_id,
group_id)
def _find_diff(self, updated_prps, stored_prps):
new_group_ids = [self.client_plugin().get_group_id(group)
for group in
(set(updated_prps or []) -
set(stored_prps or []))]
new_group_ids = list(set(updated_prps or []) - set(stored_prps or []))
removed_group_ids = [self.client_plugin().get_group_id(group)
for group in
(set(stored_prps or []) -
set(updated_prps or []))]
removed_group_ids = list(set(stored_prps or []) -
set(updated_prps or []))
return new_group_ids, removed_group_ids
@ -179,13 +192,11 @@ class KeystoneUser(resource.Resource,
user_name = (self.properties[self.NAME] or
self.physical_resource_name())
description = self.properties[self.DESCRIPTION]
domain = self.client_plugin().get_domain_id(
self.properties[self.DOMAIN])
domain = self.properties[self.DOMAIN]
enabled = self.properties[self.ENABLED]
email = self.properties[self.EMAIL]
password = self.properties[self.PASSWORD]
default_project = self.client_plugin().get_project_id(
self.properties[self.DEFAULT_PROJECT])
default_project = self.properties[self.DEFAULT_PROJECT]
groups = self.properties[self.GROUPS]
user = self.client().users.create(
@ -244,15 +255,26 @@ class KeystoneUser(resource.Resource,
self.update_assignment(prop_diff=prop_diff,
user_id=self.resource_id)
def parse_live_resource_data(self, resource_properties, resource_data):
user_reality = {
self.ROLES: self.parse_list_assignments(user_id=self.resource_id),
self.DEFAULT_PROJECT: resource_data.get('default_project_id'),
self.DOMAIN: resource_data.get('domain_id'),
self.GROUPS: [group.id for group in self.client().groups.list(
user=self.resource_id)]
}
props_keys = [self.NAME, self.DESCRIPTION, self.ENABLED, self.EMAIL]
for key in props_keys:
user_reality.update({key: resource_data.get(key)})
return user_reality
def handle_delete(self):
if self.resource_id is not None:
with self.client_plugin().ignore_not_found:
if self.properties[self.GROUPS] is not None:
self._remove_user_from_groups(
self.resource_id,
[self.client_plugin().get_group_id(group)
for group in
self.properties[self.GROUPS]])
self.properties[self.GROUPS])
self.client().users.delete(self.resource_id)

View File

@ -280,3 +280,39 @@ class KeystoneUserTest(common.HeatTestCase):
self.users.get.return_value = user
res = self.test_user._show_resource()
self.assertEqual({'attr': 'val'}, res)
def test_get_live_state(self):
user = mock.MagicMock()
user.to_dict.return_value = {
'description': '',
'enabled': True,
'domain_id': 'default',
'email': 'fake@312.com',
'default_project_id': '859aee961e30408e813853e1cffad089',
'id': '4060e773e26842a88b7490528d78de4f',
'name': 'user1-user-275g3vdmwuo5'}
self.users.get.return_value = user
role = mock.MagicMock()
role.to_dict.return_value = {
'scope': {'domain': {'id': '1234'}}, 'role': {'id': '4321'}
}
self.keystoneclient.role_assignments.list.return_value = [role]
group = mock.MagicMock()
group.id = '39393'
self.keystoneclient.groups.list.return_value = [group]
self.test_user.resource_id = '1111'
reality = self.test_user.get_live_state(self.test_user.properties)
expected = {
'description': '',
'enabled': True,
'domain': 'default',
'email': 'fake@312.com',
'default_project': '859aee961e30408e813853e1cffad089',
'name': 'user1-user-275g3vdmwuo5',
'groups': ['39393'],
'roles': [{'role': '4321', 'domain': '1234', 'project': None}]
}
self.assertEqual(set(expected.keys()), set(reality.keys()))
for key in expected:
self.assertEqual(expected[key], reality[key])