diff options
-rw-r--r-- | README.rst | 26 | ||||
-rw-r--r-- | keystoneclient/base.py | 2 | ||||
-rw-r--r-- | keystoneclient/client.py | 81 | ||||
-rw-r--r-- | keystoneclient/exceptions.py | 14 | ||||
-rw-r--r-- | keystoneclient/generic/client.py | 12 | ||||
-rw-r--r-- | keystoneclient/shell.py | 32 | ||||
-rw-r--r-- | tests/test_client.py | 16 | ||||
-rw-r--r-- | tests/test_http.py | 45 | ||||
-rw-r--r-- | tests/test_https.py | 38 | ||||
-rw-r--r-- | tests/test_shell.py | 8 | ||||
-rw-r--r-- | tests/utils.py | 37 | ||||
-rw-r--r-- | tests/v2_0/test_auth.py | 133 | ||||
-rw-r--r-- | tests/v2_0/test_discovery.py | 46 | ||||
-rw-r--r-- | tests/v2_0/test_ec2.py | 65 | ||||
-rw-r--r-- | tests/v2_0/test_endpoints.py | 56 | ||||
-rw-r--r-- | tests/v2_0/test_roles.py | 177 | ||||
-rw-r--r-- | tests/v2_0/test_services.py | 75 | ||||
-rw-r--r-- | tests/v2_0/test_tenants.py | 227 | ||||
-rw-r--r-- | tests/v2_0/test_tokens.py | 18 | ||||
-rw-r--r-- | tests/v2_0/test_users.py | 258 | ||||
-rw-r--r-- | tests/v3/test_projects.py | 34 | ||||
-rw-r--r-- | tests/v3/test_roles.py | 124 | ||||
-rw-r--r-- | tests/v3/utils.py | 139 | ||||
-rw-r--r-- | tools/pip-requires | 2 |
24 files changed, 948 insertions, 717 deletions
@@ -75,6 +75,17 @@ OS_REGION_NAME``):: If a region is not specified and multiple regions are returned by the Identity service, the client may not access the same region consistently. +If you need to connect to a server that is TLS-enabled (the auth URL begins +with 'https') and it uses a certificate from a private CA or a self-signed +certificate you will need to specify the path to an appropriate CA certificate +to use to validate the server certificate with ``--os-cacert`` or an +environment variable:: + + export OS_CACERT=/etc/ssl/my-root-cert.pem + +Certificate verification can be turned off using ``--insecure``. This should +be used with caution. + You'll find complete documentation on the shell by running ``keystone help``:: usage: keystone [--os-username <auth-user-name>] @@ -85,8 +96,8 @@ You'll find complete documentation on the shell by running ``keystone help``:: [--os-identity-api-version <identity-api-version>] [--os-token <service-token>] [--os-endpoint <service-endpoint>] - [--os-cacert <ca-certificate>] [--os-cert <certificate>] - [--os-key <key>] [--insecure] + [--os-cacert <ca-certificate>] [--insecure] + [--os-cert <certificate>] [--os-key <key>] [--no-cache] <subcommand> ... Command-line interface to the OpenStack Identity API. @@ -167,13 +178,14 @@ You'll find complete documentation on the shell by running ``keystone help``:: from the service catalog (via authentication). Defaults to env[OS_SERVICE_ENDPOINT] --os-cacert <ca-certificate> - Defaults to env[OS_CACERT] + Specify a CA bundle file to use in verifying a TLS + (https) server certificate. Defaults to env[OS_CACERT] + --insecure Explicitly allow keystoneclient to perform "insecure" + TLS (https) requests. The server's certificate will + not be verified against any certificate authorities. + This option should be used with caution. --os-cert <certificate> Defaults to env[OS_CERT] --os-key <key> Defaults to env[OS_KEY] - --insecure Explicitly allow keystoneclient to perform "insecure" - SSL (https) requests. The server's certificate will - not be verified against any certificate authorities. - This option should be used with caution. See "keystone help COMMAND" for help on a specific command. diff --git a/keystoneclient/base.py b/keystoneclient/base.py index 13a8bf1..fd9e802 100644 --- a/keystoneclient/base.py +++ b/keystoneclient/base.py @@ -82,7 +82,7 @@ class Manager(object): def _head(self, url): resp, body = self.api.head(url) - return resp.status == 204 + return resp.status_code == 204 def _create(self, url, body, response_key, return_raw=False): resp, body = self.api.post(url, body=body) diff --git a/keystoneclient/client.py b/keystoneclient/client.py index b6fd54c..555909d 100644 --- a/keystoneclient/client.py +++ b/keystoneclient/client.py @@ -10,9 +10,10 @@ OpenStack Client interface. Handles the REST calls and responses. import copy import logging +import sys import urlparse -import httplib2 +import requests try: import json @@ -42,22 +43,20 @@ except ImportError: keyring_available = False -class HTTPClient(httplib2.Http): +class HTTPClient(object): USER_AGENT = 'python-keystoneclient' + requests_config = { + 'danger_mode': False, + } + def __init__(self, username=None, tenant_id=None, tenant_name=None, password=None, auth_url=None, region_name=None, timeout=None, endpoint=None, token=None, cacert=None, key=None, cert=None, insecure=False, original_ip=None, debug=False, auth_ref=None, use_keyring=False, force_new_token=False, stale_duration=None): - super(HTTPClient, self).__init__(timeout=timeout, ca_certs=cacert) - if cert: - if key: - self.add_certificate(key=key, cert=cert, domain='') - else: - self.add_certificate(key=cert, cert=cert, domain='') self.version = 'v2.0' # set baseline defaults self.username = None @@ -94,10 +93,16 @@ class HTTPClient(httplib2.Http): self.password = password self.original_ip = original_ip self.region_name = region_name - - # httplib2 overrides - self.force_exception_to_status_code = True - self.disable_ssl_certificate_validation = insecure + if cacert: + self.verify_cert = cacert + else: + self.verify_cert = True + if insecure: + self.verify_cert = False + self.cert = cert + if cert and key: + self.cert = (cert, key,) + self.domain = '' # logging setup self.debug_log = debug @@ -105,6 +110,7 @@ class HTTPClient(httplib2.Http): ch = logging.StreamHandler() _logger.setLevel(logging.DEBUG) _logger.addHandler(ch) + self.requests_config['verbose'] = sys.stderr # keyring setup self.use_keyring = use_keyring and keyring_available @@ -277,13 +283,17 @@ class HTTPClient(httplib2.Http): header = ' -H "%s: %s"' % (element, kwargs['headers'][element]) string_parts.append(header) - _logger.debug("REQ: %s\n" % "".join(string_parts)) + _logger.debug("REQ: %s" % "".join(string_parts)) if 'body' in kwargs: _logger.debug("REQ BODY: %s\n" % (kwargs['body'])) - def http_log_resp(self, resp, body): + def http_log_resp(self, resp): if self.debug_log: - _logger.debug("RESP: %s\nRESP BODY: %s\n", resp, body) + _logger.debug( + "RESP: [%s] %s\nRESP BODY: %s\n", + resp.status_code, + resp.headers, + resp.text) def serialize(self, entity): return json.dumps(entity) @@ -291,7 +301,7 @@ class HTTPClient(httplib2.Http): def request(self, url, method, **kwargs): """ Send an http request with the specified characteristics. - Wrapper around httplib2.Http.request to handle tasks such as + Wrapper around requests.request to handle tasks such as setting headers, JSON encoding/decoding, and error handling. """ # Copy the kwargs so we can reuse the original in case of redirects @@ -303,26 +313,37 @@ class HTTPClient(httplib2.Http): self.original_ip, self.USER_AGENT) if 'body' in kwargs: request_kwargs['headers']['Content-Type'] = 'application/json' - request_kwargs['body'] = self.serialize(kwargs['body']) + request_kwargs['data'] = self.serialize(kwargs['body']) + del request_kwargs['body'] + if self.cert: + request_kwargs['cert'] = self.cert self.http_log_req((url, method,), request_kwargs) - resp, body = super(HTTPClient, self).request(url, - method, - **request_kwargs) - self.http_log_resp(resp, body) - - if resp.status in (400, 401, 403, 404, 408, 409, 413, 500, 501): - _logger.debug("Request returned failure status: %s", resp.status) - raise exceptions.from_response(resp, body) - elif resp.status in (301, 302, 305): + resp = requests.request( + method, + url, + verify=self.verify_cert, + config=self.requests_config, + **request_kwargs) + + self.http_log_resp(resp) + + if resp.status_code in (400, 401, 403, 404, 408, 409, 413, 500, 501): + _logger.debug( + "Request returned failure status: %s", + resp.status_code) + raise exceptions.from_response(resp, resp.text) + elif resp.status_code in (301, 302, 305): # Redirected. Reissue the request to the new location. - return self.request(resp['location'], method, **kwargs) + return self.request(resp.headers['location'], method, **kwargs) - if body: + if resp.text: try: - body = json.loads(body) + body = json.loads(resp.text) except ValueError: - _logger.debug("Could not decode JSON from body: %s" % body) + body = None + _logger.debug("Could not decode JSON from body: %s" + % resp.text) else: _logger.debug("No body was returned.") body = None diff --git a/keystoneclient/exceptions.py b/keystoneclient/exceptions.py index 0317879..213f078 100644 --- a/keystoneclient/exceptions.py +++ b/keystoneclient/exceptions.py @@ -130,15 +130,15 @@ _code_map = dict((c.http_status, c) for c in [BadRequest, def from_response(response, body): """ Return an instance of an ClientException or subclass - based on an httplib2 response. + based on an requests response. Usage:: - resp, body = http.request(...) - if resp.status != 200: - raise exception_from_response(resp, body) + resp = requests.request(...) + if resp.status_code != 200: + raise exception_from_response(resp, resp.text) """ - cls = _code_map.get(response.status, ClientException) + cls = _code_map.get(response.status_code, ClientException) if body: if hasattr(body, 'keys'): error = body[body.keys()[0]] @@ -149,6 +149,6 @@ def from_response(response, body): # probably couldn't communicate with Keystone at all. message = "Unable to communicate with identity service: %s." % body details = None - return cls(code=response.status, message=message, details=details) + return cls(code=response.status_code, message=message, details=details) else: - return cls(code=response.status) + return cls(code=response.status_code) diff --git a/keystoneclient/generic/client.py b/keystoneclient/generic/client.py index 7fe5e0f..4818ddf 100644 --- a/keystoneclient/generic/client.py +++ b/keystoneclient/generic/client.py @@ -84,7 +84,7 @@ class Client(client.HTTPClient): resp, body = httpclient.request(url, "GET", headers={'Accept': 'application/json'}) - if resp.status in (200, 204): # in some cases we get No Content + if resp.status_code in (200, 204): # some cases we get No Content try: results = {} if 'version' in body: @@ -113,10 +113,10 @@ class Client(client.HTTPClient): return results except KeyError: raise exceptions.AuthorizationFailure() - elif resp.status == 305: + elif resp.status_code == 305: return self._check_keystone_versions(resp['location']) else: - raise exceptions.from_response(resp, body) + raise exceptions.from_response(resp, resp.text) except Exception as e: _logger.exception(e) @@ -145,7 +145,7 @@ class Client(client.HTTPClient): resp, body = httpclient.request("%sextensions" % url, "GET", headers={'Accept': 'application/json'}) - if resp.status in (200, 204): # in some cases we get No Content + if resp.status_code in (200, 204): # some cases we get No Content try: results = {} if 'extensions' in body: @@ -171,10 +171,10 @@ class Client(client.HTTPClient): return results except KeyError: raise exceptions.AuthorizationFailure() - elif resp.status == 305: + elif resp.status_code == 305: return self._check_keystone_extensions(resp['location']) else: - raise exceptions.from_response(resp, body) + raise exceptions.from_response(resp, resp.text) except Exception as e: _logger.exception(e) diff --git a/keystoneclient/shell.py b/keystoneclient/shell.py index 11ed63d..e0b241f 100644 --- a/keystoneclient/shell.py +++ b/keystoneclient/shell.py @@ -20,7 +20,6 @@ Command-line interface to the OpenStack Identity API. import argparse import getpass -import httplib2 import os import sys @@ -153,10 +152,21 @@ class OpenStackIdentityShell(object): parser.add_argument('--os-cacert', metavar='<ca-certificate>', default=env('OS_CACERT', default=None), - help='Defaults to env[OS_CACERT]') + help='Specify a CA bundle file to use in ' + 'verifying a TLS (https) server certificate. ' + 'Defaults to env[OS_CACERT]') parser.add_argument('--os_cacert', help=argparse.SUPPRESS) + parser.add_argument('--insecure', + default=False, + action="store_true", + help='Explicitly allow keystoneclient to perform ' + '"insecure" TLS (https) requests. The ' + 'server\'s certificate will not be verified ' + 'against any certificate authorities. This ' + 'option should be used with caution.') + parser.add_argument('--os-cert', metavar='<certificate>', default=env('OS_CERT'), @@ -171,15 +181,6 @@ class OpenStackIdentityShell(object): parser.add_argument('--os_key', help=argparse.SUPPRESS) - parser.add_argument('--insecure', - default=False, - action="store_true", - help='Explicitly allow keystoneclient to perform ' - '"insecure" SSL (https) requests. The ' - 'server\'s certificate will not be verified ' - 'against any certificate authorities. This ' - 'option should be used with caution.') - parser.add_argument('--os-cache', default=env('OS_CACHE', default=False), action='store_true', @@ -297,10 +298,6 @@ class OpenStackIdentityShell(object): # Parse args again and call whatever callback was selected args = subcommand_parser.parse_args(argv) - # Deal with global arguments - if args.debug: - httplib2.debuglevel = 1 - # Short-circuit and deal with help command right away. if args.func == self.do_help: self.do_help(args) @@ -472,8 +469,5 @@ def main(): OpenStackIdentityShell().main(sys.argv[1:]) except Exception as e: - if httplib2.debuglevel == 1: - raise # dump stack. - else: - print >> sys.stderr, e + print >> sys.stderr, e sys.exit(1) diff --git a/tests/test_client.py b/tests/test_client.py index 43d0d8d..90ab346 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,21 +1,25 @@ -import httplib2 +import copy import json import mock +import requests + from keystoneclient.v2_0 import client from tests import client_fixtures from tests import utils -fake_response = httplib2.Response({"status": 200}) -fake_body = json.dumps(client_fixtures.PROJECT_SCOPED_TOKEN) -mock_request = mock.Mock(return_value=(fake_response, fake_body)) +fake_response = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(client_fixtures.PROJECT_SCOPED_TOKEN) +}) +mock_request = mock.Mock(return_value=(fake_response)) class KeystoneclientTest(utils.TestCase): def test_scoped_init(self): - with mock.patch.object(httplib2.Http, "request", mock_request): + with mock.patch.object(requests, "request", mock_request): cl = client.Client(username='exampleuser', password='password', auth_url='http://somewhere/') @@ -23,7 +27,7 @@ class KeystoneclientTest(utils.TestCase): self.assertTrue(cl.auth_ref.scoped) def test_auth_ref_load(self): - with mock.patch.object(httplib2.Http, "request", mock_request): + with mock.patch.object(requests, "request", mock_request): cl = client.Client(username='exampleuser', password='password', auth_url='http://somewhere/') diff --git a/tests/test_http.py b/tests/test_http.py index 652d0c9..d9085ad 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -1,14 +1,17 @@ -import httplib2 import mock +import requests + from keystoneclient import client from keystoneclient import exceptions from tests import utils -fake_response = httplib2.Response({"status": 200}) -fake_body = '{"hi": "there"}' -mock_request = mock.Mock(return_value=(fake_response, fake_body)) +FAKE_RESPONSE = utils.TestResponse({ + "status_code": 200, + "text": '{"hi": "there"}', +}) +MOCK_REQUEST = mock.Mock(return_value=(FAKE_RESPONSE)) def get_client(): @@ -36,39 +39,47 @@ class ClientTest(utils.TestCase): def test_get(self): cl = get_authed_client() - with mock.patch.object(httplib2.Http, "request", mock_request): + with mock.patch.object(requests, "request", MOCK_REQUEST): with mock.patch('time.time', mock.Mock(return_value=1234)): resp, body = cl.get("/hi") headers = {"X-Auth-Token": "token", "User-Agent": cl.USER_AGENT} - mock_request.assert_called_with("http://127.0.0.1:5000/hi", - "GET", headers=headers) + MOCK_REQUEST.assert_called_with( + "GET", + "http://127.0.0.1:5000/hi", + headers=headers, + **self.TEST_REQUEST_BASE) # Automatic JSON parsing self.assertEqual(body, {"hi": "there"}) def test_get_error(self): cl = get_authed_client() - fake_err_response = httplib2.Response({"status": 400}) - fake_err_body = 'Some evil plaintext string' - err_mock_request = mock.Mock(return_value=(fake_err_response, - fake_err_body)) + fake_err_response = utils.TestResponse({ + "status_code": 400, + "text": 'Some evil plaintext string', + }) + err_MOCK_REQUEST = mock.Mock(return_value=(fake_err_response)) - with mock.patch.object(httplib2.Http, "request", err_mock_request): + with mock.patch.object(requests, "request", err_MOCK_REQUEST): self.assertRaises(exceptions.BadRequest, cl.get, '/hi') def test_post(self): cl = get_authed_client() - with mock.patch.object(httplib2.Http, "request", mock_request): + with mock.patch.object(requests, "request", MOCK_REQUEST): cl.post("/hi", body=[1, 2, 3]) headers = { "X-Auth-Token": "token", "Content-Type": "application/json", "User-Agent": cl.USER_AGENT } - mock_request.assert_called_with("http://127.0.0.1:5000/hi", "POST", - headers=headers, body='[1, 2, 3]') + MOCK_REQUEST.assert_called_with( + "POST", + "http://127.0.0.1:5000/hi", + headers=headers, + data='[1, 2, 3]', + **self.TEST_REQUEST_BASE) def test_forwarded_for(self): ORIGINAL_IP = "10.100.100.1" @@ -76,10 +87,10 @@ class ClientTest(utils.TestCase): tenant_id="tenant", auth_url="auth_test", original_ip=ORIGINAL_IP) - with mock.patch.object(httplib2.Http, "request", mock_request): + with mock.patch.object(requests, "request", MOCK_REQUEST): res = cl.request('/', 'GET') - args, kwargs = mock_request.call_args + args, kwargs = MOCK_REQUEST.call_args self.assertIn( ('Forwarded', "for=%s;by=%s" % (ORIGINAL_IP, cl.USER_AGENT)), kwargs['headers'].items()) diff --git a/tests/test_https.py b/tests/test_https.py index a812bca..bef1db4 100644 --- a/tests/test_https.py +++ b/tests/test_https.py @@ -1,13 +1,17 @@ -import httplib2 +import copy import mock +import requests + from keystoneclient import client from tests import utils -FAKE_RESPONSE = httplib2.Response({"status": 200}) -FAKE_BODY = '{"hi": "there"}' -MOCK_REQUEST = mock.Mock(return_value=(FAKE_RESPONSE, FAKE_BODY)) +FAKE_RESPONSE = utils.TestResponse({ + "status_code": 200, + "text": '{"hi": "there"}', +}) +MOCK_REQUEST = mock.Mock(return_value=(FAKE_RESPONSE)) def get_client(): @@ -29,26 +33,38 @@ class ClientTest(utils.TestCase): def test_get(self): cl = get_authed_client() - with mock.patch.object(httplib2.Http, "request", MOCK_REQUEST): + with mock.patch.object(requests, "request", MOCK_REQUEST): with mock.patch('time.time', mock.Mock(return_value=1234)): resp, body = cl.get("/hi") headers = {"X-Auth-Token": "token", "User-Agent": cl.USER_AGENT} - MOCK_REQUEST.assert_called_with("https://127.0.0.1:5000/hi", - "GET", headers=headers) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['cert'] = ('cert.pem', 'key.pem') + kwargs['verify'] = 'ca.pem' + MOCK_REQUEST.assert_called_with( + "GET", + "https://127.0.0.1:5000/hi", + headers=headers, + **kwargs) # Automatic JSON parsing self.assertEqual(body, {"hi": "there"}) def test_post(self): cl = get_authed_client() - with mock.patch.object(httplib2.Http, "request", MOCK_REQUEST): + with mock.patch.object(requests, "request", MOCK_REQUEST): cl.post("/hi", body=[1, 2, 3]) headers = { "X-Auth-Token": "token", "Content-Type": "application/json", "User-Agent": cl.USER_AGENT } - MOCK_REQUEST.assert_called_with("https://127.0.0.1:5000/hi", - "POST", headers=headers, - body='[1, 2, 3]') + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['cert'] = ('cert.pem', 'key.pem') + kwargs['verify'] = 'ca.pem' + MOCK_REQUEST.assert_called_with( + "POST", + "https://127.0.0.1:5000/hi", + headers=headers, + data='[1, 2, 3]', + **kwargs) diff --git a/tests/test_shell.py b/tests/test_shell.py index a9e0b79..0642242 100644 --- a/tests/test_shell.py +++ b/tests/test_shell.py @@ -1,6 +1,7 @@ import os import mock -import httplib2 + +import requests from keystoneclient import shell as openstack_shell from keystoneclient.v2_0 import shell as shell_v2_0 @@ -42,11 +43,6 @@ class ShellTest(utils.TestCase): def test_help_unknown_command(self): self.assertRaises(exceptions.CommandError, shell, 'help foofoo') - def test_debug(self): - httplib2.debuglevel = 0 - shell('--debug help') - assert httplib2.debuglevel == 1 - def test_shell_args(self): do_tenant_mock = mock.MagicMock() with mock.patch('keystoneclient.v2_0.shell.do_user_list', diff --git a/tests/utils.py b/tests/utils.py index 514ad01..d4b44aa 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,7 +1,7 @@ import time -import httplib2 import mox +import requests import unittest2 as unittest from keystoneclient.v2_0 import client @@ -16,6 +16,10 @@ class TestCase(unittest.TestCase): TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v2.0') TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/' TEST_ADMIN_URL = '%s%s' % (TEST_ROOT_ADMIN_URL, 'v2.0') + TEST_REQUEST_BASE = { + 'config': {'danger_mode': False}, + 'verify': True, + } TEST_SERVICE_CATALOG = [{ "endpoints": [{ @@ -69,7 +73,7 @@ class TestCase(unittest.TestCase): self.mox = mox.Mox() self._original_time = time.time time.time = lambda: 1234 - httplib2.Http.request = self.mox.CreateMockAnything() + requests.request = self.mox.CreateMockAnything() self.client = client.Client(username=self.TEST_USER, token=self.TEST_TOKEN, tenant_name=self.TEST_TENANT_NAME, @@ -89,16 +93,43 @@ class UnauthenticatedTestCase(unittest.TestCase): TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v2.0') TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/' TEST_ADMIN_URL = '%s%s' % (TEST_ROOT_ADMIN_URL, 'v2.0') + TEST_REQUEST_BASE = { + 'config': {'danger_mode': False}, + 'verify': True, + } def setUp(self): super(UnauthenticatedTestCase, self).setUp() self.mox = mox.Mox() self._original_time = time.time time.time = lambda: 1234 - httplib2.Http.request = self.mox.CreateMockAnything() + requests.request = self.mox.CreateMockAnything() def tearDown(self): time.time = self._original_time super(UnauthenticatedTestCase, self).tearDown() self.mox.UnsetStubs() self.mox.VerifyAll() + + +class TestResponse(requests.Response): + """ Class used to wrap requests.Response and provide some + convenience to initialize with a dict """ + + def __init__(self, data): + self._text = None + super(TestResponse, self) + if isinstance(data, dict): + self.status_code = data.get('status_code', None) + self.headers = data.get('headers', None) + # Fake the text attribute to streamline Response creation + self._text = data.get('text', None) + else: + self.status_code = data + + def __eq__(self, other): + return self.__dict__ == other.__dict__ + + @property + def text(self): + return self._text diff --git a/tests/v2_0/test_auth.py b/tests/v2_0/test_auth.py index 37184ba..cd9caa5 100644 --- a/tests/v2_0/test_auth.py +++ b/tests/v2_0/test_auth.py @@ -1,23 +1,13 @@ -import httplib2 +import copy import json +import requests + from keystoneclient.v2_0 import client from keystoneclient import exceptions from tests import utils -def to_http_response(resp_dict): - """ - Utility function to convert a python dictionary - (e.g. {'status':status, 'body': body, 'headers':headers} - to an httplib2 response. - """ - resp = httplib2.Response(resp_dict) - for k, v in resp_dict['headers'].items(): - resp[k] = v - return resp - - class AuthenticateAgainstKeystoneTests(utils.TestCase): def setUp(self): super(AuthenticateAgainstKeystoneTests, self).setUp() @@ -55,9 +45,9 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase): _cred = 'passwordCredentials' _pass = 'password' self.TEST_REQUEST_BODY[_auth][_cred][_pass] = 'bad_key' - resp = httplib2.Response({ - "status": 401, - "body": json.dumps({ + resp = utils.TestResponse({ + "status_code": 401, + "text": json.dumps({ "unauthorized": { "message": "Unauthorized", "code": "401", @@ -65,11 +55,12 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase): }), }) - httplib2.Http.request(self.TEST_URL + "/tokens", - 'POST', - body=json.dumps(self.TEST_REQUEST_BODY), - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + kwargs['data'] = json.dumps(self.TEST_REQUEST_BODY) + requests.request('POST', + self.TEST_URL + "/tokens", + **kwargs).AndReturn((resp)) self.mox.ReplayAll() # Workaround for issue with assertRaises on python2.6 @@ -90,28 +81,30 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase): "headers": { 'location': self.TEST_ADMIN_URL + "/tokens", }, - "status": 305, - "body": "Use proxy", + "status_code": 305, + "text": "Use proxy", }, { "headers": {}, - "status": 200, - "body": correct_response, + "status_code": 200, + "text": correct_response, }, ] - responses = [(to_http_response(resp), resp['body']) + responses = [(utils.TestResponse(resp)) for resp in dict_responses] - httplib2.Http.request(self.TEST_URL + "/tokens", - 'POST', - body=json.dumps(self.TEST_REQUEST_BODY), - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn(responses[0]) - httplib2.Http.request(self.TEST_ADMIN_URL + "/tokens", - 'POST', - body=json.dumps(self.TEST_REQUEST_BODY), - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn(responses[1]) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + kwargs['data'] = json.dumps(self.TEST_REQUEST_BODY) + requests.request('POST', + self.TEST_URL + "/tokens", + **kwargs).AndReturn(responses[0]) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + kwargs['data'] = json.dumps(self.TEST_REQUEST_BODY) + requests.request('POST', + self.TEST_ADMIN_URL + "/tokens", + **kwargs).AndReturn(responses[1]) self.mox.ReplayAll() cs = client.Client(username=self.TEST_USER, @@ -126,16 +119,17 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase): self.TEST_RESPONSE_DICT["access"]["token"]["id"]) def test_authenticate_success_password_scoped(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_RESPONSE_DICT), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_RESPONSE_DICT), }) - httplib2.Http.request(self.TEST_URL + "/tokens", - 'POST', - body=json.dumps(self.TEST_REQUEST_BODY), - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + kwargs['data'] = json.dumps(self.TEST_REQUEST_BODY) + requests.request('POST', + self.TEST_URL + "/tokens", + **kwargs).AndReturn((resp)) self.mox.ReplayAll() cs = client.Client(username=self.TEST_USER, @@ -151,16 +145,17 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase): def test_authenticate_success_password_unscoped(self): del self.TEST_RESPONSE_DICT['access']['serviceCatalog'] del self.TEST_REQUEST_BODY['auth']['tenantId'] - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_RESPONSE_DICT), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_RESPONSE_DICT), }) - httplib2.Http.request(self.TEST_URL + "/tokens", - 'POST', - body=json.dumps(self.TEST_REQUEST_BODY), - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + kwargs['data'] = json.dumps(self.TEST_REQUEST_BODY) + requests.request('POST', + self.TEST_URL + "/tokens", + **kwargs).AndReturn((resp)) self.mox.ReplayAll() cs = client.Client(username=self.TEST_USER, @@ -174,16 +169,17 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase): del self.TEST_REQUEST_BODY['auth']['passwordCredentials'] self.TEST_REQUEST_BODY['auth']['token'] = {'id': self.TEST_TOKEN} self.TEST_REQUEST_HEADERS['X-Auth-Token'] = self.TEST_TOKEN - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_RESPONSE_DICT), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_RESPONSE_DICT), }) - httplib2.Http.request(self.TEST_URL + "/tokens", - 'POST', - body=json.dumps(self.TEST_REQUEST_BODY), - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + kwargs['data'] = json.dumps(self.TEST_REQUEST_BODY) + requests.request('POST', + self.TEST_URL + "/tokens", + **kwargs).AndReturn((resp)) self.mox.ReplayAll() cs = client.Client(token=self.TEST_TOKEN, @@ -201,16 +197,17 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase): del self.TEST_RESPONSE_DICT['access']['serviceCatalog'] self.TEST_REQUEST_BODY['auth']['token'] = {'id': self.TEST_TOKEN} self.TEST_REQUEST_HEADERS['X-Auth-Token'] = self.TEST_TOKEN - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_RESPONSE_DICT), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_RESPONSE_DICT), }) - httplib2.Http.request(self.TEST_URL + "/tokens", - 'POST', - body=json.dumps(self.TEST_REQUEST_BODY), - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + kwargs['data'] = json.dumps(self.TEST_REQUEST_BODY) + requests.request('POST', + self.TEST_URL + "/tokens", + **kwargs).AndReturn((resp)) self.mox.ReplayAll() cs = client.Client(token=self.TEST_TOKEN, diff --git a/tests/v2_0/test_discovery.py b/tests/v2_0/test_discovery.py index e3804c2..06f2107 100644 --- a/tests/v2_0/test_discovery.py +++ b/tests/v2_0/test_discovery.py @@ -1,22 +1,11 @@ -import httplib2 +import copy import json +import requests from keystoneclient.generic import client from tests import utils -def to_http_response(resp_dict): - """ - Utility function to convert a python dictionary - (e.g. {'status':status, 'body': body, 'headers':headers} - to an httplib2 response. - """ - resp = httplib2.Response(resp_dict) - for k, v in resp_dict['headers'].items(): - resp[k] = v - return resp - - class DiscoverKeystoneTests(utils.UnauthenticatedTestCase): def setUp(self): super(DiscoverKeystoneTests, self).setUp() @@ -58,15 +47,16 @@ class DiscoverKeystoneTests(utils.UnauthenticatedTestCase): } def test_get_versions(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_RESPONSE_DICT), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_RESPONSE_DICT), }) - httplib2.Http.request(self.TEST_ROOT_URL, - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('GET', + self.TEST_ROOT_URL, + **kwargs).AndReturn((resp)) self.mox.ReplayAll() cs = client.Client() @@ -80,15 +70,15 @@ class DiscoverKeystoneTests(utils.UnauthenticatedTestCase): ['href']) def test_get_version_local(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_RESPONSE_DICT), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_RESPONSE_DICT), }) - - httplib2.Http.request("http://localhost:35357", - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('GET', + "http://localhost:35357", + **kwargs).AndReturn((resp)) self.mox.ReplayAll() cs = client.Client() diff --git a/tests/v2_0/test_ec2.py b/tests/v2_0/test_ec2.py index 96378e6..a3ac91a 100644 --- a/tests/v2_0/test_ec2.py +++ b/tests/v2_0/test_ec2.py @@ -1,7 +1,8 @@ +import copy import urlparse import json -import httplib2 +import requests from keystoneclient.v2_0 import ec2 from tests import utils @@ -35,18 +36,19 @@ class EC2Tests(utils.TestCase): "enabled": True, } } - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(resp_body), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(resp_body), }) url = urlparse.urljoin(self.TEST_URL, 'v2.0/users/%s/credentials/OS-EC2' % user_id) - httplib2.Http.request(url, - 'POST', - body=json.dumps(req_body), - headers=self.TEST_POST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_POST_HEADERS + kwargs['data'] = json.dumps(req_body) + requests.request('POST', + url, + **kwargs).AndReturn((resp)) self.mox.ReplayAll() cred = self.client.ec2.create(user_id, tenant_id) @@ -68,18 +70,19 @@ class EC2Tests(utils.TestCase): "enabled": True, } } - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(resp_body), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(resp_body), }) url = urlparse.urljoin(self.TEST_URL, 'v2.0/users/%s/credentials/OS-EC2/%s' % (user_id, 'access')) - httplib2.Http.request(url, - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('GET', + url, + **kwargs).AndReturn((resp)) self.mox.ReplayAll() cred = self.client.ec2.get(user_id, 'access') @@ -113,17 +116,18 @@ class EC2Tests(utils.TestCase): } } - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(resp_body), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(resp_body), }) url = urlparse.urljoin(self.TEST_URL, 'v2.0/users/%s/credentials/OS-EC2' % user_id) - httplib2.Http.request(url, - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('GET', + url, + **kwargs).AndReturn((resp)) self.mox.ReplayAll() creds = self.client.ec2.list(user_id) @@ -138,18 +142,19 @@ class EC2Tests(utils.TestCase): def test_delete(self): user_id = 'usr' access = 'access' - resp = httplib2.Response({ - "status": 204, - "body": "", + resp = utils.TestResponse({ + "status_code": 204, + "text": "", }) url = urlparse.urljoin(self.TEST_URL, 'v2.0/users/%s/credentials/OS-EC2/%s' % (user_id, access)) - httplib2.Http.request(url, - 'DELETE', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('DELETE', + url, + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.client.ec2.delete(user_id, access) diff --git a/tests/v2_0/test_endpoints.py b/tests/v2_0/test_endpoints.py index 34406ed..59fc063 100644 --- a/tests/v2_0/test_endpoints.py +++ b/tests/v2_0/test_endpoints.py @@ -1,7 +1,8 @@ +import copy import urlparse import json -import httplib2 +import requests from keystoneclient.v2_0 import endpoints from tests import utils @@ -59,17 +60,18 @@ class EndpointTests(utils.TestCase): } } - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(resp_body), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(resp_body), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/endpoints'), - 'POST', - body=json.dumps(req_body), - headers=self.TEST_POST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_POST_HEADERS + kwargs['data'] = json.dumps(req_body) + requests.request('POST', + urlparse.urljoin(self.TEST_URL, + 'v2.0/endpoints'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() endpoint = self.client.endpoints.create( @@ -82,30 +84,32 @@ class EndpointTests(utils.TestCase): self.assertTrue(isinstance(endpoint, endpoints.Endpoint)) def test_delete(self): - resp = httplib2.Response({ - "status": 204, - "body": "", + resp = utils.TestResponse({ + "status_code": 204, + "text": "", }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/endpoints/8f953'), - 'DELETE', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('DELETE', + urlparse.urljoin(self.TEST_URL, + 'v2.0/endpoints/8f953'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.client.endpoints.delete('8f953') def test_list(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_ENDPOINTS), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_ENDPOINTS), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/endpoints'), - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('GET', + urlparse.urljoin(self.TEST_URL, + 'v2.0/endpoints'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() endpoint_list = self.client.endpoints.list() diff --git a/tests/v2_0/test_roles.py b/tests/v2_0/test_roles.py index 6b46af4..f5b4ee4 100644 --- a/tests/v2_0/test_roles.py +++ b/tests/v2_0/test_roles.py @@ -1,7 +1,8 @@ +import copy import urlparse import json -import httplib2 +import requests from keystoneclient.v2_0 import roles from tests import utils @@ -46,17 +47,18 @@ class RoleTests(utils.TestCase): "id": 3, } } - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(resp_body), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(resp_body), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/OS-KSADM/roles'), - 'POST', - body=json.dumps(req_body), - headers=self.TEST_POST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_POST_HEADERS + kwargs['data'] = json.dumps(req_body) + requests.request('POST', + urlparse.urljoin(self.TEST_URL, + 'v2.0/OS-KSADM/roles'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() role = self.client.roles.create(req_body['role']['name']) @@ -65,31 +67,35 @@ class RoleTests(utils.TestCase): self.assertEqual(role.name, req_body['role']['name']) def test_delete(self): - resp = httplib2.Response({ - "status": 204, - "body": "", + resp = utils.TestResponse({ + "status_code": 204, + "text": "", }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/OS-KSADM/roles/1'), - 'DELETE', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('DELETE', + urlparse.urljoin(self.TEST_URL, + 'v2.0/OS-KSADM/roles/1'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.client.roles.delete(1) def test_get(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps({ + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps({ 'role': self.TEST_ROLES['roles']['values'][0], }), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/OS-KSADM/roles/1'), - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('GET', + urlparse.urljoin(self.TEST_URL, + 'v2.0/OS-KSADM/roles/1'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() role = self.client.roles.get(1) @@ -98,109 +104,116 @@ class RoleTests(utils.TestCase): self.assertEqual(role.name, 'admin') def test_list(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_ROLES), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_ROLES), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/OS-KSADM/roles'), - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('GET', + urlparse.urljoin(self.TEST_URL, + 'v2.0/OS-KSADM/roles'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() role_list = self.client.roles.list() [self.assertTrue(isinstance(r, roles.Role)) for r in role_list] def test_roles_for_user(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_ROLES), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_ROLES), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/users/foo/roles'), - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('GET', + urlparse.urljoin(self.TEST_URL, + 'v2.0/users/foo/roles'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() role_list = self.client.roles.roles_for_user('foo') [self.assertTrue(isinstance(r, roles.Role)) for r in role_list] def test_roles_for_user_tenant(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_ROLES), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_ROLES), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/tenants/barrr/users/foo/roles'), - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('GET', + urlparse.urljoin(self.TEST_URL, + 'v2.0/tenants/barrr/users/foo/roles'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() role_list = self.client.roles.roles_for_user('foo', 'barrr') [self.assertTrue(isinstance(r, roles.Role)) for r in role_list] def test_add_user_role(self): - resp = httplib2.Response({ - "status": 204, - "body": '', + resp = utils.TestResponse({ + "status_code": 204, + "text": '', }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/users/foo/roles/OS-KSADM/barrr'), - 'PUT', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('PUT', + urlparse.urljoin(self.TEST_URL, + 'v2.0/users/foo/roles/OS-KSADM/barrr'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.client.roles.add_user_role('foo', 'barrr') def test_add_user_role_tenant(self): - resp = httplib2.Response({ - "status": 204, - "body": '', + resp = utils.TestResponse({ + "status_code": 204, + "text": '', }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/tenants/4/users/foo/roles/OS-KSADM/barrr'), - 'PUT', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('PUT', + urlparse.urljoin(self.TEST_URL, + 'v2.0/tenants/4/users/foo/roles/OS-KSADM/barrr'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.client.roles.add_user_role('foo', 'barrr', '4') def test_remove_user_role(self): - resp = httplib2.Response({ - "status": 204, - "body": '', + resp = utils.TestResponse({ + "status_code": 204, + "text": '', }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/users/foo/roles/OS-KSADM/barrr'), - 'DELETE', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('DELETE', + urlparse.urljoin(self.TEST_URL, + 'v2.0/users/foo/roles/OS-KSADM/barrr'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.client.roles.remove_user_role('foo', 'barrr') def test_remove_user_role_tenant(self): - resp = httplib2.Response({ - "status": 204, - "body": '', + resp = utils.TestResponse({ + "status_code": 204, + "text": '', }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/tenants/4/users/foo/roles/OS-KSADM/barrr'), - 'DELETE', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('DELETE', + urlparse.urljoin(self.TEST_URL, + 'v2.0/tenants/4/users/foo/roles/OS-KSADM/barrr'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.client.roles.remove_user_role('foo', 'barrr', '4') diff --git a/tests/v2_0/test_services.py b/tests/v2_0/test_services.py index 12de671..8be109a 100644 --- a/tests/v2_0/test_services.py +++ b/tests/v2_0/test_services.py @@ -1,7 +1,8 @@ +import copy import urlparse import json -import httplib2 +import requests from keystoneclient.v2_0 import services from tests import utils @@ -54,17 +55,18 @@ class ServiceTests(utils.TestCase): "id": 3, } } - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(resp_body), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(resp_body), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/OS-KSADM/services'), - 'POST', - body=json.dumps(req_body), - headers=self.TEST_POST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_POST_HEADERS + kwargs['data'] = json.dumps(req_body) + requests.request('POST', + urlparse.urljoin(self.TEST_URL, + 'v2.0/OS-KSADM/services'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() service = self.client.services.create( @@ -76,30 +78,34 @@ class ServiceTests(utils.TestCase): self.assertEqual(service.name, req_body['OS-KSADM:service']['name']) def test_delete(self): - resp = httplib2.Response({ - "status": 200, - "body": "", + resp = utils.TestResponse({ + "status_code": 200, + "text": "", }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/OS-KSADM/services/1'), - 'DELETE', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('DELETE', + urlparse.urljoin(self.TEST_URL, + 'v2.0/OS-KSADM/services/1'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.client.services.delete(1) def test_get(self): test_services = self.TEST_SERVICES['OS-KSADM:services']['values'][0] - resp = httplib2.Response({ - "status": 200, - "body": json.dumps({'OS-KSADM:service': test_services}), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps({'OS-KSADM:service': test_services}), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/OS-KSADM/services/1'), - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('GET', + urlparse.urljoin(self.TEST_URL, + 'v2.0/OS-KSADM/services/1'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() service = self.client.services.get(1) @@ -109,16 +115,17 @@ class ServiceTests(utils.TestCase): self.assertEqual(service.type, 'compute') def test_list(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_SERVICES), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_SERVICES), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/OS-KSADM/services'), - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('GET', + urlparse.urljoin(self.TEST_URL, + 'v2.0/OS-KSADM/services'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() service_list = self.client.services.list() diff --git a/tests/v2_0/test_tenants.py b/tests/v2_0/test_tenants.py index 48c67a0..246a65f 100644 --- a/tests/v2_0/test_tenants.py +++ b/tests/v2_0/test_tenants.py @@ -1,7 +1,8 @@ +import copy import urlparse import json -import httplib2 +import requests from keystoneclient.v2_0 import tenants from tests import utils @@ -61,16 +62,17 @@ class TenantTests(utils.TestCase): "description": "Like tenant 9, but better.", } } - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(resp_body), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(resp_body), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, 'v2.0/tenants'), - 'POST', - body=json.dumps(req_body), - headers=self.TEST_POST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_POST_HEADERS + kwargs['data'] = json.dumps(req_body) + requests.request('POST', + urlparse.urljoin(self.TEST_URL, 'v2.0/tenants'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() tenant = self.client.tenants.create(req_body['tenant']['name'], @@ -82,31 +84,33 @@ class TenantTests(utils.TestCase): self.assertEqual(tenant.description, "Like tenant 9, but better.") def test_delete(self): - resp = httplib2.Response({ - "status": 204, - "body": "", + resp = utils.TestResponse({ + "status_code": 204, + "text": "", }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/tenants/1'), - 'DELETE', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('DELETE', + urlparse.urljoin(self.TEST_URL, 'v2.0/tenants/1'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.client.tenants.delete(1) def test_get(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps({ + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps({ 'tenant': self.TEST_TENANTS['tenants']['values'][2], }), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/tenants/1'), - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('GET', + urlparse.urljoin(self.TEST_URL, 'v2.0/tenants/1'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() t = self.client.tenants.get(1) @@ -115,64 +119,67 @@ class TenantTests(utils.TestCase): self.assertEqual(t.name, 'admin') def test_list(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_TENANTS), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_TENANTS), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/tenants'), - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('GET', + urlparse.urljoin(self.TEST_URL, 'v2.0/tenants'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() tenant_list = self.client.tenants.list() [self.assertTrue(isinstance(t, tenants.Tenant)) for t in tenant_list] def test_list_limit(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_TENANTS), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_TENANTS), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/tenants?limit=1'), - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('GET', + urlparse.urljoin(self.TEST_URL, + 'v2.0/tenants?limit=1'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() tenant_list = self.client.tenants.list(limit=1) [self.assertTrue(isinstance(t, tenants.Tenant)) for t in tenant_list] def test_list_marker(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_TENANTS), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_TENANTS), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/tenants?marker=1'), - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('GET', + urlparse.urljoin(self.TEST_URL, + 'v2.0/tenants?marker=1'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() tenant_list = self.client.tenants.list(marker=1) [self.assertTrue(isinstance(t, tenants.Tenant)) for t in tenant_list] def test_list_limit_marker(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_TENANTS), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_TENANTS), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/tenants?marker=1&limit=1'), - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('GET', + urlparse.urljoin(self.TEST_URL, + 'v2.0/tenants?marker=1&limit=1'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() tenant_list = self.client.tenants.list(limit=1, marker=1) @@ -195,17 +202,18 @@ class TenantTests(utils.TestCase): "description": "I changed you!", }, } - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(resp_body), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(resp_body), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/tenants/4'), - 'POST', - body=json.dumps(req_body), - headers=self.TEST_POST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_POST_HEADERS + kwargs['data'] = json.dumps(req_body) + requests.request('POST', + urlparse.urljoin(self.TEST_URL, + 'v2.0/tenants/4'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() tenant = self.client.tenants.update(req_body['tenant']['id'], @@ -235,17 +243,18 @@ class TenantTests(utils.TestCase): "description": "", }, } - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(resp_body), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(resp_body), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/tenants/4'), - 'POST', - body=json.dumps(req_body), - headers=self.TEST_POST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_POST_HEADERS + kwargs['data'] = json.dumps(req_body) + requests.request('POST', + urlparse.urljoin(self.TEST_URL, + 'v2.0/tenants/4'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() tenant = self.client.tenants.update(req_body['tenant']['id'], @@ -259,31 +268,33 @@ class TenantTests(utils.TestCase): self.assertFalse(tenant.enabled) def test_add_user(self): - resp = httplib2.Response({ - "status": 204, - "body": '', + resp = utils.TestResponse({ + "status_code": 204, + "text": '', }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/tenants/4/users/foo/roles/OS-KSADM/barrr'), - 'PUT', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('PUT', + urlparse.urljoin(self.TEST_URL, + 'v2.0/tenants/4/users/foo/roles/OS-KSADM/barrr'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.client.tenants.add_user('4', 'foo', 'barrr') def test_remove_user(self): - resp = httplib2.Response({ - "status": 204, - "body": '', + resp = utils.TestResponse({ + "status_code": 204, + "text": '', }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/tenants/4/users/foo/roles/OS-KSADM/barrr'), - 'DELETE', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('DELETE', + urlparse.urljoin(self.TEST_URL, + 'v2.0/tenants/4/users/foo/roles/OS-KSADM/barrr'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.client.tenants.remove_user('4', 'foo', 'barrr') @@ -297,16 +308,17 @@ class TenantTests(utils.TestCase): "enabled": False, }, } - resp = httplib2.Response({ - "status": 204, - "body": '', + resp = utils.TestResponse({ + "status_code": 204, + "text": '', }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/tenants/4/users/foo/roles/OS-KSADM/barrr'), - 'PUT', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('PUT', + urlparse.urljoin(self.TEST_URL, + 'v2.0/tenants/4/users/foo/roles/OS-KSADM/barrr'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() # make tenant object with manager @@ -324,16 +336,17 @@ class TenantTests(utils.TestCase): "enabled": False, }, } - resp = httplib2.Response({ - "status": 204, - "body": '', + resp = utils.TestResponse({ + "status_code": 204, + "text": '', }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/tenants/4/users/foo/roles/OS-KSADM/barrr'), - 'DELETE', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request('DELETE', + urlparse.urljoin(self.TEST_URL, + 'v2.0/tenants/4/users/foo/roles/OS-KSADM/barrr'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() # make tenant object with manager diff --git a/tests/v2_0/test_tokens.py b/tests/v2_0/test_tokens.py index 7b55fc0..9863b8d 100644 --- a/tests/v2_0/test_tokens.py +++ b/tests/v2_0/test_tokens.py @@ -1,6 +1,7 @@ +import copy import urlparse -import httplib2 +import requests from tests import utils @@ -17,15 +18,16 @@ class TokenTests(utils.TestCase): 'User-Agent': 'python-keystoneclient'} def test_delete(self): - resp = httplib2.Response({ - "status": 204, - "body": ""}) + resp = utils.TestResponse({ + "status_code": 204, + "text": ""}) - req = httplib2.Http.request( - urlparse.urljoin(self.TEST_URL, 'v2.0/tokens/1'), + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request( 'DELETE', - headers=self.TEST_REQUEST_HEADERS) - req.AndReturn((resp, resp['body'])) + urlparse.urljoin(self.TEST_URL, 'v2.0/tokens/1'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() diff --git a/tests/v2_0/test_users.py b/tests/v2_0/test_users.py index 5dca0be..154cea5 100644 --- a/tests/v2_0/test_users.py +++ b/tests/v2_0/test_users.py @@ -1,7 +1,8 @@ +import copy import urlparse import json -import httplib2 +import requests from keystoneclient.v2_0 import users from tests import utils @@ -58,16 +59,18 @@ class UserTests(utils.TestCase): "email": "test@example.com", } } - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(resp_body), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(resp_body), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, 'v2.0/users'), - 'POST', - body=json.dumps(req_body), - headers=self.TEST_POST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_POST_HEADERS + kwargs['data'] = json.dumps(req_body) + requests.request( + 'POST', + urlparse.urljoin(self.TEST_URL, 'v2.0/users'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() user = self.client.users.create(req_body['user']['name'], @@ -81,30 +84,35 @@ class UserTests(utils.TestCase): self.assertEqual(user.email, "test@example.com") def test_delete(self): - resp = httplib2.Response({ - "status": 204, - "body": "", + resp = utils.TestResponse({ + "status_code": 204, + "text": "", }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, 'v2.0/users/1'), - 'DELETE', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request( + 'DELETE', + urlparse.urljoin(self.TEST_URL, 'v2.0/users/1'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.client.users.delete(1) def test_get(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps({ + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps({ 'user': self.TEST_USERS['users']['values'][0], }) }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/users/1'), - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request( + 'GET', + urlparse.urljoin(self.TEST_URL, 'v2.0/users/1'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() u = self.client.users.get(1) @@ -113,105 +121,146 @@ class UserTests(utils.TestCase): self.assertEqual(u.name, 'admin') def test_list(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_USERS), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_USERS), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/users'), - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request( + 'GET', + urlparse.urljoin(self.TEST_URL, 'v2.0/users'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() user_list = self.client.users.list() [self.assertTrue(isinstance(u, users.User)) for u in user_list] def test_list_limit(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_USERS), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_USERS), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/users?limit=1'), - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request( + 'GET', + urlparse.urljoin(self.TEST_URL, 'v2.0/users?limit=1'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() user_list = self.client.users.list(limit=1) [self.assertTrue(isinstance(u, users.User)) for u in user_list] def test_list_marker(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_USERS), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_USERS), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/users?marker=1'), - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request( + 'GET', + urlparse.urljoin(self.TEST_URL, 'v2.0/users?marker=1'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() user_list = self.client.users.list(marker=1) [self.assertTrue(isinstance(u, users.User)) for u in user_list] def test_list_limit_marker(self): - resp = httplib2.Response({ - "status": 200, - "body": json.dumps(self.TEST_USERS), + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(self.TEST_USERS), }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/users?marker=1&limit=1'), - 'GET', - headers=self.TEST_REQUEST_HEADERS) \ - .AndReturn((resp, resp['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_REQUEST_HEADERS + requests.request( + 'GET', + urlparse.urljoin(self.TEST_URL, 'v2.0/users?marker=1&limit=1'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() user_list = self.client.users.list(limit=1, marker=1) [self.assertTrue(isinstance(u, users.User)) for u in user_list] def test_update(self): - req_1 = {"user": {"password": "swordfish", "id": 2}} - 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}} + req_1 = { + "user": { + "id": 2, + "email": "gabriel@example.com", + "name": "gabriel", + } + } + req_2 = { + "user": { + "id": 2, + "password": "swordfish", + } + } + req_3 = { + "user": { + "id": 2, + "tenantId": 1, + } + } + req_4 = { + "user": { + "id": 2, + "enabled": False, + } + } + # Keystone basically echoes these back... including the password :-/ - resp_1 = httplib2.Response({"status": 200, "body": json.dumps(req_1)}) - resp_2 = httplib2.Response({"status": 200, "body": json.dumps(req_2)}) - 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'), - 'PUT', - 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/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) \ - .AndReturn((resp_3, resp_3['body'])) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/users/2/OS-KSADM/enabled'), - 'PUT', - body=json.dumps(req_4), - headers=self.TEST_POST_HEADERS) \ - .AndReturn((resp_4, resp_4['body'])) + resp_1 = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(req_1) + }) + resp_2 = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(req_2) + }) + resp_3 = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(req_3) + }) + resp_4 = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(req_4) + }) + + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_POST_HEADERS + kwargs['data'] = json.dumps(req_1) + requests.request( + 'PUT', + urlparse.urljoin(self.TEST_URL, 'v2.0/users/2'), + **kwargs).AndReturn((resp_1)) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_POST_HEADERS + kwargs['data'] = json.dumps(req_2) + requests.request( + 'PUT', + urlparse.urljoin(self.TEST_URL, 'v2.0/users/2/OS-KSADM/password'), + **kwargs).AndReturn((resp_2)) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_POST_HEADERS + kwargs['data'] = json.dumps(req_3) + requests.request( + 'PUT', + urlparse.urljoin(self.TEST_URL, 'v2.0/users/2/OS-KSADM/tenant'), + **kwargs).AndReturn((resp_3)) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_POST_HEADERS + kwargs['data'] = json.dumps(req_4) + requests.request( + 'PUT', + urlparse.urljoin(self.TEST_URL, 'v2.0/users/2/OS-KSADM/enabled'), + **kwargs).AndReturn((resp_4)) self.mox.ReplayAll() user = self.client.users.update(2, @@ -222,17 +271,26 @@ class UserTests(utils.TestCase): user = self.client.users.update_enabled(2, False) def test_update_own_password(self): - req_1 = {'user': {'password': 'ABCD', 'original_password': 'DCBA'}} - - resp_1 = {'access': {}} - resp_1 = httplib2.Response({'status': 200, 'body': json.dumps(resp_1)}) + req_body = { + 'user': { + 'password': 'ABCD', 'original_password': 'DCBA' + } + } + resp_body = { + 'access': {} + } + resp = utils.TestResponse({ + "status_code": 200, + "text": json.dumps(resp_body) + }) - httplib2.Http.request(urlparse.urljoin(self.TEST_URL, - 'v2.0/OS-KSCRUD/users/123'), - 'PATCH', - body=json.dumps(req_1), - headers=self.TEST_POST_HEADERS) \ - .AndReturn((resp_1, resp_1['body'])) + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.TEST_POST_HEADERS + kwargs['data'] = json.dumps(req_body) + requests.request( + 'PATCH', + urlparse.urljoin(self.TEST_URL, 'v2.0/OS-KSCRUD/users/123'), + **kwargs).AndReturn((resp)) self.mox.ReplayAll() diff --git a/tests/v3/test_projects.py b/tests/v3/test_projects.py index 8a4ef40..92bdc84 100644 --- a/tests/v3/test_projects.py +++ b/tests/v3/test_projects.py @@ -1,7 +1,9 @@ -import httplib2 +import copy import urlparse import uuid +import requests + from keystoneclient.v3 import projects from tests.v3 import utils @@ -26,19 +28,20 @@ class ProjectTests(utils.TestCase, utils.CrudTests): ref_list = [self.new_ref(), self.new_ref()] user_id = uuid.uuid4().hex - resp = httplib2.Response({ - 'status': 200, - 'body': self.serialize(ref_list), + resp = utils.TestResponse({ + "status-code": 200, + "text": self.serialize(ref_list), }) method = 'GET' - httplib2.Http.request( + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.headers[method] + requests.request( + method, urlparse.urljoin( self.TEST_URL, 'v3/users/%s/%s' % (user_id, self.collection_key)), - method, - headers=self.headers[method]) \ - .AndReturn((resp, resp['body'])) + **kwargs).AndReturn((resp)) self.mox.ReplayAll() returned_list = self.manager.list(user=user_id) @@ -49,19 +52,20 @@ class ProjectTests(utils.TestCase, utils.CrudTests): ref_list = [self.new_ref(), self.new_ref()] domain_id = uuid.uuid4().hex - resp = httplib2.Response({ - 'status': 200, - 'body': self.serialize(ref_list), + resp = utils.TestResponse({ + "status_code": 200, + "text": self.serialize(ref_list), }) method = 'GET' - httplib2.Http.request( + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.headers[method] + requests.request( + method, urlparse.urljoin( self.TEST_URL, 'v3/%s?domain_id=%s' % (self.collection_key, domain_id)), - method, - headers=self.headers[method]) \ - .AndReturn((resp, resp['body'])) + **kwargs).AndReturn((resp)) self.mox.ReplayAll() returned_list = self.manager.list(domain=domain_id) diff --git a/tests/v3/test_roles.py b/tests/v3/test_roles.py index e3fe353..67ac591 100644 --- a/tests/v3/test_roles.py +++ b/tests/v3/test_roles.py @@ -1,7 +1,9 @@ -import httplib2 +import copy import urlparse import uuid +import requests + from keystoneclient import exceptions from keystoneclient.v3 import roles from tests.v3 import utils @@ -25,20 +27,21 @@ class RoleTests(utils.TestCase, utils.CrudTests): user_id = uuid.uuid4().hex domain_id = uuid.uuid4().hex ref = self.new_ref() - resp = httplib2.Response({ - 'status': 201, - 'body': '', + resp = utils.TestResponse({ + "status_code": 201, + "text": '', }) method = 'PUT' - httplib2.Http.request( + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.headers[method] + requests.request( + method, urlparse.urljoin( self.TEST_URL, 'v3/domains/%s/users/%s/%s/%s' % ( domain_id, user_id, self.collection_key, ref['id'])), - method, - headers=self.headers[method]) \ - .AndReturn((resp, resp['body'])) + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.manager.grant(role=ref['id'], domain=domain_id, user=user_id) @@ -47,20 +50,21 @@ class RoleTests(utils.TestCase, utils.CrudTests): user_id = uuid.uuid4().hex domain_id = uuid.uuid4().hex ref_list = [self.new_ref(), self.new_ref()] - resp = httplib2.Response({ - 'status': 200, - 'body': self.serialize(ref_list), + resp = utils.TestResponse({ + "status_code": 200, + "text": self.serialize(ref_list), }) method = 'GET' - httplib2.Http.request( + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.headers[method] + requests.request( + method, urlparse.urljoin( self.TEST_URL, 'v3/domains/%s/users/%s/%s' % ( domain_id, user_id, self.collection_key)), - method, - headers=self.headers[method]) \ - .AndReturn((resp, resp['body'])) + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.manager.list(domain=domain_id, user=user_id) @@ -69,20 +73,21 @@ class RoleTests(utils.TestCase, utils.CrudTests): user_id = uuid.uuid4().hex domain_id = uuid.uuid4().hex ref = self.new_ref() - resp = httplib2.Response({ - 'status': 200, - 'body': '', + resp = utils.TestResponse({ + "status_code": 200, + "text": '', }) method = 'HEAD' - httplib2.Http.request( + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.headers[method] + requests.request( + method, urlparse.urljoin( self.TEST_URL, 'v3/domains/%s/users/%s/%s/%s' % ( domain_id, user_id, self.collection_key, ref['id'])), - method, - headers=self.headers[method]) \ - .AndReturn((resp, resp['body'])) + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.manager.check(role=ref['id'], domain=domain_id, user=user_id) @@ -91,20 +96,21 @@ class RoleTests(utils.TestCase, utils.CrudTests): user_id = uuid.uuid4().hex domain_id = uuid.uuid4().hex ref = self.new_ref() - resp = httplib2.Response({ - 'status': 204, - 'body': '', + resp = utils.TestResponse({ + "status_code": 204, + "text": '', }) method = 'DELETE' - httplib2.Http.request( + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.headers[method] + requests.request( + method, urlparse.urljoin( self.TEST_URL, 'v3/domains/%s/users/%s/%s/%s' % ( domain_id, user_id, self.collection_key, ref['id'])), - method, - headers=self.headers[method]) \ - .AndReturn((resp, resp['body'])) + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.manager.revoke(role=ref['id'], domain=domain_id, user=user_id) @@ -113,20 +119,21 @@ class RoleTests(utils.TestCase, utils.CrudTests): user_id = uuid.uuid4().hex project_id = uuid.uuid4().hex ref = self.new_ref() - resp = httplib2.Response({ - 'status': 201, - 'body': '', + resp = utils.TestResponse({ + "status_code": 201, + "text": '', }) method = 'PUT' - httplib2.Http.request( + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.headers[method] + requests.request( + method, urlparse.urljoin( self.TEST_URL, 'v3/projects/%s/users/%s/%s/%s' % ( project_id, user_id, self.collection_key, ref['id'])), - method, - headers=self.headers[method]) \ - .AndReturn((resp, resp['body'])) + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.manager.grant(role=ref['id'], project=project_id, user=user_id) @@ -135,20 +142,21 @@ class RoleTests(utils.TestCase, utils.CrudTests): user_id = uuid.uuid4().hex project_id = uuid.uuid4().hex ref_list = [self.new_ref(), self.new_ref()] - resp = httplib2.Response({ - 'status': 200, - 'body': self.serialize(ref_list), + resp = utils.TestResponse({ + "status_code": 200, + "text": self.serialize(ref_list), }) method = 'GET' - httplib2.Http.request( + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.headers[method] + requests.request( + method, urlparse.urljoin( self.TEST_URL, 'v3/projects/%s/users/%s/%s' % ( project_id, user_id, self.collection_key)), - method, - headers=self.headers[method]) \ - .AndReturn((resp, resp['body'])) + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.manager.list(project=project_id, user=user_id) @@ -157,20 +165,21 @@ class RoleTests(utils.TestCase, utils.CrudTests): user_id = uuid.uuid4().hex project_id = uuid.uuid4().hex ref = self.new_ref() - resp = httplib2.Response({ - 'status': 200, - 'body': '', + resp = utils.TestResponse({ + "status_code": 200, + "text": '', }) method = 'HEAD' - httplib2.Http.request( + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.headers[method] + requests.request( + method, urlparse.urljoin( self.TEST_URL, 'v3/projects/%s/users/%s/%s/%s' % ( project_id, user_id, self.collection_key, ref['id'])), - method, - headers=self.headers[method]) \ - .AndReturn((resp, resp['body'])) + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.manager.check(role=ref['id'], project=project_id, user=user_id) @@ -179,20 +188,21 @@ class RoleTests(utils.TestCase, utils.CrudTests): user_id = uuid.uuid4().hex project_id = uuid.uuid4().hex ref = self.new_ref() - resp = httplib2.Response({ - 'status': 204, - 'body': '', + resp = utils.TestResponse({ + "status_code": 204, + "text": '', }) method = 'DELETE' - httplib2.Http.request( + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.headers[method] + requests.request( + method, urlparse.urljoin( self.TEST_URL, 'v3/projects/%s/users/%s/%s/%s' % ( project_id, user_id, self.collection_key, ref['id'])), - method, - headers=self.headers[method]) \ - .AndReturn((resp, resp['body'])) + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.manager.revoke(role=ref['id'], project=project_id, user=user_id) diff --git a/tests/v3/utils.py b/tests/v3/utils.py index d45a07c..3fec457 100644 --- a/tests/v3/utils.py +++ b/tests/v3/utils.py @@ -1,10 +1,11 @@ +import copy import json import uuid import time import urlparse -import httplib2 import mox +import requests import unittest2 as unittest from keystoneclient.v3 import client @@ -24,6 +25,12 @@ def parameterize(ref): return params +class TestClient(client.Client): + + def serialize(self, entity): + return json.dumps(entity, sort_keys=True) + + class TestCase(unittest.TestCase): TEST_TENANT_NAME = 'aTenant' TEST_TOKEN = 'aToken' @@ -32,18 +39,22 @@ class TestCase(unittest.TestCase): TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v3') TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/' TEST_ADMIN_URL = '%s%s' % (TEST_ROOT_ADMIN_URL, 'v3') + TEST_REQUEST_BASE = { + 'config': {'danger_mode': False}, + 'verify': True, + } def setUp(self): super(TestCase, self).setUp() self.mox = mox.Mox() self._original_time = time.time time.time = lambda: 1234 - httplib2.Http.request = self.mox.CreateMockAnything() - self.client = client.Client(username=self.TEST_USER, - token=self.TEST_TOKEN, - tenant_name=self.TEST_TENANT_NAME, - auth_url=self.TEST_URL, - endpoint=self.TEST_URL) + requests.request = self.mox.CreateMockAnything() + self.client = TestClient(username=self.TEST_USER, + token=self.TEST_TOKEN, + tenant_name=self.TEST_TENANT_NAME, + auth_url=self.TEST_URL, + endpoint=self.TEST_URL) def tearDown(self): time.time = self._original_time @@ -58,13 +69,17 @@ class UnauthenticatedTestCase(unittest.TestCase): TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v3') TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/' TEST_ADMIN_URL = '%s%s' % (TEST_ROOT_ADMIN_URL, 'v3') + TEST_REQUEST_BASE = { + 'config': {'danger_mode': False}, + 'verify': True, + } def setUp(self): super(UnauthenticatedTestCase, self).setUp() self.mox = mox.Mox() self._original_time = time.time time.time = lambda: 1234 - httplib2.Http.request = self.mox.CreateMockAnything() + requests.request = self.mox.CreateMockAnything() def tearDown(self): time.time = self._original_time @@ -107,22 +122,23 @@ class CrudTests(object): def test_create(self, ref=None): ref = ref or self.new_ref() - resp = httplib2.Response({ - 'status': 201, - 'body': self.serialize(ref), + resp = TestResponse({ + "status_code": 201, + "text": self.serialize(ref), }) method = 'POST' req_ref = ref.copy() req_ref.pop('id') - httplib2.Http.request( + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.headers[method] + kwargs['data'] = self.serialize(req_ref) + requests.request( + method, urlparse.urljoin( self.TEST_URL, 'v3/%s' % self.collection_key), - method, - body=self.serialize(req_ref), - headers=self.headers[method]) \ - .AndReturn((resp, resp['body'])) + **kwargs).AndReturn((resp)) self.mox.ReplayAll() returned = self.manager.create(**parameterize(req_ref)) @@ -135,18 +151,20 @@ class CrudTests(object): def test_get(self, ref=None): ref = ref or self.new_ref() - resp = httplib2.Response({ - 'status': 200, - 'body': self.serialize(ref), + resp = TestResponse({ + "status_code": 200, + "text": self.serialize(ref), }) + method = 'GET' - httplib2.Http.request( + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.headers[method] + requests.request( + method, urlparse.urljoin( self.TEST_URL, 'v3/%s/%s' % (self.collection_key, ref['id'])), - method, - headers=self.headers[method]) \ - .AndReturn((resp, resp['body'])) + **kwargs).AndReturn((resp)) self.mox.ReplayAll() returned = self.manager.get(ref['id']) @@ -159,20 +177,20 @@ class CrudTests(object): def test_list(self, ref_list=None, expected_path=None, **filter_kwargs): ref_list = ref_list or [self.new_ref(), self.new_ref()] - - resp = httplib2.Response({ - 'status': 200, - 'body': self.serialize(ref_list), + resp = TestResponse({ + "status_code": 200, + "text": self.serialize(ref_list), }) method = 'GET' - httplib2.Http.request( + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.headers[method] + requests.request( + method, urlparse.urljoin( self.TEST_URL, expected_path or 'v3/%s' % self.collection_key), - method, - headers=self.headers[method]) \ - .AndReturn((resp, resp['body'])) + **kwargs).AndReturn((resp)) self.mox.ReplayAll() returned_list = self.manager.list(**filter_kwargs) @@ -183,21 +201,21 @@ class CrudTests(object): ref = ref or self.new_ref() req_ref = ref.copy() del req_ref['id'] - - resp = httplib2.Response({ - 'status': 200, - 'body': self.serialize(ref), + resp = TestResponse({ + "status_code": 200, + "text": self.serialize(ref), }) method = 'PATCH' - httplib2.Http.request( + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.headers[method] + kwargs['data'] = self.serialize(req_ref) + requests.request( + method, urlparse.urljoin( self.TEST_URL, 'v3/%s/%s' % (self.collection_key, ref['id'])), - method, - body=self.serialize(req_ref), - headers=self.headers[method]) \ - .AndReturn((resp, resp['body'])) + **kwargs).AndReturn((resp)) self.mox.ReplayAll() returned = self.manager.update(ref['id'], **parameterize(req_ref)) @@ -210,18 +228,43 @@ class CrudTests(object): def test_delete(self, ref=None): ref = ref or self.new_ref() - method = 'DELETE' - resp = httplib2.Response({ - 'status': 204, - 'body': '', + resp = TestResponse({ + "status_code": 204, + "text": '', }) - httplib2.Http.request( + + method = 'DELETE' + kwargs = copy.copy(self.TEST_REQUEST_BASE) + kwargs['headers'] = self.headers[method] + requests.request( + method, urlparse.urljoin( self.TEST_URL, 'v3/%s/%s' % (self.collection_key, ref['id'])), - method, - headers=self.headers[method]) \ - .AndReturn((resp, resp['body'])) + **kwargs).AndReturn((resp)) self.mox.ReplayAll() self.manager.delete(ref['id']) + + +class TestResponse(requests.Response): + """ Class used to wrap requests.Response and provide some + convenience to initialize with a dict """ + + def __init__(self, data): + self._text = None + super(TestResponse, self) + if isinstance(data, dict): + self.status_code = data.get('status_code', None) + self.headers = data.get('headers', None) + # Fake the text attribute to streamline Response creation + self._text = data.get('text', None) + else: + self.status_code = data + + def __eq__(self, other): + return self.__dict__ == other.__dict__ + + @property + def text(self): + return self._text diff --git a/tools/pip-requires b/tools/pip-requires index 11022aa..fab4830 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -1,4 +1,4 @@ argparse -httplib2>=0.7 prettytable +requests<1.0 simplejson |