From 8b71c7f6575b5ec3413f7e0bbb00cf5431f67f82 Mon Sep 17 00:00:00 2001 From: dixiaoli Date: Sat, 27 Feb 2016 14:38:16 +0800 Subject: [PATCH] Add OSC plugin for openstack cluster receiver list This change implements the "openstack cluster receiver list" command Based on the existing senlin command: senlin receiver-list Change-Id: I149d64c0a76bf7697fe55ac4123681203219c7a5 Blueprint: senlin-support-python-openstackclient --- senlinclient/osc/v1/receiver.py | 103 +++++++++++++ .../tests/unit/osc/v1/test_receiver.py | 141 ++++++++++++++++++ setup.cfg | 1 + 3 files changed, 245 insertions(+) create mode 100644 senlinclient/osc/v1/receiver.py create mode 100644 senlinclient/tests/unit/osc/v1/test_receiver.py diff --git a/senlinclient/osc/v1/receiver.py b/senlinclient/osc/v1/receiver.py new file mode 100644 index 0000000..e0e1581 --- /dev/null +++ b/senlinclient/osc/v1/receiver.py @@ -0,0 +1,103 @@ +# 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. + +"""Clustering v1 receiver action implementations""" + +import logging + +from cliff import lister +from openstackclient.common import utils + +from senlinclient.common.i18n import _ +from senlinclient.common import utils as senlin_utils + + +class ListReceiver(lister.Lister): + """List receivers that meet the criteria.""" + + log = logging.getLogger(__name__ + ".ListReceiver") + + def get_parser(self, prog_name): + parser = super(ListReceiver, self).get_parser(prog_name) + parser.add_argument( + '--filters', + metavar='', + help=_("Filter parameters to apply on returned receivers. " + "This can be specified multiple times, or once with " + "parameters separated by a semicolon. The valid filter " + "keys are: ['name', 'type', 'action', 'cluster_id']"), + action='append' + ) + parser.add_argument( + '--limit', + metavar='', + help=_('Limit the number of receivers returned') + ) + parser.add_argument( + '--marker', + metavar='', + help=_('Only return receivers that appear after the given ID') + ) + parser.add_argument( + '--sort', + metavar='', + help=_("Sorting option which is a string containing a list of " + "keys separated by commas. Each key can be optionally " + "appended by a sort direction (:asc or :desc). The valid " + "sort keys are: ['name', 'type', 'action', 'cluster_id', " + "'created_at']") + ) + parser.add_argument( + '--global-project', + default=False, + action="store_true", + help=_('Indicate that the list should include receivers from' + ' all projects. This option is subject to access policy ' + 'checking. Default is False') + ) + parser.add_argument( + '--full-id', + default=False, + action="store_true", + help=_('Print full IDs in list') + ) + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)", parsed_args) + + senlin_client = self.app.client_manager.clustering + + columns = ['id', 'name', 'type', 'cluster_id', 'action', 'created_at'] + queries = { + 'limit': parsed_args.limit, + 'marker': parsed_args.marker, + 'sort': parsed_args.sort, + 'global_project': parsed_args.global_project, + } + + if parsed_args.filters: + queries.update(senlin_utils.format_parameters(parsed_args.filters)) + + receivers = senlin_client.receivers(**queries) + formatters = {} + if not parsed_args.full_id: + formatters = { + 'id': lambda x: x[:8], + 'cluster_id': lambda x: x[:8], + } + + return ( + columns, + (utils.get_item_properties(r, columns, formatters=formatters) + for r in receivers) + ) diff --git a/senlinclient/tests/unit/osc/v1/test_receiver.py b/senlinclient/tests/unit/osc/v1/test_receiver.py new file mode 100644 index 0000000..84a1369 --- /dev/null +++ b/senlinclient/tests/unit/osc/v1/test_receiver.py @@ -0,0 +1,141 @@ +# 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 mock + +from openstack.cluster.v1 import receiver as sdk_receiver +from openstack import exceptions as sdk_exc + +from senlinclient.osc.v1 import receiver as osc_receiver +from senlinclient.tests.unit.osc.v1 import fakes + + +class TestReceiver(fakes.TestClusteringv1): + def setUp(self): + super(TestReceiver, self).setUp() + self.mock_client = self.app.client_manager.clustering + + +class TestReceiverList(TestReceiver): + columns = ['id', 'name', 'type', 'cluster_id', 'action', 'created_at'] + response = {"receivers": [ + { + "action": "CLUSTER_SCALE_OUT", + "actor": { + "trust_id": [ + "6dc6d336e3fc4c0a951b5698cd1236d9" + ] + }, + "channel": { + "alarm_url": "http://node1:8778/v1/webhooks/e03dd2e5-8f2e-4ec1" + "-8c6a-74ba891e5422/trigger?V=1&count=1" + }, + "cluster_id": "ae63a10b-4a90-452c-aef1-113a0b255ee3", + "created_at": "2015-06-27T05:09:43", + "domain": "Default", + "id": "573aa1ba-bf45-49fd-907d-6b5d6e6adfd3", + "name": "cluster_inflate", + "params": { + "count": "1" + }, + "project": "6e18cc2bdbeb48a5b3cad2dc499f6804", + "type": "webhook", + "updated_at": 'null', + "user": "b4ad2d6e18cc2b9c48049f6dbe8a5b3c" + } + ]} + + defaults = { + 'global_project': False, + 'marker': None, + 'limit': None, + 'sort': None, + } + + def setUp(self): + super(TestReceiverList, self).setUp() + self.cmd = osc_receiver.ListReceiver(self.app, None) + self.mock_client.receivers = mock.Mock( + return_value=sdk_receiver.Receiver(None, {})) + + def test_receiver_list_defaults(self): + arglist = [] + parsed_args = self.check_parser(self.cmd, arglist, []) + columns, data = self.cmd.take_action(parsed_args) + self.mock_client.receivers.assert_called_with(**self.defaults) + self.assertEqual(self.columns, columns) + + def test_receiver_list_full_id(self): + arglist = ['--full-id'] + parsed_args = self.check_parser(self.cmd, arglist, []) + columns, data = self.cmd.take_action(parsed_args) + self.mock_client.receivers.assert_called_with(**self.defaults) + self.assertEqual(self.columns, columns) + + def test_receiver_list_limit(self): + kwargs = copy.deepcopy(self.defaults) + kwargs['limit'] = '3' + arglist = ['--limit', '3'] + parsed_args = self.check_parser(self.cmd, arglist, []) + columns, data = self.cmd.take_action(parsed_args) + self.mock_client.receivers.assert_called_with(**kwargs) + self.assertEqual(self.columns, columns) + + def test_receiver_list_sort(self): + kwargs = copy.deepcopy(self.defaults) + kwargs['sort'] = 'name:asc' + arglist = ['--sort', 'name:asc'] + parsed_args = self.check_parser(self.cmd, arglist, []) + columns, data = self.cmd.take_action(parsed_args) + self.mock_client.receivers.assert_called_with(**kwargs) + self.assertEqual(self.columns, columns) + + def test_receiver_list_sort_invalid_key(self): + self.mock_client.receivers = mock.Mock( + return_value=self.response) + kwargs = copy.deepcopy(self.defaults) + kwargs['sort'] = 'bad_key' + arglist = ['--sort', 'bad_key'] + parsed_args = self.check_parser(self.cmd, arglist, []) + self.mock_client.receivers.side_effect = sdk_exc.HttpException() + self.assertRaises(sdk_exc.HttpException, + self.cmd.take_action, parsed_args) + + def test_receiver_list_sort_invalid_direction(self): + self.mock_client.receivers = mock.Mock( + return_value=self.response) + kwargs = copy.deepcopy(self.defaults) + kwargs['sort'] = 'name:bad_direction' + arglist = ['--sort', 'name:bad_direction'] + parsed_args = self.check_parser(self.cmd, arglist, []) + self.mock_client.receivers.side_effect = sdk_exc.HttpException() + self.assertRaises(sdk_exc.HttpException, + self.cmd.take_action, parsed_args) + + def test_receiver_list_filter(self): + kwargs = copy.deepcopy(self.defaults) + kwargs['name'] = 'my_receiver' + arglist = ['--filter', 'name=my_receiver'] + parsed_args = self.check_parser(self.cmd, arglist, []) + columns, data = self.cmd.take_action(parsed_args) + self.mock_client.receivers.assert_called_with(**kwargs) + self.assertEqual(self.columns, columns) + + def test_receiver_list_marker(self): + kwargs = copy.deepcopy(self.defaults) + kwargs['marker'] = 'a9448bf6' + arglist = ['--marker', 'a9448bf6'] + parsed_args = self.check_parser(self.cmd, arglist, []) + columns, data = self.cmd.take_action(parsed_args) + self.mock_client.receivers.assert_called_with(**kwargs) + self.assertEqual(self.columns, columns) diff --git a/setup.cfg b/setup.cfg index d8487c7..d8850cf 100644 --- a/setup.cfg +++ b/setup.cfg @@ -48,6 +48,7 @@ openstack.clustering.v1 = cluster_profile_type_list = senlinclient.osc.v1.profile_type:ProfileTypeList cluster_profile_type_show = senlinclient.osc.v1.profile_type:ProfileTypeShow cluster_profile_update = senlinclient.osc.v1.profile:UpdateProfile + cluster_receiver_list = senlinclient.osc.v1.receiver:ListReceiver [global] setup-hooks =