diff options
29 files changed, 149 insertions, 62 deletions
diff --git a/ceilometerclient/common/http.py b/ceilometerclient/common/http.py index d83745b..f440abe 100644 --- a/ceilometerclient/common/http.py +++ b/ceilometerclient/common/http.py @@ -31,7 +31,7 @@ except ImportError: import six from six.moves import http_client as httplib # noqa -from six.moves.urllib import parse +from six.moves import urllib from ceilometerclient import exc @@ -51,7 +51,7 @@ class HTTPClient(object): @staticmethod def get_connection_params(endpoint, **kwargs): - parts = parse.urlparse(endpoint) + parts = urllib.parse.urlparse(endpoint) _args = (parts.hostname, parts.port, parts.path) _kwargs = {'timeout': (float(kwargs.get('timeout')) @@ -75,7 +75,7 @@ class HTTPClient(object): _class = self.connection_params[0] try: if self.proxy_url: - proxy_parts = parse.urlparse(self.proxy_url) + proxy_parts = urllib.parse.urlparse(self.proxy_url) return _class(proxy_parts.hostname, proxy_parts.port, **self.connection_params[2]) else: @@ -212,7 +212,7 @@ class HTTPClient(object): return self._http_request(url, method, **kwargs) def get_proxy_url(self): - scheme = parse.urlparse(self.endpoint).scheme + scheme = urllib.parse.urlparse(self.endpoint).scheme if scheme == 'https': return os.environ.get('https_proxy') elif scheme == 'http': diff --git a/ceilometerclient/common/utils.py b/ceilometerclient/common/utils.py index 658cf7b..a6682f9 100644 --- a/ceilometerclient/common/utils.py +++ b/ceilometerclient/common/utils.py @@ -14,12 +14,13 @@ # under the License. from __future__ import print_function -import six + import sys import textwrap import uuid import prettytable +import six from ceilometerclient import exc from ceilometerclient.openstack.common import cliutils diff --git a/ceilometerclient/tests/test_exc.py b/ceilometerclient/tests/test_exc.py index 3cdfb85..9c8f146 100644 --- a/ceilometerclient/tests/test_exc.py +++ b/ceilometerclient/tests/test_exc.py @@ -16,7 +16,6 @@ import json from ceilometerclient import exc - from ceilometerclient.tests import utils HTTPEXCEPTIONS = {'HTTPBadRequest': exc.HTTPBadRequest, diff --git a/ceilometerclient/tests/test_shell.py b/ceilometerclient/tests/test_shell.py index a2dbc4e..be6e115 100644 --- a/ceilometerclient/tests/test_shell.py +++ b/ceilometerclient/tests/test_shell.py @@ -11,15 +11,14 @@ # under the License. import re -import six import sys import fixtures +from keystoneclient.v2_0 import client as ksclient import mock +import six from testtools import matchers -from keystoneclient.v2_0 import client as ksclient - from ceilometerclient import exc from ceilometerclient import shell as ceilometer_shell from ceilometerclient.tests import utils diff --git a/ceilometerclient/tests/test_utils.py b/ceilometerclient/tests/test_utils.py index 8840fb8..ccace89 100644 --- a/ceilometerclient/tests/test_utils.py +++ b/ceilometerclient/tests/test_utils.py @@ -13,8 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. - import itertools + import mock import six diff --git a/ceilometerclient/tests/utils.py b/ceilometerclient/tests/utils.py index dae7ea2..a3e6a38 100644 --- a/ceilometerclient/tests/utils.py +++ b/ceilometerclient/tests/utils.py @@ -14,6 +14,7 @@ # under the License. import copy + import fixtures import six import testtools diff --git a/ceilometerclient/tests/v2/test_alarms.py b/ceilometerclient/tests/v2/test_alarms.py index bfa7f85..ad6a811 100644 --- a/ceilometerclient/tests/v2/test_alarms.py +++ b/ceilometerclient/tests/v2/test_alarms.py @@ -1,6 +1,5 @@ -# -*- encoding: utf-8 -*- # -# Copyright © 2013 Red Hat, Inc +# Copyright 2013 Red Hat, Inc # # Author: Eoghan Glynn <eglynn@redhat.com> # @@ -202,6 +201,10 @@ fixtures = { {}, UPDATED_ALARM, ), + 'DELETE': ( + {}, + None, + ), }, '/v2/alarms/alarm-id/state': { @@ -344,6 +347,40 @@ class AlarmManagerTest(testtools.TestCase): self.assertEqual(self.api.calls, expect) self.assertTrue(deleted is None) + def test_get_from_alarm_class(self): + alarm = self.mgr.get(alarm_id='alarm-id') + self.assertTrue(alarm) + alarm.get() + expect = [ + ('GET', '/v2/alarms/alarm-id', {}, None), + ('GET', '/v2/alarms/alarm-id', {}, None) + ] + self.assertEqual(expect, self.api.calls) + self.assertEqual('alarm-id', alarm.alarm_id) + self.assertEqual(alarm.threshold_rule, alarm.rule) + + def test_get_state_from_alarm_class(self): + 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) + ] + self.assertEqual(expect, self.api.calls) + 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) + ] + self.assertEqual(expect, self.api.calls) + self.assertTrue(deleted is None) + def _do_test_get_history(self, q, url): history = self.mgr.get_history(q=q, alarm_id='alarm-id') expect = [('GET', url, {}, None)] diff --git a/ceilometerclient/tests/v2/test_event_types.py b/ceilometerclient/tests/v2/test_event_types.py index 85c59ec..08a25a4 100644 --- a/ceilometerclient/tests/v2/test_event_types.py +++ b/ceilometerclient/tests/v2/test_event_types.py @@ -1,4 +1,3 @@ -# -*- encoding: utf-8 -*- # Copyright 2014 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/ceilometerclient/tests/v2/test_events.py b/ceilometerclient/tests/v2/test_events.py index ee90a14..4935d8b 100644 --- a/ceilometerclient/tests/v2/test_events.py +++ b/ceilometerclient/tests/v2/test_events.py @@ -1,4 +1,3 @@ -# -*- encoding: utf-8 -*- # Copyright 2014 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -23,22 +22,22 @@ fixtures = { {}, [ { + 'message_id': '1', 'event_type': 'Foo', 'generated': '1970-01-01T00:00:00', - 'traits': {'trait_A': 'abc', - 'message_id': '1'}, + 'traits': {'trait_A': 'abc'}, }, { + 'message_id': '2', 'event_type': 'Foo', 'generated': '1970-01-01T00:00:00', - 'traits': {'trait_A': 'def', - 'message_id': '2'}, + 'traits': {'trait_A': 'def'}, }, { + 'message_id': '3', 'event_type': 'Bar', 'generated': '1970-01-01T00:00:00', - 'traits': {'trait_B': 'bartrait', - 'message_id': '3'}, + 'traits': {'trait_B': 'bartrait'}, }, ] ), @@ -49,18 +48,18 @@ fixtures = { {}, [ { + 'message_id': '1', 'event_type': 'Foo', 'generated': '1970-01-01T00:00:00', 'traits': {'trait_A': 'abc', - 'hostname': 'localhost', - 'message_id': '1'}, + 'hostname': 'localhost'}, }, { + 'message_id': '2', 'event_type': 'Foo', 'generated': '1970-01-01T00:00:00', 'traits': {'trait_A': 'def', - 'hostname': 'localhost', - 'message_id': '2'}, + 'hostname': 'localhost'}, } ] ), @@ -71,18 +70,18 @@ fixtures = { {}, [ { + 'message_id': '1', 'event_type': 'Foo', 'generated': '1970-01-01T00:00:00', 'traits': {'trait_A': 'abc', - 'hostname': 'foreignhost', - 'message_id': '1'}, + 'hostname': 'foreignhost'}, }, { + 'message_id': '2', 'event_type': 'Foo', 'generated': '1970-01-01T00:00:00', 'traits': {'trait_A': 'def', - 'hostname': 'foreignhost', - 'message_id': '2'}, + 'hostname': 'foreignhost'}, } ] ), @@ -94,12 +93,12 @@ fixtures = { {}, [ { + 'message_id': '1', 'event_type': 'Bar', 'generated': '1970-01-01T00:00:00', 'traits': {'trait_A': 'abc', 'hostname': 'localhost', - 'num_cpus': '5', - 'message_id': '1'}, + 'num_cpus': '5'}, }, ] ), @@ -110,10 +109,10 @@ fixtures = { 'GET': ( {}, { + 'message_id': '2', 'event_type': 'Foo', 'generated': '1970-01-01T00:00:00', 'traits': {'trait_A': 'def', - 'message_id': '2', 'intTrait': '42'}, } ), @@ -187,3 +186,14 @@ class EventManagerTest(utils.BaseTestCase): ] self.assertEqual(self.api.calls, expect) self.assertEqual(len(events), 1) + + def test_get_from_event_class(self): + event = self.mgr.get(2) + self.assertTrue(event) + event.get() + expect = [ + ('GET', '/v2/events/2', {}, None), + ('GET', '/v2/events/2', {}, None), + ] + self.assertEqual(expect, self.api.calls) + self.assertEqual('Foo', event.event_type) diff --git a/ceilometerclient/tests/v2/test_resources.py b/ceilometerclient/tests/v2/test_resources.py index 13a29fe..d62ce40 100644 --- a/ceilometerclient/tests/v2/test_resources.py +++ b/ceilometerclient/tests/v2/test_resources.py @@ -104,3 +104,14 @@ class ResourceManagerTest(utils.BaseTestCase): self.assertEqual(self.api.calls, expect) self.assertEqual(len(resources), 1) self.assertEqual(resources[0].resource_id, 'a') + + def test_get_from_resource_class(self): + resource = self.mgr.get(resource_id='a') + self.assertTrue(resource) + resource.get() + expect = [ + ('GET', '/v2/resources/a', {}, None), + ('GET', '/v2/resources/a', {}, None), + ] + self.assertEqual(expect, self.api.calls) + self.assertEqual('a', resource.resource_id) diff --git a/ceilometerclient/tests/v2/test_shell.py b/ceilometerclient/tests/v2/test_shell.py index 730382b..69e6a50 100644 --- a/ceilometerclient/tests/v2/test_shell.py +++ b/ceilometerclient/tests/v2/test_shell.py @@ -15,11 +15,11 @@ # License for the specific language governing permissions and limitations # under the License. -import mock import re -import six import sys +import mock +import six from testtools import matchers from ceilometerclient import shell as base_shell diff --git a/ceilometerclient/tests/v2/test_trait_descriptions.py b/ceilometerclient/tests/v2/test_trait_descriptions.py index 4c84f3c..0b273f0 100644 --- a/ceilometerclient/tests/v2/test_trait_descriptions.py +++ b/ceilometerclient/tests/v2/test_trait_descriptions.py @@ -1,4 +1,3 @@ -# -*- encoding: utf-8 -*- # Copyright 2014 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/ceilometerclient/tests/v2/test_traits.py b/ceilometerclient/tests/v2/test_traits.py index 697acf1..f8239a0 100644 --- a/ceilometerclient/tests/v2/test_traits.py +++ b/ceilometerclient/tests/v2/test_traits.py @@ -1,4 +1,3 @@ -# -*- encoding: utf-8 -*- # Copyright 2014 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/ceilometerclient/v1/shell.py b/ceilometerclient/v1/shell.py index 1edfc2d..efb807f 100644 --- a/ceilometerclient/v1/shell.py +++ b/ceilometerclient/v1/shell.py @@ -68,7 +68,7 @@ def do_sample_list(cc, args): @utils.arg('-p', '--project_id', metavar='<PROJECT_ID>', help='ID of the project to show samples for.') def do_meter_list(cc, args={}): - '''List the user's meter''' + '''List the user's meter.''' fields = {'resource_id': args.resource_id, 'user_id': args.user_id, 'project_id': args.project_id, diff --git a/ceilometerclient/v2/alarms.py b/ceilometerclient/v2/alarms.py index 837904c..7c46fb2 100644 --- a/ceilometerclient/v2/alarms.py +++ b/ceilometerclient/v2/alarms.py @@ -1,6 +1,5 @@ -# -*- encoding: utf-8 -*- # -# Copyright © 2013 Red Hat, Inc +# Copyright 2013 Red Hat, Inc # # Author: Eoghan Glynn <eglynn@redhat.com> # @@ -20,6 +19,7 @@ import warnings from ceilometerclient.common import base from ceilometerclient.common import utils +from ceilometerclient import exc from ceilometerclient.v2 import options @@ -49,8 +49,16 @@ class Alarm(base.Resource): # that look like the Alarm storage object if k == 'rule': k = '%s_rule' % self.type + if k == 'id': + return self.alarm_id return super(Alarm, self).__getattr__(k) + def delete(self): + return self.manager.delete(self.alarm_id) + + def get_state(self): + return self.manager.get_state(self.alarm_id) + class AlarmChange(base.Resource): def __repr__(self): @@ -75,6 +83,13 @@ class AlarmManager(base.Manager): return self._list(self._path(alarm_id), expect_single=True)[0] except IndexError: return None + except exc.HTTPNotFound: + # When we try to get deleted alarm HTTPNotFound occurs + # or when alarm doesn't exists this exception don't must + # go deeper because cleanUp() (method which remove all + # created things like instance, alarm, etc.) at scenario + # tests doesn't know how to process it + return None @classmethod def _compat_legacy_alarm_kwargs(cls, kwargs, create=False): diff --git a/ceilometerclient/v2/event_types.py b/ceilometerclient/v2/event_types.py index 036eb3e..631f0b4 100644 --- a/ceilometerclient/v2/event_types.py +++ b/ceilometerclient/v2/event_types.py @@ -1,4 +1,3 @@ -# -*- encoding: utf-8 -*- # Copyright 2014 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/ceilometerclient/v2/events.py b/ceilometerclient/v2/events.py index 0e245bb..32380d6 100644 --- a/ceilometerclient/v2/events.py +++ b/ceilometerclient/v2/events.py @@ -1,4 +1,3 @@ -# -*- encoding: utf-8 -*- # Copyright 2014 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -21,6 +20,11 @@ class Event(base.Resource): def __repr__(self): return "<Event %s>" % self._info + def __getattr__(self, k): + if k == 'id': + return self.message_id + return super(Event, self).__getattr__(k) + class EventManager(base.Manager): resource_class = Event diff --git a/ceilometerclient/v2/meters.py b/ceilometerclient/v2/meters.py index baa7cbd..938854d 100644 --- a/ceilometerclient/v2/meters.py +++ b/ceilometerclient/v2/meters.py @@ -1,6 +1,5 @@ -# -*- encoding: utf-8 -*- # -# Copyright © 2013 Red Hat, Inc +# Copyright 2013 Red Hat, Inc # # 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 diff --git a/ceilometerclient/v2/options.py b/ceilometerclient/v2/options.py index 775ac40..ee85c42 100644 --- a/ceilometerclient/v2/options.py +++ b/ceilometerclient/v2/options.py @@ -13,7 +13,7 @@ import re -from six.moves.urllib import parse +from six.moves import urllib OP_LOOKUP = {'!=': 'ne', '>=': 'ge', @@ -54,7 +54,7 @@ def build_url(path, q, params=None): # Transform the dict to a sequence of two-element tuples in fixed # order, then the encoded string will be consistent in Python 2&3. new_qparams = sorted(query_params.items(), key=lambda x: x[0]) - path += "?" + parse.urlencode(new_qparams, doseq=True) + path += "?" + urllib.parse.urlencode(new_qparams, doseq=True) if params: for p in params: diff --git a/ceilometerclient/v2/query.py b/ceilometerclient/v2/query.py index a615e2f..85d2f6c 100644 --- a/ceilometerclient/v2/query.py +++ b/ceilometerclient/v2/query.py @@ -23,7 +23,7 @@ from ceilometerclient.v2 import samples class QueryManager(base.Manager): path_suffix = None - def query(self, filter, orderby, limit): + def query(self, filter=None, orderby=None, limit=None): query = {} if filter: query["filter"] = filter diff --git a/ceilometerclient/v2/resources.py b/ceilometerclient/v2/resources.py index 59adb95..99e6fd5 100644 --- a/ceilometerclient/v2/resources.py +++ b/ceilometerclient/v2/resources.py @@ -1,6 +1,5 @@ -# -*- encoding: utf-8 -*- # -# Copyright © 2013 Red Hat, Inc +# Copyright 2013 Red Hat, Inc # # 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 @@ -22,6 +21,11 @@ class Resource(base.Resource): def __repr__(self): return "<Resource %s>" % self._info + def __getattr__(self, k): + if k == 'id': + return self.resource_id + return super(Resource, self).__getattr__(k) + class ResourceManager(base.Manager): resource_class = Resource diff --git a/ceilometerclient/v2/shell.py b/ceilometerclient/v2/shell.py index 3807c7b..b13ab20 100644 --- a/ceilometerclient/v2/shell.py +++ b/ceilometerclient/v2/shell.py @@ -1,6 +1,5 @@ -# -*- encoding: utf-8 -*- # -# Copyright © 2013 Red Hat, Inc +# Copyright 2013 Red Hat, Inc # Copyright Ericsson AB 2014. All rights reserved # # Authors: Angus Salkeld <asalkeld@redhat.com> @@ -21,6 +20,7 @@ import functools import json + import six from ceilometerclient.common import utils @@ -144,7 +144,8 @@ def do_sample_list(cc, args): @utils.arg('--sample-volume', metavar='<SAMPLE_VOLUME>', required=True, help='The sample volume.') @utils.arg('--resource-metadata', metavar='<RESOURCE_METADATA>', - help='Resource metadata.') + help='Resource metadata. Provided value should be a set of ' + 'key-value pairs e.g. {"key":"value"}.') @utils.arg('--timestamp', metavar='<TIMESTAMP>', help='The sample timestamp.') def do_sample_create(cc, args={}): @@ -321,9 +322,8 @@ def _display_alarm(alarm): help='ID of the alarm to show.') def do_alarm_show(cc, args={}): '''Show an alarm.''' - try: - alarm = cc.alarms.get(args.alarm_id) - except exc.HTTPNotFound: + alarm = cc.alarms.get(args.alarm_id) + if alarm is None: raise exc.CommandError('Alarm not found: %s' % args.alarm_id) else: _display_alarm(alarm) @@ -650,9 +650,13 @@ def do_alarm_history(cc, args={}): raise exc.CommandError('Alarm not found: %s' % args.alarm_id) field_labels = ['Type', 'Timestamp', 'Detail'] fields = ['type', 'timestamp', 'detail'] + # We're using sortby=None as the alarm history returned from the Ceilometer + # is already sorted in the "the newer state is the earlier one in the + # list". If we'll pass any field as a sortby param, it'll be sorted in the + # ASC way by the PrettyTable utils.print_list(history, fields, field_labels, formatters={'detail': alarm_change_detail_formatter}, - sortby=1) + sortby=None) @utils.arg('-q', '--query', metavar='<QUERY>', diff --git a/ceilometerclient/v2/trait_descriptions.py b/ceilometerclient/v2/trait_descriptions.py index b6a0372..418647a 100644 --- a/ceilometerclient/v2/trait_descriptions.py +++ b/ceilometerclient/v2/trait_descriptions.py @@ -1,4 +1,3 @@ -# -*- encoding: utf-8 -*- # Copyright 2013 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/ceilometerclient/v2/traits.py b/ceilometerclient/v2/traits.py index fbeb22a..55f8960 100644 --- a/ceilometerclient/v2/traits.py +++ b/ceilometerclient/v2/traits.py @@ -1,4 +1,3 @@ -# -*- encoding: utf-8 -*- # Copyright 2013 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/doc/source/conf.py b/doc/source/conf.py index d91350b..0d030d1 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # project = 'python-ceilometerclient' diff --git a/requirements.txt b/requirements.txt index 253bf42..6123791 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,5 +2,5 @@ pbr>=0.6,!=0.7,<1.0 argparse iso8601>=0.1.9 PrettyTable>=0.7,<0.8 -python-keystoneclient>=0.7.0 -six>=1.6.0 +python-keystoneclient>=0.9.0 +six>=1.7.0 @@ -17,6 +17,14 @@ # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT import setuptools +# In python < 2.7.4, a lazy loading of package `pbr` will break +# setuptools if some other modules registered functions in `atexit`. +# solution from: http://bugs.python.org/issue15881#msg170215 +try: + import multiprocessing # noqa +except ImportError: + pass + setuptools.setup( setup_requires=['pbr'], pbr=True) diff --git a/test-requirements.txt b/test-requirements.txt index 6d04138..bb5e7e6 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,10 +1,10 @@ # Hacking already pins down pep8, pyflakes and flake8 -hacking>=0.8.0,<0.9 +hacking>=0.9.1,<0.10 coverage>=3.6 discover fixtures>=0.3.14 mock>=1.0 python-subunit>=0.0.18 -sphinx>=1.1.2,<1.2 +sphinx>=1.1.2,!=1.2.0,<1.3 testrepository>=0.0.18 testtools>=0.9.34 @@ -25,6 +25,8 @@ commands = python setup.py testr --coverage --testr-args='{posargs}' commands = {posargs} [flake8] -ignore = None +# H405 multi line docstring summary not separated with an empty line +# H904 Wrap long lines in parentheses instead of a backslash +ignore = H405,H904 show-source = True exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,tools |