diff --git a/keystoneclient/base.py b/keystoneclient/base.py index d5d3ee9e4..df0413427 100644 --- a/keystoneclient/base.py +++ b/keystoneclient/base.py @@ -87,8 +87,14 @@ class Manager(object): def _delete(self, url): resp, body = self.api.delete(url) - def _update(self, url, body, response_key=None): - resp, body = self.api.put(url, body=body) + def _update(self, url, body, response_key=None, method="PUT"): + methods = {"PUT": self.api.put, + "POST": self.api.post} + try: + resp, body = methods[method](url, body=body) + except KeyError: + raise exceptions.ClientException("Invalid update method: %s" + % method) # PUT requests may not return a body if body: return self.resource_class(self, body[response_key]) diff --git a/keystoneclient/v2_0/shell.py b/keystoneclient/v2_0/shell.py index 6eed7dd99..ff9804b37 100755 --- a/keystoneclient/v2_0/shell.py +++ b/keystoneclient/v2_0/shell.py @@ -49,11 +49,13 @@ def do_user_create(kc, args): @utils.arg('id', metavar='', nargs='?', - help='User ID to update email.') + help='User ID to update.') +@utils.arg('name', metavar='', nargs='?', + help='New desired user name.') @utils.arg('email', metavar='', nargs='?', help='New desired email address.') -def do_user_update_email(kc, args): - user = kc.users.update_email(args.id, args.email) +def do_user_update(kc, args): + user = kc.users.update(args.id, name=args.name, email=args.email) utils.print_dict(user._info) diff --git a/keystoneclient/v2_0/users.py b/keystoneclient/v2_0/users.py index 809705312..d3b6586ad 100644 --- a/keystoneclient/v2_0/users.py +++ b/keystoneclient/v2_0/users.py @@ -36,15 +36,18 @@ class UserManager(base.ManagerWithFind): def get(self, user): return self._get("/users/%s" % base.getid(user), "user") - def update_email(self, user, email): + def update(self, user, **kwargs): """ - Update email - """ - # FIXME(ja): why do we have to send id in params and url? - params = {"user": {"id": base.getid(user), - "email": email}} + Update user data. - return self._update("/users/%s" % base.getid(user), params, "user") + Supported arguments include ``name`` and ``email``. + """ + # FIXME(gabriel): "tenantId" seems to be accepted by the API but + # fails to actually update the default tenant. + params = {"user": kwargs} + params['user']['id'] = base.getid(user) + url = "/users/%s" % base.getid(user) + return self._update(url, params, "user", method="POST") def update_enabled(self, user, enabled): """ @@ -63,7 +66,7 @@ class UserManager(base.ManagerWithFind): params = {"user": {"id": base.getid(user), "password": password}} - return self._update("/users/%s/password" % base.getid(user), + return self._update("/users/%s/OS-KSADM/password" % base.getid(user), params, "user") def update_tenant(self, user, tenant): @@ -75,7 +78,7 @@ class UserManager(base.ManagerWithFind): # FIXME(ja): seems like a bad url - default tenant is an attribute # not a subresource!??? - return self._update("/users/%s/tenant" % base.getid(user), + return self._update("/users/%s/OS-KSADM/tenant" % base.getid(user), params, "user") def create(self, name, password, email, tenant_id=None, enabled=True): diff --git a/tests/v2_0/test_users.py b/tests/v2_0/test_users.py index 34ae344f1..9669772dc 100644 --- a/tests/v2_0/test_users.py +++ b/tests/v2_0/test_users.py @@ -164,7 +164,9 @@ class UserTests(utils.TestCase): def test_update(self): req_1 = {"user": {"password": "swordfish", "id": 2}} - req_2 = {"user": {"id": 2, "email": "gabriel@example.com"}} + req_2 = {"user": {"id": 2, + "email": "gabriel@example.com", + "name": "gabriel"}} req_3 = {"user": {"tenantId": 1, "id": 2}} req_4 = {"user": {"enabled": False, "id": 2}} # Keystone basically echoes these back... including the password :-/ @@ -173,19 +175,19 @@ class UserTests(utils.TestCase): resp_3 = httplib2.Response({"status": 200, "body": json.dumps(req_3)}) resp_4 = httplib2.Response({"status": 200, "body": json.dumps(req_3)}) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/users/2/password'), - 'PUT', - body=json.dumps(req_1), - headers=self.TEST_POST_HEADERS) \ - .AndReturn((resp_1, resp_1['body'])) httplib2.Http.request(urlparse.urljoin(self.TEST_URL, 'v2.0/users/2'), - 'PUT', + 'POST', body=json.dumps(req_2), headers=self.TEST_POST_HEADERS) \ .AndReturn((resp_2, resp_2['body'])) httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/users/2/tenant'), + 'v2.0/users/2/OS-KSADM/password'), + 'PUT', + body=json.dumps(req_1), + headers=self.TEST_POST_HEADERS) \ + .AndReturn((resp_1, resp_1['body'])) + httplib2.Http.request(urlparse.urljoin(self.TEST_URL, + 'v2.0/users/2/OS-KSADM/tenant'), 'PUT', body=json.dumps(req_3), headers=self.TEST_POST_HEADERS) \ @@ -198,7 +200,9 @@ class UserTests(utils.TestCase): .AndReturn((resp_4, resp_4['body'])) self.mox.ReplayAll() + user = self.client.users.update(2, + name='gabriel', + email='gabriel@example.com') user = self.client.users.update_password(2, 'swordfish') - user = self.client.users.update_email(2, 'gabriel@example.com') user = self.client.users.update_tenant(2, 1) user = self.client.users.update_enabled(2, False)