From 151b9a6c5c4048b16ff05a7e8973cd91b49b5361 Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Thu, 7 May 2015 11:29:03 +0200 Subject: [PATCH] Add support for the hashmap threshold API Change-Id: I970c8844c3af41c7cc3d99ce09e4f69ec337f888 --- cloudkittyclient/tests/v1/test_hashmap.py | 88 +++++++++++ .../v1/rating/hashmap/__init__.py | 20 +++ cloudkittyclient/v1/rating/hashmap/client.py | 1 + cloudkittyclient/v1/rating/hashmap/shell.py | 149 ++++++++++++++++++ 4 files changed, 258 insertions(+) diff --git a/cloudkittyclient/tests/v1/test_hashmap.py b/cloudkittyclient/tests/v1/test_hashmap.py index d4c2072..a2e9f47 100644 --- a/cloudkittyclient/tests/v1/test_hashmap.py +++ b/cloudkittyclient/tests/v1/test_hashmap.py @@ -207,6 +207,38 @@ fixtures = { {}, ), }, + # a threshold + ('/v1/rating/module_config/hashmap/thresholds/' + '1f136864-be73-481f-b9be-4fbda2496f72'): { + 'GET': ( + {}, + { + 'threshold_id': '1f136864-be73-481f-b9be-4fbda2496f72', + 'service_id': '1329d62f-bd1c-4a88-a75a-07545e41e8d7', + 'field_id': 'c7c28d87-5103-4a05-af7f-e4d0891cb7fc', + 'group_id': None, + 'level': 30, + 'cost': 5.98, + 'map_type': 'flat', + }, + ), + 'PUT': ( + {}, + { + 'threshold_id': '1f136864-be73-481f-b9be-4fbda2496f72', + 'service_id': '1329d62f-bd1c-4a88-a75a-07545e41e8d7', + 'field_id': 'c7c28d87-5103-4a05-af7f-e4d0891cb7fc', + 'group_id': None, + 'level': 30, + 'cost': 5.99, + 'type': 'flat', + }, + ), + 'DELETE': ( + {}, + {}, + ), + }, } @@ -423,3 +455,59 @@ class GroupTest(utils.BaseTestCase): '?recursive=True') ] self.http_client.assert_called(*expect) + + +class ThresholdManagerTest(utils.BaseTestCase): + + def setUp(self): + super(ThresholdManagerTest, self).setUp() + self.http_client = fake_client.FakeHTTPClient(fixtures=fixtures) + self.api = client.BaseClient(self.http_client) + self.mgr = hashmap.ThresholdManager(self.api) + + def test_get_a_threshold(self): + resource = self.mgr.get( + threshold_id='1f136864-be73-481f-b9be-4fbda2496f72' + ) + expect = [ + 'GET', ('/v1/rating/module_config/hashmap/thresholds/' + '1f136864-be73-481f-b9be-4fbda2496f72') + ] + self.http_client.assert_called(*expect) + self.assertEqual(resource.threshold_id, + '1f136864-be73-481f-b9be-4fbda2496f72') + self.assertEqual( + resource.service_id, + '1329d62f-bd1c-4a88-a75a-07545e41e8d7' + ) + self.assertEqual( + resource.field_id, + 'c7c28d87-5103-4a05-af7f-e4d0891cb7fc' + ) + self.assertEqual(resource.level, 30) + self.assertEqual(resource.cost, 5.98) + + def test_update_a_threshold(self): + resource = self.mgr.get( + threshold_id='1f136864-be73-481f-b9be-4fbda2496f72' + ) + resource.cost = 5.99 + self.mgr.update(**resource.dirty_fields) + expect = [ + 'PUT', ('/v1/rating/module_config/hashmap/thresholds/' + '1f136864-be73-481f-b9be-4fbda2496f72'), + {u'threshold_id': u'1f136864-be73-481f-b9be-4fbda2496f72', + u'cost': 5.99, u'map_type': u'flat', + u'service_id': u'1329d62f-bd1c-4a88-a75a-07545e41e8d7', + u'field_id': u'c7c28d87-5103-4a05-af7f-e4d0891cb7fc', + u'level': 30} + ] + self.http_client.assert_called(*expect) + + def test_delete_a_threshold(self): + self.mgr.delete(threshold_id='1f136864-be73-481f-b9be-4fbda2496f72') + expect = [ + 'DELETE', ('/v1/rating/module_config/hashmap/thresholds/' + '1f136864-be73-481f-b9be-4fbda2496f72') + ] + self.http_client.assert_called(*expect) diff --git a/cloudkittyclient/v1/rating/hashmap/__init__.py b/cloudkittyclient/v1/rating/hashmap/__init__.py index af6ee8d..063f381 100644 --- a/cloudkittyclient/v1/rating/hashmap/__init__.py +++ b/cloudkittyclient/v1/rating/hashmap/__init__.py @@ -110,3 +110,23 @@ class GroupManager(base.CrudManager): if recursive: url += "?recursive=True" return self._delete(url) + + +class Threshold(base.Resource): + key = 'threshold' + + def __repr__(self): + return "" % self._info + + +class ThresholdManager(base.CrudManager): + resource_class = Threshold + base_url = '/v1/rating/module_config/hashmap' + key = 'threshold' + collection_key = 'thresholds' + + def group(self, threshold_id): + url = ('%(base_url)s/thresholds/%(threshold_id)s/group' % + {'base_url': self.base_url, 'threshold_id': threshold_id}) + out = self._get(url) + return out diff --git a/cloudkittyclient/v1/rating/hashmap/client.py b/cloudkittyclient/v1/rating/hashmap/client.py index 5192ddc..e236605 100644 --- a/cloudkittyclient/v1/rating/hashmap/client.py +++ b/cloudkittyclient/v1/rating/hashmap/client.py @@ -29,3 +29,4 @@ class Client(object): self.fields = hashmap.FieldManager(self.http_client) self.mappings = hashmap.MappingManager(self.http_client) self.groups = hashmap.GroupManager(self.http_client) + self.thresholds = hashmap.ThresholdManager(self.http_client) diff --git a/cloudkittyclient/v1/rating/hashmap/shell.py b/cloudkittyclient/v1/rating/hashmap/shell.py index 5d16849..4dff81e 100644 --- a/cloudkittyclient/v1/rating/hashmap/shell.py +++ b/cloudkittyclient/v1/rating/hashmap/shell.py @@ -13,9 +13,15 @@ # License for the specific language governing permissions and limitations # under the License. +import functools + +from oslo.utils import strutils + from cloudkittyclient.common import utils from cloudkittyclient import exc +_bool_strict = functools.partial(strutils.bool_from_string, strict=True) + @utils.arg('-n', '--name', help='Service name', @@ -263,3 +269,146 @@ def do_hashmap_group_delete(cc, args={}): recursive=args.recursive) except exc.HTTPNotFound: raise exc.CommandError('Group not found: %s' % args.group_id) + + +@utils.arg('-l', '--level', + help='Threshold level', + required=True) +@utils.arg('-c', '--cost', + help='Threshold cost', + required=True) +@utils.arg('-m', '--map-type', + help='Threshold type (flat, rate)', + required=False) +@utils.arg('-s', '--service-id', + help='Service id', + required=False) +@utils.arg('-f', '--field-id', + help='Field id', + required=False) +@utils.arg('-g', '--group-id', + help='Group id', + required=False) +def do_hashmap_threshold_create(cc, args={}): + """Create a ampping.""" + arg_to_field_mapping = { + 'level': 'level', + 'cost': 'cost', + 'map_type': 'map_type', + 'service_id': 'service_id', + 'field_id': 'field_id', + 'group_id': 'group_id', + } + fields = {} + for k, v in vars(args).items(): + if k in arg_to_field_mapping: + if v is not None: + fields[arg_to_field_mapping.get(k, k)] = v + out = cc.hashmap.thresholds.create(**fields) + utils.print_dict(out.to_dict()) + + +@utils.arg('-t', '--threshold-id', + help='Threshold id', + required=True) +@utils.arg('-l', '--level', + help='Threshold level', + required=False) +@utils.arg('-c', '--cost', + help='Threshold cost', + required=False) +@utils.arg('-m', '--map-type', + help='Threshold type (flat, rate)', + required=False) +@utils.arg('-g', '--group-id', + help='Group id', + required=False) +def do_hashmap_threshold_update(cc, args={}): + """Update a threshold.""" + arg_to_field_mapping = { + 'threshold_id': 'threshold_id', + 'cost': 'cost', + 'level': 'level', + 'map_type': 'map_type', + 'group_id': 'group_id', + } + try: + threshold = cc.hashmap.thresholds.get(threshold_id=args.threshold_id) + except exc.HTTPNotFound: + raise exc.CommandError('Modules not found: %s' % args.counter_name) + for k, v in vars(args).items(): + if k in arg_to_field_mapping: + if v is not None: + setattr(threshold, k, v) + cc.hashmap.thresholds.update(**threshold.dirty_fields) + + +@utils.arg('-s', '--service-id', + help='Service id', + required=False) +@utils.arg('-f', '--field-id', + help='Field id', + required=False) +@utils.arg('-g', '--group-id', + help='Group id', + required=False) +@utils.arg('--no-group', + type=_bool_strict, metavar='{True,False}', + help='If True, list only orhpaned thresholds', + required=False) +def do_hashmap_threshold_list(cc, args={}): + """List thresholds.""" + if (args.group_id is None and + args.service_id is None and args.field_id is None): + raise exc.CommandError("Provide either group-id, service-id or " + "field-id") + try: + thresholds = cc.hashmap.thresholds.list(service_id=args.service_id, + field_id=args.field_id, + group_id=args.group_id, + no_group=args.no_group) + except exc.HTTPNotFound: + raise exc.CommandError('Threshold not found: %s' % args.counter_name) + else: + field_labels = ['Threshold id', 'Level', 'Cost', + 'Type', 'Field id', + 'Service id', 'Group id'] + fields = ['threshold_id', 'level', 'cost', + 'map_type', 'field_id', + 'service_id', 'group_id'] + utils.print_list(thresholds, fields, field_labels, sortby=0) + + +@utils.arg('-t', '--threshold-id', + help='Threshold uuid', + required=True) +def do_hashmap_threshold_delete(cc, args={}): + """Delete a threshold.""" + try: + cc.hashmap.thresholds.delete(threshold_id=args.threshold_id) + except exc.HTTPNotFound: + raise exc.CommandError('Threshold not found: %s' % args.threshold_id) + + +@utils.arg('-t', '--threshold-id', + help='Threshold uuid', + required=True) +def do_hashmap_threshold_get(cc, args={}): + """Get a threshold.""" + try: + threshold = cc.hashmap.thresholds.get(threshold_id=args.threshold_id) + except exc.HTTPNotFound: + raise exc.CommandError('Threshold not found: %s' % args.threshold_id) + utils.print_dict(threshold.to_dict()) + + +@utils.arg('-t', '--threshold-id', + help='Threshold uuid', + required=True) +def do_hashmap_threshold_group(cc, args={}): + """Get a threshold group.""" + try: + threshold = cc.hashmap.thresholds.group(threshold_id=args.threshold_id) + except exc.HTTPNotFound: + raise exc.CommandError('Threshold not found: %s' % args.threshold_id) + utils.print_dict(threshold.to_dict())