From 72a3d64c1872987e0a0f78346345f66b24652b69 Mon Sep 17 00:00:00 2001 From: Daniel Wallace Date: Fri, 15 Jan 2016 16:50:08 -0600 Subject: [PATCH] allow for updating passwords in keystone v2 Perform a users.update_password before throwing away the password from kwargs. Change-Id: Ie478b541a7958a888274eedcd0d2a135a08132c6 --- shade/_tasks.py | 5 +++++ shade/openstackcloud.py | 8 +++++++- shade/tests/functional/test_users.py | 21 +++++++++++++++++++++ shade/tests/unit/test_users.py | 25 +++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 1 deletion(-) diff --git a/shade/_tasks.py b/shade/_tasks.py index dffda0042..6f72bdd2a 100644 --- a/shade/_tasks.py +++ b/shade/_tasks.py @@ -37,6 +37,11 @@ class UserUpdate(task_manager.Task): return client.keystone_client.users.update(**self.args) +class UserPasswordUpdate(task_manager.Task): + def main(self, client): + return client.keystone_client.users.update_password(**self.args) + + class UserGet(task_manager.Task): def main(self, client): return client.keystone_client.users.get(**self.args) diff --git a/shade/openstackcloud.py b/shade/openstackcloud.py index 3804cce87..8f7bea3fd 100644 --- a/shade/openstackcloud.py +++ b/shade/openstackcloud.py @@ -513,9 +513,15 @@ class OpenStackCloud(object): if self.cloud_config.get_api_version('identity') != '3': # Do not pass v3 args to a v2 keystone. kwargs.pop('domain_id', None) - kwargs.pop('password', None) kwargs.pop('description', None) kwargs.pop('default_project', None) + password = kwargs.pop('password', None) + if password is not None: + with _utils.shade_exceptions( + "Error updating password for {user}".format( + user=name_or_id)): + user = self.manager.submitTask(_tasks.UserPasswordUpdate( + user=kwargs['user'], password=password)) elif 'domain_id' in kwargs: # The incoming parameter is domain_id in order to match the # parameter name in create_user(), but UserUpdate() needs it diff --git a/shade/tests/functional/test_users.py b/shade/tests/functional/test_users.py index 2167121c0..72cb38e11 100644 --- a/shade/tests/functional/test_users.py +++ b/shade/tests/functional/test_users.py @@ -108,6 +108,27 @@ class TestUsers(base.TestCase): self.assertEqual('somebody@nowhere.com', new_user['email']) self.assertFalse(new_user['enabled']) + def test_update_user_password(self): + user_name = self.user_prefix + '_password' + user_email = 'nobody@nowhere.com' + user = self._create_user(name=user_name, + email=user_email, + password='old_secret') + self.assertIsNotNone(user) + self.assertTrue(user['enabled']) + + # This should work for both v2 and v3 + new_user = self.cloud.update_user(user['id'], + password='new_secret') + self.assertIsNotNone(new_user) + self.assertEqual(user['id'], new_user['id']) + self.assertEqual(user_name, new_user['name']) + self.assertEqual(user_email, new_user['email']) + self.assertTrue(new_user['enabled']) + self.assertIsNotNone(operator_cloud( + username=user_name, password='new_secret', + auth_url=self.cloud.auth['auth_url']).keystone_client) + def test_users_and_groups(self): if self.cloud.cloud_config.get_api_version('identity') in ('2', '2.0'): self.skipTest('Identity service does not support groups') diff --git a/shade/tests/unit/test_users.py b/shade/tests/unit/test_users.py index 65d3378d6..b75eb8c94 100644 --- a/shade/tests/unit/test_users.py +++ b/shade/tests/unit/test_users.py @@ -67,6 +67,31 @@ class TestUsers(base.TestCase): self.assertEqual(name, user.name) self.assertEqual(email, user.email) + @mock.patch.object(occ.cloud_config.CloudConfig, 'get_api_version') + @mock.patch.object(shade.OpenStackCloud, 'keystone_client') + def test_update_user_password_v2(self, mock_keystone, mock_api_version): + mock_api_version.return_value = '2' + name = 'Mickey Mouse' + email = 'mickey@disney.com' + password = 'mice-rule' + domain_id = '1' + user = {'id': '1', 'name': name, 'email': email} + fake_user = fakes.FakeUser(**user) + munch_fake_user = munch.Munch(user) + mock_keystone.users.list.return_value = [fake_user] + mock_keystone.users.get.return_value = fake_user + mock_keystone.users.update.return_value = fake_user + mock_keystone.users.update_password.return_value = fake_user + user = self.cloud.update_user(name, name=name, email=email, + password=password, + domain_id=domain_id) + mock_keystone.users.update.assert_called_once_with( + user=munch_fake_user, name=name, email=email) + mock_keystone.users.update_password.assert_called_once_with( + user=munch_fake_user, password=password) + self.assertEqual(name, user.name) + self.assertEqual(email, user.email) + @mock.patch.object(occ.cloud_config.CloudConfig, 'get_api_version') @mock.patch.object(shade.OpenStackCloud, 'keystone_client') def test_create_user_v3_no_domain(self, mock_keystone, mock_api_version):