From da1af078fea76271e07f1f20d1eac1dfe0bf9c0f Mon Sep 17 00:00:00 2001 From: Peter Razumovsky Date: Fri, 8 Apr 2016 17:46:11 +0300 Subject: [PATCH] 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 --- .../resources/openstack/keystone/user.py | 76 ++++++++++++------- heat/tests/openstack/keystone/test_user.py | 36 +++++++++ 2 files changed, 85 insertions(+), 27 deletions(-) diff --git a/heat/engine/resources/openstack/keystone/user.py b/heat/engine/resources/openstack/keystone/user.py index 32a72efacd..57c3ae9511 100644 --- a/heat/engine/resources/openstack/keystone/user.py +++ b/heat/engine/resources/openstack/keystone/user.py @@ -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) diff --git a/heat/tests/openstack/keystone/test_user.py b/heat/tests/openstack/keystone/test_user.py index 1f9dfbcc77..9cb8d716e5 100644 --- a/heat/tests/openstack/keystone/test_user.py +++ b/heat/tests/openstack/keystone/test_user.py @@ -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])