From c9910004585bdc8d0d8bd9b1b307bd9df8fa95be Mon Sep 17 00:00:00 2001 From: Steven Hardy Date: Wed, 16 Jul 2014 19:09:38 +0100 Subject: [PATCH] stack user add _user_token Change-Id: I729a6e591e30a93378596eb35722120b4bb364fc --- heat/engine/stack_user.py | 15 ++++++++++ heat/tests/fakes.py | 3 ++ heat/tests/test_stack_user.py | 52 +++++++++++++++++++++++++++++++++-- 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/heat/engine/stack_user.py b/heat/engine/stack_user.py index 1dc933b40f..0cbec3b6c0 100644 --- a/heat/engine/stack_user.py +++ b/heat/engine/stack_user.py @@ -49,6 +49,21 @@ class StackUser(resource.Resource): # Store the ID in resource data, for compatibility with SignalResponder self.data_set('user_id', user_id) + def _user_token(self): + project_id = self.stack.stack_user_project_id + if not project_id: + raise ValueError(_("Can't get user token, user not yet created")) + password = getattr(self, 'password', None) + # FIXME(shardy): the create and getattr here could allow insane + # passwords, e.g a zero length string, if these happen it almost + # certainly means a bug elsewhere in heat, so add assertion to catch + if password is None: + raise ValueError(_("Can't get user token without password")) + + return self.keystone().stack_domain_user_token( + username=self.physical_resource_name(), + project_id=project_id, password=password) + def _get_user_id(self): user_id = self.data().get('user_id') if user_id: diff --git a/heat/tests/fakes.py b/heat/tests/fakes.py index cb83b39a4d..943b952e71 100644 --- a/heat/tests/fakes.py +++ b/heat/tests/fakes.py @@ -164,3 +164,6 @@ class FakeKeystoneClient(object): def delete_stack_domain_user_keypair(self, user_id, project_id, credential_id): pass + + def stack_domain_user_token(self, username, project_id, password): + pass diff --git a/heat/tests/test_stack_user.py b/heat/tests/test_stack_user.py index cc171bb435..243b9f436c 100644 --- a/heat/tests/test_stack_user.py +++ b/heat/tests/test_stack_user.py @@ -12,6 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. +import six + from keystoneclient import exceptions as kc_exceptions from heat.common import exception @@ -48,7 +50,8 @@ class StackUserTest(HeatTestCase): super(StackUserTest, self).tearDown() def _user_create(self, stack_name, project_id, user_id, - resource_name='user', create_project=True): + resource_name='user', create_project=True, + password=None): t = template_format.parse(user_template) stack = utils.parse_stack(t, stack_name=stack_name) rsrc = stack[resource_name] @@ -72,7 +75,7 @@ class StackUserTest(HeatTestCase): 'create_stack_domain_user') expected_username = '%s-%s-%s' % (stack_name, resource_name, 'aabbcc') fakes.FakeKeystoneClient.create_stack_domain_user( - username=expected_username, password=None, + username=expected_username, password=password, project_id=project_id).AndReturn(user_id) return rsrc @@ -350,3 +353,48 @@ class StackUserTest(HeatTestCase): rs_data = db_api.resource_data_get_all(rsrc) self.assertEqual({'user_id': 'auserdel'}, rs_data) self.m.VerifyAll() + + def test_user_token(self): + rsrc = self._user_create(stack_name='user_test123', + project_id='aproject123', + user_id='auser123', + password='apassword') + + short_id.get_id(rsrc.id).AndReturn('aabbcc') + self.m.StubOutWithMock(fakes.FakeKeystoneClient, + 'stack_domain_user_token') + username = 'user_test123-user-aabbcc' + fakes.FakeKeystoneClient.stack_domain_user_token( + username=username, project_id='aproject123', + password='apassword').AndReturn('atoken123') + self.m.ReplayAll() + + rsrc.password = 'apassword' + scheduler.TaskRunner(rsrc.create)() + self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) + self.assertEqual('atoken123', rsrc._user_token()) + self.m.VerifyAll() + + def test_user_token_err_nopassword(self): + rsrc = self._user_create(stack_name='user_test123', + project_id='aproject123', + user_id='auser123') + self.m.ReplayAll() + + scheduler.TaskRunner(rsrc.create)() + self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) + ex = self.assertRaises(ValueError, rsrc._user_token) + expected = "Can't get user token without password" + self.assertEqual(expected, six.text_type(ex)) + self.m.VerifyAll() + + def test_user_token_err_noproject(self): + stack_name = 'user_test123' + resource_name = 'user' + t = template_format.parse(user_template) + stack = utils.parse_stack(t, stack_name=stack_name) + rsrc = stack[resource_name] + + ex = self.assertRaises(ValueError, rsrc._user_token) + expected = "Can't get user token, user not yet created" + self.assertEqual(expected, six.text_type(ex))