From ff9bde4001bdf47cfca1d2ad39b64a90d8b27c34 Mon Sep 17 00:00:00 2001 From: Anderson Mesquita Date: Wed, 8 Jan 2014 18:47:34 -0600 Subject: [PATCH] Add filter option to stack-list Add ability to use filters on stack-list by passing a ``--filters`` options to the command line. This option can appear multiple times or be used once with several key=value filters separated by semicolons. If the same key appears more than once, both will be taken into account when sending the request to the API. e.g.: The option: ``--filters status=COMPLETE;status=FAILED`` Will issue the call: ``/stacks?status=COMPLETE&status=FAILED`` Closes-Bug: 1268816 Change-Id: I553d6b5e3ceebdb24dcd4e4c8e409a4375d72333 --- heatclient/common/utils.py | 8 +++++++- heatclient/tests/test_shell.py | 10 ++++++++-- heatclient/tests/test_utils.py | 8 ++++++++ heatclient/v1/shell.py | 9 ++++++++- heatclient/v1/stacks.py | 12 +++++------- 5 files changed, 36 insertions(+), 11 deletions(-) diff --git a/heatclient/common/utils.py b/heatclient/common/utils.py index b5f4bda3..fbd4d8da 100644 --- a/heatclient/common/utils.py +++ b/heatclient/common/utils.py @@ -162,7 +162,13 @@ def format_parameters(params): 'Use the key=value format') raise exc.CommandError(msg) - parameters[n] = v + if n not in parameters: + parameters[n] = v + else: + if not isinstance(parameters[n], list): + parameters[n] = [parameters[n]] + parameters[n].append(v) + return parameters diff --git a/heatclient/tests/test_shell.py b/heatclient/tests/test_shell.py index 45bc1627..c5aa49b8 100644 --- a/heatclient/tests/test_shell.py +++ b/heatclient/tests/test_shell.py @@ -379,12 +379,18 @@ class ShellTestUserPass(ShellBase): def test_stack_list_with_args(self): self._script_keystone_client() - expected_url = '/stacks?marker=fake_id&limit=2' + expected_url = ('/stacks?' + 'status=COMPLETE&status=FAILED' + '&marker=fake_id&limit=2') fakes.script_heat_list(expected_url) self.m.ReplayAll() - list_text = self.shell('stack-list --limit 2 --marker fake_id') + list_text = self.shell('stack-list' + ' --limit 2' + ' --marker fake_id' + ' --filters=status=COMPLETE' + ' --filters=status=FAILED') required = [ 'teststack', diff --git a/heatclient/tests/test_utils.py b/heatclient/tests/test_utils.py index 192bd426..70395093 100644 --- a/heatclient/tests/test_utils.py +++ b/heatclient/tests/test_utils.py @@ -66,6 +66,14 @@ class shellTest(testtools.TestCase): 'ww7a4oAO;NQ/fD==', 'UpstreamDNS': '8.8.8.8'}, p) + def test_format_parameters_multiple_values_per_pamaters(self): + p = utils.format_parameters([ + 'status=COMPLETE', + 'status=FAILED']) + self.assertIn('status', p) + self.assertIn('COMPLETE', p['status']) + self.assertIn('FAILED', p['status']) + def test_format_parameter_bad_parameter(self): params = ['KeyName=heat_key;UpstreamDNS8.8.8.8'] ex = self.assertRaises(exc.CommandError, diff --git a/heatclient/v1/shell.py b/heatclient/v1/shell.py index e759ab96..41bbff55 100644 --- a/heatclient/v1/shell.py +++ b/heatclient/v1/shell.py @@ -234,6 +234,11 @@ def do_list(hc): do_stack_list(hc) +@utils.arg('-f', '--filters', metavar='', + help='Filter parameters to apply on returned stacks. ' + 'This can be specified multiple times, or once with parameters ' + 'separated by semicolon.', + action='append') @utils.arg('-l', '--limit', metavar='', help='Limit the number of stacks returned') @utils.arg('-m', '--marker', metavar='', @@ -243,7 +248,9 @@ def do_stack_list(hc, args=None): kwargs = {} if args: kwargs = {'limit': args.limit, - 'marker': args.marker} + 'marker': args.marker, + 'filters': utils.format_parameters(args.filters)} + stacks = hc.stacks.list(**kwargs) fields = ['id', 'stack_name', 'stack_status', 'creation_time'] utils.print_list(stacks, fields, sortby=3) diff --git a/heatclient/v1/stacks.py b/heatclient/v1/stacks.py index d6d27372..e1843641 100644 --- a/heatclient/v1/stacks.py +++ b/heatclient/v1/stacks.py @@ -77,7 +77,7 @@ class StackManager(base.BaseManager): def paginate(params): '''Paginate stacks, even if more than API limit.''' current_limit = int(params.get('limit') or 0) - url = '/stacks?%s' % urlutils.urlencode(params) + url = '/stacks?%s' % urlutils.urlencode(params, True) stacks = self._list(url, 'stacks') for stack in stacks: yield stack @@ -91,16 +91,14 @@ class StackManager(base.BaseManager): yield stack params = {} + if 'filters' in kwargs: + filters = kwargs.pop('filters') + params.update(filters) + for key, value in kwargs.iteritems(): if value: params[key] = value - filters = kwargs.get('filters', {}) - properties = filters.pop('properties', {}) - for key, value in properties.items(): - params['property-%s' % key] = value - params.update(filters) - return paginate(params) def create(self, **kwargs):