diff options
author | ekudryashova <ekudryashova@mirantis.com> | 2014-01-23 19:28:09 +0200 |
---|---|---|
committer | Eugeniya Kudryashova <ekudryashova@mirantis.com> | 2014-07-31 18:59:58 +0300 |
commit | 47934c777c50897b649793e0960eebdaad322c45 (patch) | |
tree | d265370067aa46be001d1656936c916bc418a50a | |
parent | 092eb6643161747186ba4d0947a847af45e3d546 (diff) | |
download | python-ceilometerclient-47934c777c50897b649793e0960eebdaad322c45.tar.gz |
Use HTTPClient from common Oslo code
In the process of unification of the clients code we should
reuse common functionality from Oslo.
bp common-client-library-2
Change-Id: I0e027c33ee42b6de032d33269caeea33e7837f40
31 files changed, 498 insertions, 888 deletions
diff --git a/ceilometerclient/client.py b/ceilometerclient/client.py index b66e547..283e24e 100644 --- a/ceilometerclient/client.py +++ b/ceilometerclient/client.py @@ -14,10 +14,11 @@ from keystoneclient.auth.identity import v2 as v2_auth from keystoneclient.auth.identity import v3 as v3_auth from keystoneclient import discover from keystoneclient import session -import six from ceilometerclient.common import utils from ceilometerclient import exc +from ceilometerclient.openstack.common.apiclient import auth +from ceilometerclient.openstack.common.apiclient import exceptions def _get_keystone_session(**kwargs): @@ -139,12 +140,94 @@ def _get_endpoint(ks_session, **kwargs): return endpoint -def get_client(api_version, **kwargs): +class AuthPlugin(auth.BaseAuthPlugin): + opt_names = ['tenant_id', 'region_name', 'auth_token', + 'service_type', 'endpoint_type', 'cacert', + 'auth_url', 'insecure', 'cert_file', 'key_file', + 'cert', 'key', 'tenant_name', 'project_name', + 'project_id', 'user_domain_id', 'user_domain_name', + 'password', 'username'] + + def __init__(self, auth_system=None, **kwargs): + self.opt_names.extend(self.common_opt_names) + super(AuthPlugin, self).__init__(auth_system, **kwargs) + + def _do_authenticate(self, http_client): + if self.opts.get('token') and self.opts.get('endpoint'): + token = self.opts.get('token') + endpoint = self.opts.get('endpoint') + else: + project_id = self.opts.get('project_id') \ + or self.opts.get('tenant_id') + project_name = (self.opts.get('project_name') or + self.opts.get('tenant_name')) + ks_kwargs = { + 'username': self.opts.get('username'), + 'password': self.opts.get('password'), + 'user_id': self.opts.get('user_id'), + 'user_domain_id': self.opts.get('user_domain_id'), + 'user_domain_name': self.opts.get('user_domain_name'), + 'project_id': project_id, + 'project_name': project_name, + 'project_domain_name': self.opts.get('project_domain_name'), + 'project_domain_id': self.opts.get('project_domain_id'), + 'auth_url': self.opts.get('auth_url'), + 'cacert': self.opts.get('cacert'), + 'cert': self.opts.get('cert'), + 'key': self.opts.get('key'), + 'insecure': self.opts.get('insecure') + } + + # retrieve session + ks_session = _get_keystone_session(**ks_kwargs) + token = lambda: ks_session.get_token() + endpoint = self.opts.get('endpoint') or \ + _get_endpoint(ks_session, **ks_kwargs) + self.opts['token'] = token() + self.opts['endpoint'] = endpoint + + def token_and_endpoint(self, endpoint_type, service_type): + token = self.opts.get('token') + if callable(token): + token = token() + return token, self.opts.get('endpoint') + + def sufficient_options(self): + """Check if all required options are present. + + :raises: AuthPluginOptionsMissing + """ + missing = not ((self.opts.get('token') and + self.opts.get('endpoint')) or + (self.opts.get('username') + and self.opts.get('password') + and self.opts.get('auth_url') and + (self.opts.get('tenant_id') + or self.opts.get('tenant_name')))) + + if missing: + missing_opts = [] + opts = ['token', 'endpoint', 'username', 'password', 'auth_url', + 'tenant_id', 'tenant_name'] + for opt in opts: + if not self.opts.get(opt): + missing_opts.append(opt) + raise exceptions.AuthPluginOptionsMissing(missing_opts) + + +def Client(version, *args, **kwargs): + module = utils.import_versioned_module(version, 'client') + client_class = getattr(module, 'Client') + return client_class(*args, **kwargs) + + +def get_client(version, **kwargs): """Get an authtenticated client, based on the credentials - in the keyword args. + in the keyword args. :param api_version: the API version to use ('1' or '2') :param kwargs: keyword args containing credentials, either: + * os_auth_token: pre-existing token to re-use * ceilometer_url: ceilometer API endpoint or: @@ -164,53 +247,38 @@ def get_client(api_version, **kwargs): * os_key: SSL private key * insecure: allow insecure SSL (no cert verification) """ - token = kwargs.get('os_auth_token') - if token and not six.callable(token): - token = lambda: kwargs.get('os_auth_token') - - if token and kwargs.get('ceilometer_url'): - endpoint = kwargs.get('ceilometer_url') - else: - project_id = kwargs.get('os_project_id') or kwargs.get('os_tenant_id') - project_name = (kwargs.get('os_project_name') or - kwargs.get('os_tenant_name')) - ks_kwargs = { - 'username': kwargs.get('os_username'), - 'password': kwargs.get('os_password'), - 'user_id': kwargs.get('os_user_id'), - 'user_domain_id': kwargs.get('os_user_domain_id'), - 'user_domain_name': kwargs.get('os_user_domain_name'), - 'project_id': project_id, - 'project_name': project_name, - 'project_domain_name': kwargs.get('os_project_domain_name'), - 'project_domain_id': kwargs.get('os_project_domain_id'), - 'auth_url': kwargs.get('os_auth_url'), - 'cacert': kwargs.get('os_cacert'), - 'cert': kwargs.get('os_cert'), - 'key': kwargs.get('os_key'), - 'insecure': kwargs.get('insecure') - } - - # retrieve session - ks_session = _get_keystone_session(**ks_kwargs) - token = token or (lambda: ks_session.get_token()) - - endpoint = kwargs.get('ceilometer_url') or \ - _get_endpoint(ks_session, **ks_kwargs) + endpoint = kwargs.get('ceilometer_url') cli_kwargs = { - 'token': token, - 'insecure': kwargs.get('insecure'), - 'timeout': kwargs.get('timeout'), + 'username': kwargs.get('os_username'), + 'password': kwargs.get('os_password'), + 'tenant_id': kwargs.get('os_tenant_id'), + 'tenant_name': kwargs.get('os_tenant_name'), + 'auth_url': kwargs.get('os_auth_url'), + 'region_name': kwargs.get('os_region_name'), + 'service_type': kwargs.get('os_service_type'), + 'endpoint_type': kwargs.get('os_endpoint_type'), 'cacert': kwargs.get('os_cacert'), 'cert_file': kwargs.get('os_cert'), - 'key_file': kwargs.get('os_key') + 'key_file': kwargs.get('os_key'), + 'token': kwargs.get('os_auth_token'), } - return Client(api_version, endpoint, **cli_kwargs) + cli_kwargs.update(kwargs) + return Client(version, endpoint, **cli_kwargs) -def Client(version, *args, **kwargs): - module = utils.import_versioned_module(version, 'client') - client_class = getattr(module, 'Client') - return client_class(*args, **kwargs) +def get_auth_plugin(endpoint, **kwargs): + auth_plugin = AuthPlugin( + auth_url=kwargs.get('auth_url'), + service_type=kwargs.get('service_type'), + token=kwargs.get('token'), + endpoint_type=kwargs.get('endpoint_type'), + cacert=kwargs.get('ca_file'), + tenant_id=kwargs.get('project_id') or kwargs.get('tenant_id'), + endpoint=endpoint, + username=kwargs.get('username'), + password=kwargs.get('password'), + tenant_name=kwargs.get('tenant_name'), + ) + return auth_plugin diff --git a/ceilometerclient/common/base.py b/ceilometerclient/common/base.py index a01adbf..7d4be24 100644 --- a/ceilometerclient/common/base.py +++ b/ceilometerclient/common/base.py @@ -49,13 +49,13 @@ class Manager(object): self.api = api def _create(self, url, body): - resp, body = self.api.json_request('POST', url, body=body) + body = self.api.post(url, json=body).json() if body: return self.resource_class(self, body) def _list(self, url, response_key=None, obj_class=None, body=None, expect_single=False): - resp, body = self.api.json_request('GET', url) + body = self.api.get(url).json() if obj_class is None: obj_class = self.resource_class @@ -72,13 +72,13 @@ class Manager(object): return [obj_class(self, res, loaded=True) for res in data if res] def _update(self, url, body, response_key=None): - resp, body = self.api.json_request('PUT', url, body=body) + body = self.api.put(url, json=body).json() # PUT requests may not return a body if body: return self.resource_class(self, body) def _delete(self, url): - self.api.raw_request('DELETE', url) + self.api.delete(url) class Resource(base.Resource): diff --git a/ceilometerclient/common/http.py b/ceilometerclient/common/http.py deleted file mode 100644 index 56373ee..0000000 --- a/ceilometerclient/common/http.py +++ /dev/null @@ -1,313 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy -import hashlib -import logging -import os -import socket - -try: - import ssl -except ImportError: - # TODO(bcwaldon): Handle this failure more gracefully - pass - -try: - import json -except ImportError: - import simplejson as json - -import six -from six.moves import http_client as httplib # noqa -from six.moves import urllib - -from ceilometerclient import exc - - -LOG = logging.getLogger(__name__) -USER_AGENT = 'python-ceilometerclient' -CHUNKSIZE = 1024 * 64 # 64kB -SENSITIVE_HEADERS = ('X-Auth-Token',) - - -class HTTPClient(object): - - def __init__(self, endpoint, **kwargs): - self.endpoint = endpoint - self.auth_token = kwargs.get('token') - self.connection_params = self.get_connection_params(endpoint, **kwargs) - self.proxy_url = self.get_proxy_url() - - @staticmethod - def get_connection_params(endpoint, **kwargs): - parts = urllib.parse.urlparse(endpoint) - - _args = (parts.hostname, parts.port, parts.path) - _kwargs = {'timeout': (float(kwargs.get('timeout')) - if kwargs.get('timeout') else 600)} - - if parts.scheme == 'https': - _class = VerifiedHTTPSConnection - _kwargs['cacert'] = kwargs.get('cacert', None) - _kwargs['cert_file'] = kwargs.get('cert_file', None) - _kwargs['key_file'] = kwargs.get('key_file', None) - _kwargs['insecure'] = kwargs.get('insecure', False) - elif parts.scheme == 'http': - _class = httplib.HTTPConnection - else: - msg = 'Unsupported scheme: %s' % parts.scheme - raise exc.InvalidEndpoint(msg) - - return (_class, _args, _kwargs) - - def get_connection(self): - _class = self.connection_params[0] - try: - if self.proxy_url: - proxy_parts = urllib.parse.urlparse(self.proxy_url) - return _class(proxy_parts.hostname, proxy_parts.port, - **self.connection_params[2]) - else: - return _class(*self.connection_params[1][0:2], - **self.connection_params[2]) - except httplib.InvalidURL: - raise exc.InvalidEndpoint() - - def safe_header(self, name, value): - if name in SENSITIVE_HEADERS: - # because in python3 byte string handling is ... ug - v = value.encode('utf-8') - h = hashlib.sha1(v) - d = h.hexdigest() - return name, "{SHA1}%s" % d - else: - return name, value - - def log_curl_request(self, method, url, kwargs): - curl = ['curl -i -X %s' % method] - - for (key, value) in kwargs['headers'].items(): - header = '-H \'%s: %s\'' % self.safe_header(key, value) - curl.append(header) - - conn_params_fmt = [ - ('key_file', '--key %s'), - ('cert_file', '--cert %s'), - ('cacert', '--cacert %s'), - ] - for (key, fmt) in conn_params_fmt: - value = self.connection_params[2].get(key) - if value: - curl.append(fmt % value) - - if self.connection_params[2].get('insecure'): - curl.append('-k') - - if 'body' in kwargs: - curl.append('-d \'%s\'' % kwargs['body']) - - curl.append('%s/%s' % (self.endpoint.rstrip('/'), url.lstrip('/'))) - LOG.debug(' '.join(curl)) - - @staticmethod - def log_http_response(resp, body=None): - status = (resp.version / 10.0, resp.status, resp.reason) - dump = ['\nHTTP/%.1f %s %s' % status] - dump.extend(['%s: %s' % (k, v) for k, v in resp.getheaders()]) - dump.append('') - if body: - dump.extend([body, '']) - LOG.debug('\n'.join(dump)) - - def _make_connection_url(self, url): - (_class, _args, _kwargs) = self.connection_params - base_url = _args[2] - return '%s/%s' % (base_url.rstrip('/'), url.lstrip('/')) - - def _http_request(self, url, method, **kwargs): - """Send an http request with the specified characteristics. - - Wrapper around httplib.HTTP(S)Connection.request to handle tasks such - as setting headers and error handling. - """ - # Copy the kwargs so we can reuse the original in case of redirects - kwargs['headers'] = copy.deepcopy(kwargs.get('headers', {})) - kwargs['headers'].setdefault('User-Agent', USER_AGENT) - auth_token = self.auth_token() - if auth_token: - kwargs['headers'].setdefault('X-Auth-Token', auth_token) - - self.log_curl_request(method, url, kwargs) - conn = self.get_connection() - - try: - if self.proxy_url: - conn_url = (self.endpoint.rstrip('/') + - self._make_connection_url(url)) - else: - conn_url = self._make_connection_url(url) - conn.request(method, conn_url, **kwargs) - resp = conn.getresponse() - except socket.gaierror as e: - message = ("Error finding address for %(url)s: %(e)s" - % dict(url=url, e=e)) - raise exc.InvalidEndpoint(message=message) - except (socket.error, socket.timeout) as e: - endpoint = self.endpoint - message = ("Error communicating with %(endpoint)s %(e)s" - % dict(endpoint=endpoint, e=e)) - raise exc.CommunicationError(message=message) - - body_iter = ResponseBodyIterator(resp) - - # Read body into string if it isn't obviously image data - if resp.getheader('content-type', None) != 'application/octet-stream': - body_str = ''.join([chunk for chunk in body_iter]) - self.log_http_response(resp, body_str) - body_iter = six.StringIO(body_str) - else: - self.log_http_response(resp) - - if 400 <= resp.status < 600: - LOG.warn("Request returned failure status.") - raise exc.from_response(resp, ''.join(body_iter)) - elif resp.status in (301, 302, 305): - # Redirected. Reissue the request to the new location. - return self._http_request(resp['location'], method, **kwargs) - elif resp.status == 300: - raise exc.from_response(resp) - - return resp, body_iter - - def json_request(self, method, url, **kwargs): - kwargs.setdefault('headers', {}) - kwargs['headers'].setdefault('Content-Type', 'application/json') - kwargs['headers'].setdefault('Accept', 'application/json') - - if 'body' in kwargs: - kwargs['body'] = json.dumps(kwargs['body']) - - resp, body_iter = self._http_request(url, method, **kwargs) - content_type = resp.getheader('content-type', None) - - if resp.status == 204 or resp.status == 205 or content_type is None: - return resp, list() - - if 'application/json' in content_type: - body = ''.join([chunk for chunk in body_iter]) - try: - body = json.loads(body) - except ValueError: - LOG.error('Could not decode response body as JSON') - else: - body = None - - return resp, body - - def raw_request(self, method, url, **kwargs): - kwargs.setdefault('headers', {}) - kwargs['headers'].setdefault('Content-Type', - 'application/octet-stream') - return self._http_request(url, method, **kwargs) - - def get_proxy_url(self): - scheme = urllib.parse.urlparse(self.endpoint).scheme - if scheme == 'https': - return os.environ.get('https_proxy') - elif scheme == 'http': - return os.environ.get('http_proxy') - msg = 'Unsupported scheme: %s' % scheme - raise exc.InvalidEndpoint(msg) - - -class VerifiedHTTPSConnection(httplib.HTTPSConnection): - """httplib-compatibile connection using client-side SSL authentication - - :see http://code.activestate.com/recipes/ - 577548-https-httplib-client-connection-with-certificate-v/ - """ - - def __init__(self, host, port, key_file=None, cert_file=None, - cacert=None, timeout=None, insecure=False): - httplib.HTTPSConnection.__init__(self, host, port, key_file=key_file, - cert_file=cert_file) - self.key_file = key_file - self.cert_file = cert_file - if cacert is not None: - self.cacert = cacert - else: - self.cacert = self.get_system_ca_file() - self.timeout = timeout - self.insecure = insecure - - def connect(self): - """Connect to a host on a given (SSL) port. - If cacert is pointing somewhere, use it to check Server Certificate. - - Redefined/copied and extended from httplib.py:1105 (Python 2.6.x). - This is needed to pass cert_reqs=ssl.CERT_REQUIRED as parameter to - ssl.wrap_socket(), which forces SSL to check server certificate against - our client certificate. - """ - sock = socket.create_connection((self.host, self.port), self.timeout) - - if self._tunnel_host: - self.sock = sock - self._tunnel() - - if self.insecure is True: - kwargs = {'cert_reqs': ssl.CERT_NONE} - else: - kwargs = {'cert_reqs': ssl.CERT_REQUIRED, 'ca_certs': self.cacert} - - if self.cert_file: - kwargs['certfile'] = self.cert_file - if self.key_file: - kwargs['keyfile'] = self.key_file - - self.sock = ssl.wrap_socket(sock, **kwargs) - - @staticmethod - def get_system_ca_file(): - """Return path to system default CA file.""" - # Standard CA file locations for Debian/Ubuntu, RedHat/Fedora, - # Suse, FreeBSD/OpenBSD - ca_path = ['/etc/ssl/certs/ca-certificates.crt', - '/etc/pki/tls/certs/ca-bundle.crt', - '/etc/ssl/ca-bundle.pem', - '/etc/ssl/cert.pem'] - for ca in ca_path: - if os.path.exists(ca): - return ca - return None - - -class ResponseBodyIterator(object): - """A class that acts as an iterator over an HTTP response.""" - - def __init__(self, resp): - self.resp = resp - - def __iter__(self): - while True: - yield self.next() - - def next(self): - chunk = self.resp.read(CHUNKSIZE) - if chunk: - return chunk - else: - raise StopIteration() diff --git a/ceilometerclient/shell.py b/ceilometerclient/shell.py index 98f3851..138dd62 100644 --- a/ceilometerclient/shell.py +++ b/ceilometerclient/shell.py @@ -32,157 +32,6 @@ from ceilometerclient.openstack.common import strutils class CeilometerShell(object): - def _append_identity_args(self, parser): - # FIXME(fabgia): identity related parameters should be passed by the - # Keystone client itself to avoid constant update in all the services - # clients. When this fix is merged this method can be made obsolete. - # Bug: https://bugs.launchpad.net/python-keystoneclient/+bug/1332337 - parser.add_argument('-k', '--insecure', - default=False, - action='store_true', - help="Explicitly allow ceilometerclient 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.") - - # User related options - parser.add_argument('--os-username', - default=cliutils.env('OS_USERNAME'), - help='Defaults to env[OS_USERNAME].') - - parser.add_argument('--os_username', - help=argparse.SUPPRESS) - - parser.add_argument('--os-user-id', - default=cliutils.env('OS_USER_ID'), - help='Defaults to env[OS_USER_ID].') - - parser.add_argument('--os-password', - default=cliutils.env('OS_PASSWORD'), - help='Defaults to env[OS_PASSWORD].') - - parser.add_argument('--os_password', - help=argparse.SUPPRESS) - - # Domain related options - parser.add_argument('--os-user-domain-id', - default=cliutils.env('OS_USER_DOMAIN_ID'), - help='Defaults to env[OS_USER_DOMAIN_ID].') - - parser.add_argument('--os-user-domain-name', - default=cliutils.env('OS_USER_DOMAIN_NAME'), - help='Defaults to env[OS_USER_DOMAIN_NAME].') - - parser.add_argument('--os-project-domain-id', - default=cliutils.env('OS_PROJECT_DOMAIN_ID'), - help='Defaults to env[OS_PROJECT_DOMAIN_ID].') - - parser.add_argument('--os-project-domain-name', - default=cliutils.env('OS_PROJECT_DOMAIN_NAME'), - help='Defaults to env[OS_PROJECT_DOMAIN_NAME].') - - # Project V3 or Tenant V2 related options - parser.add_argument('--os-project-id', - default=cliutils.env('OS_PROJECT_ID'), - help='Another way to specify tenant ID. ' - 'This option is mutually exclusive with ' - ' --os-tenant-id. ' - 'Defaults to env[OS_PROJECT_ID].') - - parser.add_argument('--os-project-name', - default=cliutils.env('OS_PROJECT_NAME'), - help='Another way to specify tenant name. ' - 'This option is mutually exclusive with ' - ' --os-tenant-name. ' - 'Defaults to env[OS_PROJECT_NAME].') - - parser.add_argument('--os-tenant-id', - default=cliutils.env('OS_TENANT_ID'), - help='This option is mutually exclusive with ' - ' --os-project-id. ' - 'Defaults to env[OS_PROJECT_ID].') - - parser.add_argument('--os_tenant_id', - help=argparse.SUPPRESS) - - parser.add_argument('--os-tenant-name', - default=cliutils.env('OS_TENANT_NAME'), - help='Defaults to env[OS_TENANT_NAME].') - - parser.add_argument('--os_tenant_name', - help=argparse.SUPPRESS) - - # Auth related options - parser.add_argument('--os-auth-url', - default=cliutils.env('OS_AUTH_URL'), - help='Defaults to env[OS_AUTH_URL].') - - parser.add_argument('--os_auth_url', - help=argparse.SUPPRESS) - - parser.add_argument('--os-auth-token', - default=cliutils.env('OS_AUTH_TOKEN'), - help='Defaults to env[OS_AUTH_TOKEN].') - - parser.add_argument('--os_auth_token', - help=argparse.SUPPRESS) - - parser.add_argument('--os-cacert', - metavar='<ca-certificate-file>', - dest='os_cacert', - default=cliutils.env('OS_CACERT'), - help='Path of CA TLS certificate(s) used to verify' - 'the remote server\'s certificate. Without this ' - 'option ceilometer looks for the default system ' - 'CA certificates.') - - parser.add_argument('--os-cert', - help='Path of certificate file to use in SSL ' - 'connection. This file can optionally be ' - 'prepended with the private key.') - - parser.add_argument('--os-key', - help='Path of client key to use in SSL ' - 'connection. This option is not necessary ' - 'if your key is prepended to your cert file.') - - # Service Catalog related options - parser.add_argument('--os-service-type', - default=cliutils.env('OS_SERVICE_TYPE'), - help='Defaults to env[OS_SERVICE_TYPE].') - - parser.add_argument('--os_service_type', - help=argparse.SUPPRESS) - - parser.add_argument('--os-endpoint-type', - default=cliutils.env('OS_ENDPOINT_TYPE'), - help='Defaults to env[OS_ENDPOINT_TYPE].') - - parser.add_argument('--os_endpoint_type', - help=argparse.SUPPRESS) - - parser.add_argument('--os-region-name', - default=cliutils.env('OS_REGION_NAME'), - help='Defaults to env[OS_REGION_NAME].') - - parser.add_argument('--os_region_name', - help=argparse.SUPPRESS) - - # Deprecated options - parser.add_argument('--ca-file', - dest='os_cacert', - help='DEPRECATED! Use --os-cacert.') - - parser.add_argument('--cert-file', - dest='os_cert', - help='DEPRECATED! Use --os-cert.') - - parser.add_argument('--key-file', - dest='os_key', - help='DEPRECATED! Use --os-key.') - def get_base_parser(self): parser = argparse.ArgumentParser( prog='ceilometer', @@ -233,9 +82,8 @@ class CeilometerShell(object): parser.add_argument('--ceilometer_api_version', help=argparse.SUPPRESS) - # FIXME(fabgia): identity related parameters should be passed by the - # Keystone client itself. - self._append_identity_args(parser) + self.auth_plugin.add_opts(parser) + self.auth_plugin.add_common_opts(parser) return parser @@ -291,8 +139,10 @@ class CeilometerShell(object): def parse_args(self, argv): # Parse args once to find version + self.auth_plugin = ceiloclient.AuthPlugin(argv) parser = self.get_base_parser() (options, args) = parser.parse_known_args(argv) + self.auth_plugin.parse_opts(options) self._setup_logging(options.debug) # build available subcommands based on version @@ -331,13 +181,13 @@ class CeilometerShell(object): self.do_bash_completion(args) return 0 - if not (args.os_auth_token and args.ceilometer_url): - if not args.os_username: + if not (self.auth_plugin.opts['auth_token'] and args.ceilometer_url): + if not self.auth_plugin.opts['username']: raise exc.CommandError("You must provide a username via " "either --os-username or via " "env[OS_USERNAME]") - if not args.os_password: + if not self.auth_plugin.opts['password']: raise exc.CommandError("You must provide a password via " "either --os-password or via " "env[OS_PASSWORD]") @@ -354,13 +204,21 @@ class CeilometerShell(object): "--os-user-domain-id or via " "env[OS_USER_DOMAIN_ID]") - if not args.os_auth_url: + if not (self.auth_plugin.opts['tenant_id'] + or self.auth_plugin.opts['tenant_name']): + raise exc.CommandError("You must provide a tenant_id via " + "either --os-tenant-id or via " + "env[OS_TENANT_ID]") + + if not self.auth_plugin.opts['auth_url']: raise exc.CommandError("You must provide an auth url via " "either --os-auth-url or via " "env[OS_AUTH_URL]") - client = ceiloclient.get_client(api_version, **(args.__dict__)) - + client_kwargs = vars(args) + client_kwargs.update(self.auth_plugin.opts) + client_kwargs['auth_plugin'] = self.auth_plugin + client = ceiloclient.Client(api_version, **client_kwargs) # call whatever callback was selected try: args.func(client, args) diff --git a/ceilometerclient/tests/test_client.py b/ceilometerclient/tests/test_client.py index 14aaca6..faed8ee 100644 --- a/ceilometerclient/tests/test_client.py +++ b/ceilometerclient/tests/test_client.py @@ -12,46 +12,63 @@ import types +import mock + from ceilometerclient import client +from ceilometerclient.tests import fakes from ceilometerclient.tests import utils from ceilometerclient.v1 import client as v1client from ceilometerclient.v2 import client as v2client -FAKE_ENV = {'os_username': 'username', - 'os_password': 'password', - 'os_tenant_name': 'tenant_name', - 'os_auth_url': 'http://no.where:5000/', - 'os_auth_token': '1234', - 'ceilometer_url': 'http://no.where'} +FAKE_ENV = {'username': 'username', + 'password': 'password', + 'tenant_name': 'tenant_name', + 'auth_url': 'http://no.where', + 'ceilometer_url': 'http://no.where', + 'auth_plugin': 'fake_auth', + 'token': '1234'} class ClientTest(utils.BaseTestCase): - def create_client(self, api_version=2, exclude=[]): - env = dict((k, v) for k, v in FAKE_ENV.items() if k not in exclude) - return client.get_client(api_version, **env) + def create_client(self, env, api_version=2, endpoint=None, exclude=[]): + env = dict((k, v) for k, v in env.items() + if k not in exclude) + + return client.Client(api_version, endpoint, **env) def setUp(self): super(ClientTest, self).setUp() def test_client_version(self): - c1 = self.create_client(api_version=1) + c1 = self.create_client(env=FAKE_ENV, api_version=1) self.assertIsInstance(c1, v1client.Client) - c2 = self.create_client(api_version=2) + c2 = self.create_client(env=FAKE_ENV, api_version=2) self.assertIsInstance(c2, v2client.Client) - def test_client_auth_token_lambda(self): - FAKE_ENV['os_auth_token'] = lambda: '1234' - self._test_client_auth_token() - - def test_client_auth_token_non_lambda(self): - FAKE_ENV['os_auth_token'] = "1234" - self._test_client_auth_token() + def test_client_auth_lambda(self): + env = FAKE_ENV.copy() + env['token'] = lambda: env['token'] + self.assertIsInstance(env['token'], + types.FunctionType) + c2 = self.create_client(env) + self.assertIsInstance(c2, v2client.Client) - def _test_client_auth_token(self): - c2 = self.create_client() + def test_client_auth_non_lambda(self): + env = FAKE_ENV.copy() + env['token'] = "1234" + self.assertIsInstance(env['token'], str) + c2 = self.create_client(env) self.assertIsInstance(c2, v2client.Client) - self.assertIsInstance(c2.http_client.auth_token, - types.FunctionType) - self.assertEqual('1234', c2.http_client.auth_token()) + + @mock.patch('keystoneclient.v2_0.client', fakes.FakeKeystone) + def test_client_without_auth_plugin(self): + env = FAKE_ENV.copy() + del env['auth_plugin'] + c = self.create_client(env, api_version=2, endpoint='fake_endpoint') + self.assertIsInstance(c.auth_plugin, client.AuthPlugin) + + def test_client_with_auth_plugin(self): + c = self.create_client(FAKE_ENV, api_version=2) + self.assertIsInstance(c.auth_plugin, str) diff --git a/ceilometerclient/tests/test_http.py b/ceilometerclient/tests/test_http.py deleted file mode 100644 index c7a6404..0000000 --- a/ceilometerclient/tests/test_http.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import mock - -from ceilometerclient.common import http -from ceilometerclient.tests import utils - - -class HttpClientTest(utils.BaseTestCase): - url = 'http://localhost' - - def test_url_generation_trailing_slash_in_base_prefix_in_path(self): - client = http.HTTPClient("%s/" % self.url) - url = client._make_connection_url('/v1/resources') - self.assertEqual(url, '/v1/resources') - - def test_url_generation_no_trailing_slash_in_base_prefix_in_path(self): - client = http.HTTPClient(self.url) - url = client._make_connection_url('/v1/resources') - self.assertEqual(url, '/v1/resources') - - def test_url_generation_trailing_slash_in_base_no_prefix_in_path(self): - client = http.HTTPClient("%s/" % self.url) - url = client._make_connection_url('v1/resources') - self.assertEqual(url, '/v1/resources') - - def test_url_generation_no_trailing_slash_in_base_no_prefix_in_path(self): - client = http.HTTPClient(self.url) - url = client._make_connection_url('v1/resources') - self.assertEqual(url, '/v1/resources') - - def test_get_connection(self): - client = http.HTTPClient(self.url) - self.assertIsNotNone(client.get_connection()) - - @mock.patch.object(http.HTTPClient, 'get_connection') - def test_url_generation_with_proxy(self, get_conn): - client = http.HTTPClient(self.url, token=lambda: 'token') - client.proxy_url = "http://localhost:3128/" - conn = mock.MagicMock() - conn.request.side_effect = Exception("stop") - get_conn.return_value = conn - try: - client._http_request('/v1/resources', 'GET') - except Exception: - pass - conn.request.assert_called_once_with('GET', (self.url.rstrip('/') + - '/v1/resources'), - headers=mock.ANY) - - -class HttpsClientTest(HttpClientTest): - url = 'https://localhost' - - -class HttpEndingSlashClientTest(HttpClientTest): - url = 'http://localhost/' diff --git a/ceilometerclient/tests/test_shell.py b/ceilometerclient/tests/test_shell.py index 5f0ffba..cadfcc8 100644 --- a/ceilometerclient/tests/test_shell.py +++ b/ceilometerclient/tests/test_shell.py @@ -48,10 +48,10 @@ class ShellTest(utils.BaseTestCase): super(ShellTest, self).setUp() @mock.patch('sys.stdout', new=six.StringIO()) - @mock.patch.object(ks_session, 'Session') - @mock.patch.object(v1client.http.HTTPClient, 'json_request') - @mock.patch.object(v1client.http.HTTPClient, 'raw_request') - def shell(self, argstr, mock_ksclient, mock_json, mock_raw): + @mock.patch.object(ks_session, 'Session', mock.MagicMock()) + @mock.patch.object(v1client.client.HTTPClient, + 'client_request', mock.MagicMock()) + def shell(self, argstr): try: _shell = ceilometer_shell.CeilometerShell() _shell.main(argstr.split()) @@ -103,7 +103,7 @@ class ShellKeystoneV2Test(ShellTest): mock_ksclient.side_effect = exc.HTTPUnauthorized self.make_env(FAKE_V2_ENV) args = ['--debug', 'event-list'] - self.assertRaises(exc.HTTPUnauthorized, ceilometer_shell.main, args) + self.assertRaises(exc.CommandError, ceilometer_shell.main, args) @mock.patch.object(ks_session, 'Session') def test_dash_d_switch_raises_error(self, mock_ksclient): @@ -132,7 +132,7 @@ class ShellKeystoneV3Test(ShellTest): mock_ksclient.side_effect = exc.HTTPUnauthorized self.make_env(FAKE_V3_ENV) args = ['--debug', 'event-list'] - self.assertRaises(exc.HTTPUnauthorized, ceilometer_shell.main, args) + self.assertRaises(exc.CommandError, ceilometer_shell.main, args) @mock.patch.object(ks_session, 'Session') def test_dash_d_switch_raises_error(self, mock_ksclient): diff --git a/ceilometerclient/tests/utils.py b/ceilometerclient/tests/utils.py index a3e6a38..57bc276 100644 --- a/ceilometerclient/tests/utils.py +++ b/ceilometerclient/tests/utils.py @@ -13,55 +13,12 @@ # License for the specific language governing permissions and limitations # under the License. -import copy - import fixtures -import six import testtools -from ceilometerclient.common import http - class BaseTestCase(testtools.TestCase): def setUp(self): super(BaseTestCase, self).setUp() self.useFixture(fixtures.FakeLogger()) - - -class FakeAPI(object): - def __init__(self, fixtures): - self.fixtures = fixtures - self.calls = [] - - def _request(self, method, url, headers=None, body=None): - call = (method, url, headers or {}, body) - self.calls.append(call) - return self.fixtures[url][method] - - def raw_request(self, *args, **kwargs): - fixture = self._request(*args, **kwargs) - body_iter = http.ResponseBodyIterator(six.StringIO(fixture[1])) - return FakeResponse(fixture[0]), body_iter - - def json_request(self, *args, **kwargs): - fixture = self._request(*args, **kwargs) - return FakeResponse(fixture[0]), fixture[1] - - -class FakeResponse(object): - def __init__(self, headers, body=None, version=None): - """:param headers: dict representing HTTP response headers - :param body: file-like object - """ - self.headers = headers - self.body = body - - def getheaders(self): - return copy.deepcopy(self.headers).items() - - def getheader(self, key, default): - return self.headers.get(key, default) - - def read(self, amt): - return self.body.read(amt) diff --git a/ceilometerclient/tests/v1/test_meters.py b/ceilometerclient/tests/v1/test_meters.py index f97c18b..1c883b7 100644 --- a/ceilometerclient/tests/v1/test_meters.py +++ b/ceilometerclient/tests/v1/test_meters.py @@ -12,7 +12,8 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. - +from ceilometerclient.openstack.common.apiclient import client +from ceilometerclient.openstack.common.apiclient import fake_client from ceilometerclient.tests import utils import ceilometerclient.v1.meters @@ -109,15 +110,16 @@ class MeterManagerTest(utils.BaseTestCase): def setUp(self): super(MeterManagerTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = ceilometerclient.v1.meters.MeterManager(self.api) def test_list_all(self): resources = list(self.mgr.list()) expect = [ - ('GET', '/v1/meters', {}, None), + 'GET', '/v1/meters' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(resources), 2) self.assertEqual(resources[0].resource_id, 'a') self.assertEqual(resources[1].resource_id, 'b') @@ -125,9 +127,9 @@ class MeterManagerTest(utils.BaseTestCase): def test_list_by_source(self): resources = list(self.mgr.list(source='openstack')) expect = [ - ('GET', '/v1/sources/openstack/meters', {}, None), + 'GET', '/v1/sources/openstack/meters' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(resources), 2) self.assertEqual(resources[0].resource_id, 'b') self.assertEqual(resources[1].resource_id, 'q') @@ -135,26 +137,26 @@ class MeterManagerTest(utils.BaseTestCase): def test_list_by_user(self): resources = list(self.mgr.list(user_id='joey')) expect = [ - ('GET', '/v1/users/joey/meters', {}, None), + 'GET', '/v1/users/joey/meters' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(resources), 1) self.assertEqual(resources[0].resource_id, 'b') def test_list_by_project(self): resources = list(self.mgr.list(project_id='dig_the_ditch')) expect = [ - ('GET', '/v1/projects/dig_the_ditch/meters', {}, None), + 'GET', '/v1/projects/dig_the_ditch/meters' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(resources), 1) self.assertEqual(resources[0].resource_id, 'b') def test_list_by_metaquery(self): resources = list(self.mgr.list(metaquery='metadata.zxc_id=foo')) expect = [ - ('GET', '/v1/meters?metadata.zxc_id=foo', {}, None), + 'GET', '/v1/meters?metadata.zxc_id=foo' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(resources), 1) self.assertEqual(resources[0].resource_id, 'b') diff --git a/ceilometerclient/tests/v1/test_projects.py b/ceilometerclient/tests/v1/test_projects.py index a1faaf0..2f34a5c 100644 --- a/ceilometerclient/tests/v1/test_projects.py +++ b/ceilometerclient/tests/v1/test_projects.py @@ -12,7 +12,8 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. - +from ceilometerclient.openstack.common.apiclient import client +from ceilometerclient.openstack.common.apiclient import fake_client from ceilometerclient.tests import utils import ceilometerclient.v1.meters @@ -40,15 +41,16 @@ class ProjectManagerTest(utils.BaseTestCase): def setUp(self): super(ProjectManagerTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = ceilometerclient.v1.meters.ProjectManager(self.api) def test_list_all(self): projects = list(self.mgr.list()) expect = [ - ('GET', '/v1/projects', {}, None), + 'GET', '/v1/projects' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(projects), 2) self.assertEqual(projects[0].project_id, 'a') self.assertEqual(projects[1].project_id, 'b') @@ -56,8 +58,8 @@ class ProjectManagerTest(utils.BaseTestCase): def test_list_by_source(self): projects = list(self.mgr.list(source='source_b')) expect = [ - ('GET', '/v1/sources/source_b/projects', {}, None), + 'GET', '/v1/sources/source_b/projects' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(projects), 1) self.assertEqual(projects[0].project_id, 'b') diff --git a/ceilometerclient/tests/v1/test_resources.py b/ceilometerclient/tests/v1/test_resources.py index 00cea8c..4eac3fe 100644 --- a/ceilometerclient/tests/v1/test_resources.py +++ b/ceilometerclient/tests/v1/test_resources.py @@ -12,7 +12,8 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. - +from ceilometerclient.openstack.common.apiclient import client +from ceilometerclient.openstack.common.apiclient import fake_client from ceilometerclient.tests import utils import ceilometerclient.v1.meters @@ -108,15 +109,16 @@ class ResourceManagerTest(utils.BaseTestCase): def setUp(self): super(ResourceManagerTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = ceilometerclient.v1.meters.ResourceManager(self.api) def test_list_all(self): resources = list(self.mgr.list()) expect = [ - ('GET', '/v1/resources', {}, None), + 'GET', '/v1/resources' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(resources), 2) self.assertEqual(resources[0].resource_id, 'a') self.assertEqual(resources[1].resource_id, 'b') @@ -124,27 +126,27 @@ class ResourceManagerTest(utils.BaseTestCase): def test_list_by_user(self): resources = list(self.mgr.list(user_id='joey')) expect = [ - ('GET', '/v1/users/joey/resources', {}, None), + 'GET', '/v1/users/joey/resources' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(resources), 1) self.assertEqual(resources[0].resource_id, 'b') def test_list_by_metaquery(self): resources = list(self.mgr.list(metaquery='metadata.zxc_id=foo')) expect = [ - ('GET', '/v1/resources?metadata.zxc_id=foo', {}, None), + 'GET', '/v1/resources?metadata.zxc_id=foo' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(resources), 1) self.assertEqual(resources[0].resource_id, 'b') def test_list_by_project(self): resources = list(self.mgr.list(project_id='project_bla')) expect = [ - ('GET', '/v1/projects/project_bla/resources', {}, None), + 'GET', '/v1/projects/project_bla/resources' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(resources), 1) self.assertEqual(resources[0].resource_id, 'a') @@ -152,9 +154,8 @@ class ResourceManagerTest(utils.BaseTestCase): resources = list(self.mgr.list(start_timestamp='now', end_timestamp='now')) expect = [ - ('GET', '/v1/resources?start_timestamp=now&end_timestamp=now', - {}, None), + 'GET', '/v1/resources?start_timestamp=now&end_timestamp=now' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(resources), 1) self.assertEqual(resources[0].resource_id, 'b') diff --git a/ceilometerclient/tests/v1/test_samples.py b/ceilometerclient/tests/v1/test_samples.py index 9e59b46..61f064e 100644 --- a/ceilometerclient/tests/v1/test_samples.py +++ b/ceilometerclient/tests/v1/test_samples.py @@ -12,7 +12,8 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. - +from ceilometerclient.openstack.common.apiclient import client +from ceilometerclient.openstack.common.apiclient import fake_client from ceilometerclient.tests import utils import ceilometerclient.v1.meters @@ -122,24 +123,25 @@ class SampleManagerTest(utils.BaseTestCase): def setUp(self): super(SampleManagerTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = ceilometerclient.v1.meters.SampleManager(self.api) def test_list_all(self): samples = list(self.mgr.list(counter_name=None)) expect = [ - ('GET', '/v1/meters', {}, None), + 'GET', '/v1/meters' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(samples), 0) def test_list_by_source(self): samples = list(self.mgr.list(source='openstack', counter_name='this')) expect = [ - ('GET', '/v1/sources/openstack/meters/this', {}, None), + 'GET', '/v1/sources/openstack/meters/this' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(samples), 1) self.assertEqual(samples[0].resource_id, 'b') @@ -147,9 +149,9 @@ class SampleManagerTest(utils.BaseTestCase): samples = list(self.mgr.list(user_id='freddy', counter_name='balls')) expect = [ - ('GET', '/v1/users/freddy/meters/balls', {}, None), + 'GET', '/v1/users/freddy/meters/balls' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(samples), 1) self.assertEqual(samples[0].project_id, 'melbourne_open') self.assertEqual(samples[0].user_id, 'freddy') @@ -159,9 +161,9 @@ class SampleManagerTest(utils.BaseTestCase): samples = list(self.mgr.list(project_id='dig_the_ditch', counter_name='meters')) expect = [ - ('GET', '/v1/projects/dig_the_ditch/meters/meters', {}, None), + 'GET', '/v1/projects/dig_the_ditch/meters/meters' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(samples), 1) self.assertEqual(samples[0].project_id, 'dig_the_ditch') self.assertEqual(samples[0].volume, 345) @@ -171,9 +173,9 @@ class SampleManagerTest(utils.BaseTestCase): samples = list(self.mgr.list(metaquery='metadata.zxc_id=foo', counter_name='this')) expect = [ - ('GET', '/v1/meters?metadata.zxc_id=foo', {}, None), + 'GET', '/v1/meters?metadata.zxc_id=foo' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(samples), 1) self.assertEqual(samples[0].resource_metadata['zxc_id'], 'foo') @@ -183,12 +185,11 @@ class SampleManagerTest(utils.BaseTestCase): start_timestamp='now', end_timestamp='now')) expect = [ - ('GET', - '/v1/users/freddy/meters/balls?' + - 'start_timestamp=now&end_timestamp=now', - {}, None), + 'GET', + '/v1/users/freddy/meters/balls?' + + 'start_timestamp=now&end_timestamp=now' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(samples), 1) self.assertEqual(samples[0].project_id, 'melbourne_open') self.assertEqual(samples[0].user_id, 'freddy') diff --git a/ceilometerclient/tests/v1/test_users.py b/ceilometerclient/tests/v1/test_users.py index df208c5..541139b 100644 --- a/ceilometerclient/tests/v1/test_users.py +++ b/ceilometerclient/tests/v1/test_users.py @@ -12,7 +12,8 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. - +from ceilometerclient.openstack.common.apiclient import client +from ceilometerclient.openstack.common.apiclient import fake_client from ceilometerclient.tests import utils import ceilometerclient.v1.meters @@ -40,15 +41,16 @@ class UserManagerTest(utils.BaseTestCase): def setUp(self): super(UserManagerTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = ceilometerclient.v1.meters.UserManager(self.api) def test_list_all(self): users = list(self.mgr.list()) expect = [ - ('GET', '/v1/users', {}, None), + 'GET', '/v1/users' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(users), 2) self.assertEqual(users[0].user_id, 'a') self.assertEqual(users[1].user_id, 'b') @@ -56,8 +58,8 @@ class UserManagerTest(utils.BaseTestCase): def test_list_by_source(self): users = list(self.mgr.list(source='source_b')) expect = [ - ('GET', '/v1/sources/source_b/users', {}, None), + 'GET', '/v1/sources/source_b/users' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(users), 1) self.assertEqual(users[0].user_id, 'b') diff --git a/ceilometerclient/tests/v2/test_alarms.py b/ceilometerclient/tests/v2/test_alarms.py index a0e13ac..f963bce 100644 --- a/ceilometerclient/tests/v2/test_alarms.py +++ b/ceilometerclient/tests/v2/test_alarms.py @@ -21,7 +21,8 @@ import six from six.moves import xrange # noqa import testtools -from ceilometerclient.tests import utils +from ceilometerclient.openstack.common.apiclient import client +from ceilometerclient.openstack.common.apiclient import fake_client from ceilometerclient.v2 import alarms AN_ALARM = {u'alarm_actions': [u'http://site:8000/alarm'], @@ -210,11 +211,11 @@ fixtures = { { 'PUT': ( {}, - 'alarm' + {'alarm': 'alarm'} ), 'GET': ( {}, - 'alarm' + {'alarm': 'alarm'} ), }, @@ -254,15 +255,16 @@ class AlarmManagerTest(testtools.TestCase): def setUp(self): super(AlarmManagerTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = alarms.AlarmManager(self.api) def test_list_all(self): alarms = list(self.mgr.list()) expect = [ - ('GET', '/v2/alarms', {}, None), + 'GET', '/v2/alarms' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(alarms), 1) self.assertEqual(alarms[0].alarm_id, 'alarm-id') @@ -272,21 +274,20 @@ class AlarmManagerTest(testtools.TestCase): {"field": "name", "value": "SwiftObjectAlarm"}])) expect = [ - ('GET', - '/v2/alarms?q.field=project_id&q.field=name&q.op=&q.op=' - '&q.type=&q.type=&q.value=project-id&q.value=SwiftObjectAlarm', - {}, None), + 'GET', + '/v2/alarms?q.field=project_id&q.field=name&q.op=&q.op=' + '&q.type=&q.type=&q.value=project-id&q.value=SwiftObjectAlarm', ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(alarms), 1) self.assertEqual(alarms[0].alarm_id, 'alarm-id') def test_get(self): alarm = self.mgr.get(alarm_id='alarm-id') expect = [ - ('GET', '/v2/alarms/alarm-id', {}, None), + 'GET', '/v2/alarms/alarm-id' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertTrue(alarm) self.assertEqual(alarm.alarm_id, 'alarm-id') self.assertEqual(alarm.rule, alarm.threshold_rule) @@ -294,18 +295,21 @@ class AlarmManagerTest(testtools.TestCase): def test_create(self): alarm = self.mgr.create(**CREATE_ALARM) expect = [ - ('POST', '/v2/alarms', {}, CREATE_ALARM), + 'POST', '/v2/alarms' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect, body=CREATE_ALARM) self.assertTrue(alarm) def test_update(self): alarm = self.mgr.update(alarm_id='alarm-id', **UPDATE_ALARM) - expect = [ - ('GET', '/v2/alarms/alarm-id', {}, None), - ('PUT', '/v2/alarms/alarm-id', {}, UPDATED_ALARM), + expect_get = [ + 'GET', '/v2/alarms/alarm-id' + ] + expect_put = [ + 'PUT', '/v2/alarms/alarm-id', UPDATED_ALARM ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect_get, pos=0) + self.http_client.assert_called(*expect_put, pos=1) self.assertTrue(alarm) self.assertEqual(alarm.alarm_id, 'alarm-id') for (key, value) in six.iteritems(UPDATED_ALARM): @@ -313,11 +317,14 @@ class AlarmManagerTest(testtools.TestCase): def test_update_delta(self): alarm = self.mgr.update(alarm_id='alarm-id', **DELTA_ALARM) - expect = [ - ('GET', '/v2/alarms/alarm-id', {}, None), - ('PUT', '/v2/alarms/alarm-id', {}, UPDATED_ALARM), + expect_get = [ + 'GET', '/v2/alarms/alarm-id' ] - self.assertEqual(self.api.calls, expect) + expect_put = [ + 'PUT', '/v2/alarms/alarm-id', UPDATED_ALARM + ] + self.http_client.assert_called(*expect_get, pos=0) + self.http_client.assert_called(*expect_put, pos=1) self.assertTrue(alarm) self.assertEqual(alarm.alarm_id, 'alarm-id') for (key, value) in six.iteritems(UPDATED_ALARM): @@ -326,25 +333,25 @@ class AlarmManagerTest(testtools.TestCase): def test_set_state(self): state = self.mgr.set_state(alarm_id='alarm-id', state='alarm') expect = [ - ('PUT', '/v2/alarms/alarm-id/state', {}, 'alarm'), + 'PUT', '/v2/alarms/alarm-id/state' ] - self.assertEqual(self.api.calls, expect) - self.assertEqual(state, 'alarm') + self.http_client.assert_called(*expect, body='alarm') + self.assertEqual(state, {'alarm': 'alarm'}) def test_get_state(self): state = self.mgr.get_state(alarm_id='alarm-id') expect = [ - ('GET', '/v2/alarms/alarm-id/state', {}, None), + 'GET', '/v2/alarms/alarm-id/state' ] - self.assertEqual(self.api.calls, expect) - self.assertEqual(state, 'alarm') + self.http_client.assert_called(*expect) + self.assertEqual(state, {'alarm': 'alarm'}) def test_delete(self): deleted = self.mgr.delete(alarm_id='victim-id') expect = [ - ('DELETE', '/v2/alarms/victim-id', {}, None), + 'DELETE', '/v2/alarms/victim-id' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertIsNone(deleted) def test_get_from_alarm_class(self): @@ -352,10 +359,10 @@ class AlarmManagerTest(testtools.TestCase): self.assertTrue(alarm) alarm.get() expect = [ - ('GET', '/v2/alarms/alarm-id', {}, None), - ('GET', '/v2/alarms/alarm-id', {}, None) + 'GET', '/v2/alarms/alarm-id' ] - self.assertEqual(expect, self.api.calls) + self.http_client.assert_called(*expect, pos=0) + self.http_client.assert_called(*expect, pos=1) self.assertEqual('alarm-id', alarm.alarm_id) self.assertEqual(alarm.threshold_rule, alarm.rule) @@ -363,28 +370,34 @@ class AlarmManagerTest(testtools.TestCase): alarm = self.mgr.get(alarm_id='alarm-id') self.assertTrue(alarm) state = alarm.get_state() - expect = [ - ('GET', '/v2/alarms/alarm-id', {}, None), - ('GET', '/v2/alarms/alarm-id/state', {}, None) + expect_get_1 = [ + 'GET', '/v2/alarms/alarm-id' ] - self.assertEqual(expect, self.api.calls) + expect_get_2 = [ + 'GET', '/v2/alarms/alarm-id/state' + ] + self.http_client.assert_called(*expect_get_1, pos=0) + self.http_client.assert_called(*expect_get_2, pos=1) self.assertEqual('alarm', state) def test_delete_from_alarm_class(self): alarm = self.mgr.get(alarm_id='alarm-id') self.assertTrue(alarm) deleted = alarm.delete() - expect = [ - ('GET', '/v2/alarms/alarm-id', {}, None), - ('DELETE', '/v2/alarms/alarm-id', {}, None) + expect_get = [ + 'GET', '/v2/alarms/alarm-id' ] - self.assertEqual(expect, self.api.calls) + expect_delete = [ + 'DELETE', '/v2/alarms/alarm-id' + ] + self.http_client.assert_called(*expect_get, pos=0) + self.http_client.assert_called(*expect_delete, pos=1) self.assertIsNone(deleted) def _do_test_get_history(self, q, url): history = self.mgr.get_history(q=q, alarm_id='alarm-id') - expect = [('GET', url, {}, None)] - self.assertEqual(self.api.calls, expect) + expect = ['GET', url] + self.http_client.assert_called(*expect) for i in xrange(len(history)): change = history[i] self.assertIsInstance(change, alarms.AlarmChange) @@ -406,15 +419,17 @@ class AlarmLegacyManagerTest(testtools.TestCase): def setUp(self): super(AlarmLegacyManagerTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = alarms.AlarmManager(self.api) def test_create(self): alarm = self.mgr.create(**CREATE_LEGACY_ALARM) expect = [ - ('POST', '/v2/alarms', {}, CREATE_ALARM_WITHOUT_TC), + 'POST', '/v2/alarms', CREATE_ALARM_WITHOUT_TC, ] - self.assertEqual(self.api.calls, expect) + + self.http_client.assert_called(*expect) self.assertTrue(alarm) def test_create_counter_name(self): @@ -424,18 +439,17 @@ class AlarmLegacyManagerTest(testtools.TestCase): del create['meter_name'] alarm = self.mgr.create(**create) expect = [ - ('POST', '/v2/alarms', {}, CREATE_ALARM_WITHOUT_TC), + 'POST', '/v2/alarms', CREATE_ALARM_WITHOUT_TC, ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertTrue(alarm) def test_update(self): alarm = self.mgr.update(alarm_id='alarm-id', **DELTA_LEGACY_ALARM) - expect = [ - ('GET', '/v2/alarms/alarm-id', {}, None), - ('PUT', '/v2/alarms/alarm-id', {}, UPDATED_ALARM), + expect_put = [ + 'PUT', '/v2/alarms/alarm-id', UPDATED_ALARM ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect_put) self.assertTrue(alarm) self.assertEqual(alarm.alarm_id, 'alarm-id') for (key, value) in six.iteritems(UPDATED_ALARM): @@ -447,11 +461,10 @@ class AlarmLegacyManagerTest(testtools.TestCase): updated['counter_name'] = UPDATED_LEGACY_ALARM['meter_name'] del updated['meter_name'] alarm = self.mgr.update(alarm_id='alarm-id', **updated) - expect = [ - ('GET', '/v2/alarms/alarm-id', {}, None), - ('PUT', '/v2/alarms/alarm-id', {}, UPDATED_ALARM), + expect_put = [ + 'PUT', '/v2/alarms/alarm-id', UPDATED_ALARM ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect_put) self.assertTrue(alarm) self.assertEqual(alarm.alarm_id, 'alarm-id') for (key, value) in six.iteritems(UPDATED_ALARM): @@ -462,7 +475,8 @@ class AlarmTimeConstraintTest(testtools.TestCase): def setUp(self): super(AlarmTimeConstraintTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = alarms.AlarmManager(self.api) def test_add_new(self): @@ -471,26 +485,37 @@ class AlarmTimeConstraintTest(testtools.TestCase): duration=500) kwargs = dict(time_constraints=[new_constraint]) self.mgr.update(alarm_id='alarm-id', **kwargs) - actual = self.api.calls[1][3]['time_constraints'] - expected = AN_ALARM[u'time_constraints'] + [new_constraint] - self.assertEqual(expected, actual) + body = copy.deepcopy(AN_ALARM) + body[u'time_constraints'] = \ + AN_ALARM[u'time_constraints'] + [new_constraint] + expect = [ + 'PUT', '/v2/alarms/alarm-id', body + ] + self.http_client.assert_called(*expect) def test_update_existing(self): updated_constraint = dict(name='cons2', duration=500) kwargs = dict(time_constraints=[updated_constraint]) self.mgr.update(alarm_id='alarm-id', **kwargs) - actual = self.api.calls[1][3]['time_constraints'] - expected = [AN_ALARM[u'time_constraints'][0], dict(name='cons2', - description='desc2', - start='0 23 * * *', - duration=500, - timezone='')] - self.assertEqual(expected, actual) + body = copy.deepcopy(AN_ALARM) + body[u'time_constraints'][1] = dict(name='cons2', + description='desc2', + start='0 23 * * *', + duration=500, + timezone='') + + expect = [ + 'PUT', '/v2/alarms/alarm-id', body + ] + self.http_client.assert_called(*expect) def test_remove(self): kwargs = dict(remove_time_constraints=['cons2']) self.mgr.update(alarm_id='alarm-id', **kwargs) - actual = self.api.calls[1][3]['time_constraints'] - expected = [AN_ALARM[u'time_constraints'][0]] - self.assertEqual(expected, actual) + body = copy.deepcopy(AN_ALARM) + body[u'time_constraints'] = AN_ALARM[u'time_constraints'][:1] + expect = [ + 'PUT', '/v2/alarms/alarm-id', body + ] + self.http_client.assert_called(*expect) diff --git a/ceilometerclient/tests/v2/test_event_types.py b/ceilometerclient/tests/v2/test_event_types.py index 08a25a4..8d5e4a0 100644 --- a/ceilometerclient/tests/v2/test_event_types.py +++ b/ceilometerclient/tests/v2/test_event_types.py @@ -12,6 +12,9 @@ # License for the specific language governing permissions and limitations # under the License. + +from ceilometerclient.openstack.common.apiclient import client +from ceilometerclient.openstack.common.apiclient import fake_client from ceilometerclient.tests import utils import ceilometerclient.v2.event_types @@ -30,15 +33,16 @@ class EventTypesManagerTest(utils.BaseTestCase): def setUp(self): super(EventTypesManagerTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = ceilometerclient.v2.event_types.EventTypeManager(self.api) def test_list(self): event_types = list(self.mgr.list()) expect = [ - ('GET', '/v2/event_types/', {}, None), + 'GET', '/v2/event_types/' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(event_types), 4) self.assertEqual(event_types[0].event_type, "Foo") self.assertEqual(event_types[1].event_type, "Bar") diff --git a/ceilometerclient/tests/v2/test_events.py b/ceilometerclient/tests/v2/test_events.py index 4935d8b..acf27d4 100644 --- a/ceilometerclient/tests/v2/test_events.py +++ b/ceilometerclient/tests/v2/test_events.py @@ -11,7 +11,8 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. - +from ceilometerclient.openstack.common.apiclient import client +from ceilometerclient.openstack.common.apiclient import fake_client from ceilometerclient.tests import utils import ceilometerclient.v2.events @@ -124,15 +125,16 @@ class EventManagerTest(utils.BaseTestCase): def setUp(self): super(EventManagerTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = ceilometerclient.v2.events.EventManager(self.api) def test_list_all(self): events = list(self.mgr.list()) expect = [ - ('GET', '/v2/events', {}, None), + 'GET', '/v2/events' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(events), 3) self.assertEqual(events[0].event_type, 'Foo') self.assertEqual(events[1].event_type, 'Foo') @@ -141,9 +143,9 @@ class EventManagerTest(utils.BaseTestCase): def test_list_one(self): event = self.mgr.get(2) expect = [ - ('GET', '/v2/events/2', {}, None), + 'GET', '/v2/events/2' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertTrue(event) self.assertEqual(event.event_type, 'Foo') @@ -152,11 +154,10 @@ class EventManagerTest(utils.BaseTestCase): "value": "localhost", "type": "string"}])) expect = [ - ('GET', '/v2/events?q.field=hostname&q.op=&q.type=string' - '&q.value=localhost', - {}, None), + 'GET', '/v2/events?q.field=hostname&q.op=&q.type=string' + '&q.value=localhost' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(events), 2) self.assertEqual(events[0].event_type, 'Foo') @@ -164,11 +165,10 @@ class EventManagerTest(utils.BaseTestCase): events = list(self.mgr.list(q=[{"field": "hostname", "value": "foreignhost"}])) expect = [ - ('GET', '/v2/events?q.field=hostname&q.op=' - '&q.type=&q.value=foreignhost', - {}, None), + 'GET', '/v2/events?q.field=hostname&q.op=' + '&q.type=&q.value=foreignhost' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(events), 2) self.assertEqual(events[0].event_type, 'Foo') @@ -180,11 +180,10 @@ class EventManagerTest(utils.BaseTestCase): "type": "integer"}])) expect = [ - ('GET', '/v2/events?q.field=hostname&q.field=num_cpus&q.op=&q.op=' - '&q.type=&q.type=integer&q.value=localhost&q.value=5', - {}, None), + 'GET', '/v2/events?q.field=hostname&q.field=num_cpus&q.op=&q.op=' + '&q.type=&q.type=integer&q.value=localhost&q.value=5' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(events), 1) def test_get_from_event_class(self): @@ -192,8 +191,8 @@ class EventManagerTest(utils.BaseTestCase): self.assertTrue(event) event.get() expect = [ - ('GET', '/v2/events/2', {}, None), - ('GET', '/v2/events/2', {}, None), + 'GET', '/v2/events/2' ] - self.assertEqual(expect, self.api.calls) + self.http_client.assert_called(*expect, pos=0) + self.http_client.assert_called(*expect, pos=1) self.assertEqual('Foo', event.event_type) diff --git a/ceilometerclient/tests/v2/test_options.py b/ceilometerclient/tests/v2/test_options.py index e9dee54..6318d5c 100644 --- a/ceilometerclient/tests/v2/test_options.py +++ b/ceilometerclient/tests/v2/test_options.py @@ -10,7 +10,6 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. - from ceilometerclient.tests import utils from ceilometerclient.v2 import options diff --git a/ceilometerclient/tests/v2/test_query_alarm_history.py b/ceilometerclient/tests/v2/test_query_alarm_history.py index 2a6cfb4..60d437d 100644 --- a/ceilometerclient/tests/v2/test_query_alarm_history.py +++ b/ceilometerclient/tests/v2/test_query_alarm_history.py @@ -14,6 +14,8 @@ # License for the specific language governing permissions and limitations # under the License. +from ceilometerclient.openstack.common.apiclient import client +from ceilometerclient.openstack.common.apiclient import fake_client from ceilometerclient.tests import utils from ceilometerclient.v2 import query @@ -49,13 +51,16 @@ class QueryAlarmsManagerTest(utils.BaseTestCase): def setUp(self): super(QueryAlarmsManagerTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = query.QueryAlarmHistoryManager(self.api) def test_query(self): alarm_history = self.mgr.query(**QUERY) expect = [ - ('POST', '/v2/query/alarms/history', {}, QUERY), + + 'POST', '/v2/query/alarms/history', QUERY, + ] - self.assertEqual(expect, self.api.calls) + self.http_client.assert_called(*expect) self.assertEqual(1, len(alarm_history)) diff --git a/ceilometerclient/tests/v2/test_query_alarms.py b/ceilometerclient/tests/v2/test_query_alarms.py index 199caa7..7e7a108 100644 --- a/ceilometerclient/tests/v2/test_query_alarms.py +++ b/ceilometerclient/tests/v2/test_query_alarms.py @@ -14,6 +14,8 @@ # License for the specific language governing permissions and limitations # under the License. +from ceilometerclient.openstack.common.apiclient import client +from ceilometerclient.openstack.common.apiclient import fake_client from ceilometerclient.tests import utils from ceilometerclient.v2 import query @@ -60,13 +62,15 @@ class QueryAlarmsManagerTest(utils.BaseTestCase): def setUp(self): super(QueryAlarmsManagerTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = query.QueryAlarmsManager(self.api) def test_query(self): alarms = self.mgr.query(**QUERY) expect = [ - ('POST', '/v2/query/alarms', {}, QUERY), + 'POST', '/v2/query/alarms', QUERY, ] - self.assertEqual(expect, self.api.calls) + + self.http_client.assert_called(*expect) self.assertEqual(1, len(alarms)) diff --git a/ceilometerclient/tests/v2/test_query_samples.py b/ceilometerclient/tests/v2/test_query_samples.py index b12a508..7f6e7d9 100644 --- a/ceilometerclient/tests/v2/test_query_samples.py +++ b/ceilometerclient/tests/v2/test_query_samples.py @@ -14,6 +14,8 @@ # License for the specific language governing permissions and limitations # under the License. +from ceilometerclient.openstack.common.apiclient import client +from ceilometerclient.openstack.common.apiclient import fake_client from ceilometerclient.tests import utils from ceilometerclient.v2 import query @@ -53,13 +55,15 @@ class QuerySamplesManagerTest(utils.BaseTestCase): def setUp(self): super(QuerySamplesManagerTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = query.QuerySamplesManager(self.api) def test_query(self): samples = self.mgr.query(**QUERY) expect = [ - ('POST', '/v2/query/samples', {}, QUERY), + + 'POST', '/v2/query/samples', QUERY, ] - self.assertEqual(expect, self.api.calls) + self.http_client.assert_called(*expect) self.assertEqual(1, len(samples)) diff --git a/ceilometerclient/tests/v2/test_resources.py b/ceilometerclient/tests/v2/test_resources.py index d62ce40..5d53737 100644 --- a/ceilometerclient/tests/v2/test_resources.py +++ b/ceilometerclient/tests/v2/test_resources.py @@ -12,7 +12,8 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. - +from ceilometerclient.openstack.common.apiclient import client +from ceilometerclient.openstack.common.apiclient import fake_client from ceilometerclient.tests import utils import ceilometerclient.v2.resources @@ -70,15 +71,16 @@ class ResourceManagerTest(utils.BaseTestCase): def setUp(self): super(ResourceManagerTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = ceilometerclient.v2.resources.ResourceManager(self.api) def test_list_all(self): resources = list(self.mgr.list()) expect = [ - ('GET', '/v2/resources', {}, None), + 'GET', '/v2/resources' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(resources), 2) self.assertEqual(resources[0].resource_id, 'a') self.assertEqual(resources[1].resource_id, 'b') @@ -86,9 +88,9 @@ class ResourceManagerTest(utils.BaseTestCase): def test_list_one(self): resource = self.mgr.get(resource_id='a') expect = [ - ('GET', '/v2/resources/a', {}, None), + 'GET', '/v2/resources/a' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertTrue(resource) self.assertEqual(resource.resource_id, 'a') @@ -97,11 +99,10 @@ class ResourceManagerTest(utils.BaseTestCase): "value": "a"}, ])) expect = [ - ('GET', '/v2/resources?q.field=resource_id&q.op=' - '&q.type=&q.value=a', - {}, None), + 'GET', '/v2/resources?q.field=resource_id&q.op=' + '&q.type=&q.value=a' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(resources), 1) self.assertEqual(resources[0].resource_id, 'a') @@ -110,8 +111,8 @@ class ResourceManagerTest(utils.BaseTestCase): self.assertTrue(resource) resource.get() expect = [ - ('GET', '/v2/resources/a', {}, None), - ('GET', '/v2/resources/a', {}, None), + 'GET', '/v2/resources/a' ] - self.assertEqual(expect, self.api.calls) + self.http_client.assert_called(*expect, pos=0) + self.http_client.assert_called(*expect, pos=1) self.assertEqual('a', resource.resource_id) diff --git a/ceilometerclient/tests/v2/test_samples.py b/ceilometerclient/tests/v2/test_samples.py index 7b0b878..46b4cff 100644 --- a/ceilometerclient/tests/v2/test_samples.py +++ b/ceilometerclient/tests/v2/test_samples.py @@ -15,6 +15,8 @@ import copy +from ceilometerclient.openstack.common.apiclient import client +from ceilometerclient.openstack.common.apiclient import fake_client from ceilometerclient.tests import utils import ceilometerclient.v2.samples @@ -71,15 +73,16 @@ class SampleManagerTest(utils.BaseTestCase): def setUp(self): super(SampleManagerTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = ceilometerclient.v2.samples.SampleManager(self.api) def test_list_by_meter_name(self): samples = list(self.mgr.list(meter_name='instance')) expect = [ - ('GET', '/v2/meters/instance', {}, None), + 'GET', '/v2/meters/instance' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(samples), 1) self.assertEqual(samples[0].resource_id, 'resource-id') @@ -91,20 +94,20 @@ class SampleManagerTest(utils.BaseTestCase): {"field": "source", "value": "bar"}, ])) - expect = [('GET', '%s?%s' % (base_url, args), {}, None)] - self.assertEqual(self.api.calls, expect) + expect = ['GET', '%s?%s' % (base_url, args)] + self.http_client.assert_called(*expect) self.assertEqual(len(samples), 0) def test_create(self): sample = self.mgr.create(**CREATE_SAMPLE) expect = [ - ('POST', '/v2/meters/instance', {}, [CREATE_SAMPLE]), + 'POST', '/v2/meters/instance' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect, body=CREATE_SAMPLE) self.assertTrue(sample) def test_limit(self): samples = list(self.mgr.list(meter_name='instance', limit=1)) - expect = [('GET', '/v2/meters/instance?limit=1', {}, None)] - self.assertEqual(self.api.calls, expect) + expect = ['GET', '/v2/meters/instance?limit=1'] + self.http_client.assert_called(*expect) self.assertEqual(len(samples), 1) diff --git a/ceilometerclient/tests/v2/test_statistics.py b/ceilometerclient/tests/v2/test_statistics.py index ed3465c..65f633e 100644 --- a/ceilometerclient/tests/v2/test_statistics.py +++ b/ceilometerclient/tests/v2/test_statistics.py @@ -12,7 +12,8 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. - +from ceilometerclient.openstack.common.apiclient import client +from ceilometerclient.openstack.common.apiclient import fake_client from ceilometerclient.tests import utils import ceilometerclient.v2.statistics @@ -114,15 +115,16 @@ class StatisticsManagerTest(utils.BaseTestCase): def setUp(self): super(StatisticsManagerTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = ceilometerclient.v2.statistics.StatisticsManager(self.api) def test_list_by_meter_name(self): stats = list(self.mgr.list(meter_name='instance')) expect = [ - ('GET', '/v2/meters/instance/statistics', {}, None), + 'GET', '/v2/meters/instance/statistics' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(stats), 1) self.assertEqual(stats[0].count, 135) @@ -135,10 +137,9 @@ class StatisticsManagerTest(utils.BaseTestCase): "value": "bar"}, ])) expect = [ - ('GET', - '%s?%s' % (base_url, qry), {}, None), + 'GET', '%s?%s' % (base_url, qry) ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(stats), 1) self.assertEqual(stats[0].count, 135) @@ -152,10 +153,9 @@ class StatisticsManagerTest(utils.BaseTestCase): ], period=60)) expect = [ - ('GET', - '%s?%s%s' % (base_url, qry, period), {}, None), + 'GET', '%s?%s%s' % (base_url, qry, period) ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(stats), 1) self.assertEqual(stats[0].count, 135) @@ -169,10 +169,10 @@ class StatisticsManagerTest(utils.BaseTestCase): ], groupby=['resource_id'])) expect = [ - ('GET', - '%s?%s%s' % (base_url, qry, groupby), {}, None), + 'GET', + '%s?%s%s' % (base_url, qry, groupby) ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(stats), 2) self.assertEqual(stats[0].count, 135) self.assertEqual(stats[1].count, 12) @@ -189,10 +189,10 @@ class StatisticsManagerTest(utils.BaseTestCase): ], groupby='resource_id')) expect = [ - ('GET', - '%s?%s%s' % (base_url, qry, groupby), {}, None), + 'GET', + '%s?%s%s' % (base_url, qry, groupby) ] - self.assertEqual(expect, self.api.calls) + self.http_client.assert_called(*expect) self.assertEqual(2, len(stats)) self.assertEqual(135, stats[0].count) self.assertEqual(12, stats[1].count) @@ -212,10 +212,10 @@ class StatisticsManagerTest(utils.BaseTestCase): stats = list(self.mgr.list(meter_name='instance', aggregates=aggregates)) expect = [ - ('GET', - '%s?%s' % (base_url, aggregate_query), {}, None), + 'GET', + '%s?%s' % (base_url, aggregate_query) ] - self.assertEqual(expect, self.api.calls) + self.http_client.assert_called(*expect) self.assertEqual(1, len(stats)) self.assertEqual(2, stats[0].count) self.assertEqual(2.0, stats[0].aggregate.get('count')) diff --git a/ceilometerclient/tests/v2/test_trait_descriptions.py b/ceilometerclient/tests/v2/test_trait_descriptions.py index 0b273f0..7913124 100644 --- a/ceilometerclient/tests/v2/test_trait_descriptions.py +++ b/ceilometerclient/tests/v2/test_trait_descriptions.py @@ -11,7 +11,8 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. - +from ceilometerclient.openstack.common.apiclient import client +from ceilometerclient.openstack.common.apiclient import fake_client from ceilometerclient.tests import utils import ceilometerclient.v2.trait_descriptions @@ -34,16 +35,17 @@ class TraitDescriptionManagerTest(utils.BaseTestCase): def setUp(self): super(TraitDescriptionManagerTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = (ceilometerclient.v2.trait_descriptions. TraitDescriptionManager(self.api)) def test_list(self): trait_descriptions = list(self.mgr.list('Foo')) expect = [ - ('GET', '/v2/event_types/Foo/traits', {}, None), + 'GET', '/v2/event_types/Foo/traits' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(trait_descriptions), 3) for i, vals in enumerate([('trait_1', 'string'), ('trait_2', 'integer'), diff --git a/ceilometerclient/tests/v2/test_traits.py b/ceilometerclient/tests/v2/test_traits.py index f8239a0..1d7dde0 100644 --- a/ceilometerclient/tests/v2/test_traits.py +++ b/ceilometerclient/tests/v2/test_traits.py @@ -11,7 +11,8 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. - +from ceilometerclient.openstack.common.apiclient import client +from ceilometerclient.openstack.common.apiclient import fake_client from ceilometerclient.tests import utils import ceilometerclient.v2.traits @@ -37,15 +38,16 @@ class TraitManagerTest(utils.BaseTestCase): def setUp(self): super(TraitManagerTest, self).setUp() - self.api = utils.FakeAPI(fixtures) + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) self.mgr = ceilometerclient.v2.traits.TraitManager(self.api) def test_list(self): traits = list(self.mgr.list('Foo', 'trait_1')) expect = [ - ('GET', '/v2/event_types/Foo/traits/trait_1', {}, None), + 'GET', '/v2/event_types/Foo/traits/trait_1' ] - self.assertEqual(self.api.calls, expect) + self.http_client.assert_called(*expect) self.assertEqual(len(traits), 2) for i, vals in enumerate([('trait_1', 'datetime', diff --git a/ceilometerclient/v1/client.py b/ceilometerclient/v1/client.py index 89a5b44..e8827e2 100644 --- a/ceilometerclient/v1/client.py +++ b/ceilometerclient/v1/client.py @@ -13,7 +13,9 @@ # License for the specific language governing permissions and limitations # under the License. -from ceilometerclient.common import http + +from ceilometerclient import client as ceiloclient +from ceilometerclient.openstack.common.apiclient import client from ceilometerclient.v1 import meters @@ -29,7 +31,24 @@ class Client(object): def __init__(self, *args, **kwargs): """Initialize a new client for the Ceilometer v1 API.""" - self.http_client = http.HTTPClient(*args, **kwargs) + self.auth_plugin = kwargs.get('auth_plugin') \ + or ceiloclient.get_auth_plugin(*args, **kwargs) + self.client = client.HTTPClient( + auth_plugin=self.auth_plugin, + region_name=kwargs.get('region_name'), + endpoint_type=kwargs.get('endpoint_type'), + original_ip=kwargs.get('original_ip'), + verify=kwargs.get('verify'), + cert=kwargs.get('cacert'), + timeout=kwargs.get('timeout'), + timings=kwargs.get('timings'), + keyring_saver=kwargs.get('keyring_saver'), + debug=kwargs.get('debug'), + user_agent=kwargs.get('user_agent'), + http=kwargs.get('http') + ) + + self.http_client = client.BaseClient(self.client) self.meters = meters.MeterManager(self.http_client) self.samples = meters.SampleManager(self.http_client) self.users = meters.UserManager(self.http_client) diff --git a/ceilometerclient/v2/alarms.py b/ceilometerclient/v2/alarms.py index 7c46fb2..341cbb7 100644 --- a/ceilometerclient/v2/alarms.py +++ b/ceilometerclient/v2/alarms.py @@ -57,7 +57,8 @@ class Alarm(base.Resource): return self.manager.delete(self.alarm_id) def get_state(self): - return self.manager.get_state(self.alarm_id) + state = self.manager.get_state(self.alarm_id) + return state.get('alarm') class AlarmChange(base.Resource): @@ -167,14 +168,12 @@ class AlarmManager(base.Manager): return self._delete(self._path(alarm_id)) def set_state(self, alarm_id, state): - resp, body = self.api.json_request('PUT', - "%s/state" % self._path(alarm_id), - body=state) + body = self.api.put("%s/state" % self._path(alarm_id), + json=state).json() return body def get_state(self, alarm_id): - resp, body = self.api.json_request('GET', - "%s/state" % self._path(alarm_id)) + body = self.api.get("%s/state" % self._path(alarm_id)).json() return body def get_history(self, alarm_id, q=None): diff --git a/ceilometerclient/v2/client.py b/ceilometerclient/v2/client.py index ba5ca43..95be8f5 100644 --- a/ceilometerclient/v2/client.py +++ b/ceilometerclient/v2/client.py @@ -15,7 +15,8 @@ # License for the specific language governing permissions and limitations # under the License. -from ceilometerclient.common import http +from ceilometerclient import client as ceiloclient +from ceilometerclient.openstack.common.apiclient import client from ceilometerclient.v2 import alarms from ceilometerclient.v2 import event_types from ceilometerclient.v2 import events @@ -39,8 +40,26 @@ class Client(object): """ def __init__(self, *args, **kwargs): + """Initialize a new client for the Ceilometer v2 API.""" - self.http_client = http.HTTPClient(*args, **kwargs) + self.auth_plugin = kwargs.get('auth_plugin') \ + or ceiloclient.get_auth_plugin(*args, **kwargs) + self.client = client.HTTPClient( + auth_plugin=self.auth_plugin, + region_name=kwargs.get('region_name'), + endpoint_type=kwargs.get('endpoint_type'), + original_ip=kwargs.get('original_ip'), + verify=kwargs.get('verify'), + cert=kwargs.get('cacert'), + timeout=kwargs.get('timeout'), + timings=kwargs.get('timings'), + keyring_saver=kwargs.get('keyring_saver'), + debug=kwargs.get('debug'), + user_agent=kwargs.get('user_agent'), + http=kwargs.get('http') + ) + + self.http_client = client.BaseClient(self.client) self.meters = meters.MeterManager(self.http_client) self.samples = samples.SampleManager(self.http_client) self.statistics = statistics.StatisticsManager(self.http_client) @@ -51,6 +70,7 @@ class Client(object): self.traits = traits.TraitManager(self.http_client) self.trait_descriptions = trait_descriptions.\ TraitDescriptionManager(self.http_client) + self.query_samples = query.QuerySamplesManager( self.http_client) self.query_alarms = query.QueryAlarmsManager( diff --git a/ceilometerclient/v2/query.py b/ceilometerclient/v2/query.py index 85d2f6c..a11a56d 100644 --- a/ceilometerclient/v2/query.py +++ b/ceilometerclient/v2/query.py @@ -33,9 +33,9 @@ class QueryManager(base.Manager): query["limit"] = limit url = '/v2/query%s' % self.path_suffix - resp, body = self.api.json_request('POST', - url, - body=query) + + body = self.api.post(url, json=query).json() + if body: return [self.resource_class(self, b) for b in body] else: diff --git a/ceilometerclient/v2/samples.py b/ceilometerclient/v2/samples.py index cd0c3c2..b0ff3b5 100644 --- a/ceilometerclient/v2/samples.py +++ b/ceilometerclient/v2/samples.py @@ -47,8 +47,6 @@ class SampleManager(base.Manager): new = dict((key, value) for (key, value) in kwargs.items() if key in CREATION_ATTRIBUTES) url = self._path(counter_name=kwargs['counter_name']) - resp, body = self.api.json_request('POST', - url, - body=[new]) + body = self.api.post(url, json=new).json() if body: return [Sample(self, b) for b in body] diff --git a/requirements.txt b/requirements.txt index 6123791..1c2e9bb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,4 @@ iso8601>=0.1.9 PrettyTable>=0.7,<0.8 python-keystoneclient>=0.9.0 six>=1.7.0 +stevedore>=0.14 |