From 72d68a23357ebc9647734f25471e5def1e38d76b Mon Sep 17 00:00:00 2001 From: dixiaoli Date: Sun, 21 Feb 2016 11:29:31 +0800 Subject: [PATCH] Add OpenstackClient plugin for cluster policy delete This change implements the "openstack cluster policy delete" command Based on the existing senlin command: senlin policy-delete Change-Id: Id3ccd41392549299025987d4bee5a5f3482f0d97 Blueprint: senlin-support-python-openstackclient --- senlinclient/osc/v1/policy.py | 57 ++++++++++++++ senlinclient/tests/unit/osc/v1/test_policy.py | 74 +++++++++++++++++++ setup.cfg | 1 + 3 files changed, 132 insertions(+) diff --git a/senlinclient/osc/v1/policy.py b/senlinclient/osc/v1/policy.py index 60e23563..070fb562 100644 --- a/senlinclient/osc/v1/policy.py +++ b/senlinclient/osc/v1/policy.py @@ -13,7 +13,9 @@ """Clustering v1 policy action implementations""" import logging +import sys +from cliff import command from cliff import lister from cliff import show from openstack import exceptions as sdk_exc @@ -21,6 +23,7 @@ from openstackclient.common import exceptions as exc from openstackclient.common import utils from senlinclient.common.i18n import _ +from senlinclient.common.i18n import _LI from senlinclient.common import utils as senlin_utils @@ -213,3 +216,57 @@ class UpdatePolicy(show.ShowOne): if policy is not None: senlin_client.update_policy(policy.id, **params) return _show_policy(senlin_client, policy_id=policy.id) + + +class DeletePolicy(command.Command): + """Delete policy(s).""" + + log = logging.getLogger(__name__ + ".DeletePolicy") + + def get_parser(self, prog_name): + parser = super(DeletePolicy, self).get_parser(prog_name) + parser.add_argument( + 'policy', + metavar='', + nargs='+', + help=_('Name or ID of policy(s) to delete') + ) + parser.add_argument( + '--force', + action='store_true', + help=_('Skip yes/no prompt (assume yes)') + ) + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)", parsed_args) + senlin_client = self.app.client_manager.clustering + try: + if not parsed_args.force and sys.stdin.isatty(): + sys.stdout.write( + _("Are you sure you want to delete this policy(s)" + " [y/N]?")) + prompt_response = sys.stdin.readline().lower() + if not prompt_response.startswith('y'): + return + except KeyboardInterrupt: # Ctrl-c + self.log.info(_LI('Ctrl-c detected.')) + return + except EOFError: # Ctrl-d + self.log.info(_LI('Ctrl-d detected')) + return + + failure_count = 0 + + for pid in parsed_args.policy: + try: + senlin_client.delete_policy(pid, False) + except Exception as ex: + failure_count += 1 + print(ex) + if failure_count: + raise exc.CommandError(_('Failed to delete %(count)s of the ' + '%(total)s specified policy(s).') % + {'count': failure_count, + 'total': len(parsed_args.policy)}) + print('Policy deleted: %s' % parsed_args.policy) diff --git a/senlinclient/tests/unit/osc/v1/test_policy.py b/senlinclient/tests/unit/osc/v1/test_policy.py index 1d2d065a..c57a3b11 100644 --- a/senlinclient/tests/unit/osc/v1/test_policy.py +++ b/senlinclient/tests/unit/osc/v1/test_policy.py @@ -12,6 +12,7 @@ import copy import mock +import six from openstack.cluster.v1 import policy as sdk_policy from openstack import exceptions as sdk_exc @@ -292,3 +293,76 @@ class TestPolicyUpdate(TestPolicy): self.cmd.take_action, parsed_args) self.assertIn('ResourceNotFound: ResourceNotFound', str(error)) + + +class TestPolicyDelete(TestPolicy): + def setUp(self): + super(TestPolicyDelete, self).setUp() + self.cmd = osc_policy.DeletePolicy(self.app, None) + self.mock_client.delete_policy = mock.Mock() + + def test_policy_delete(self): + arglist = ['policy1', 'policy2', 'policy3'] + parsed_args = self.check_parser(self.cmd, arglist, []) + self.cmd.take_action(parsed_args) + self.mock_client.delete_policy.assert_has_calls( + [mock.call('policy1', False), mock.call('policy2', False), + mock.call('policy3', False)] + ) + + def test_policy_delete_force(self): + arglist = ['policy1', 'policy2', 'policy3', '--force'] + parsed_args = self.check_parser(self.cmd, arglist, []) + self.cmd.take_action(parsed_args) + self.mock_client.delete_policy.assert_has_calls( + [mock.call('policy1', False), mock.call('policy2', False), + mock.call('policy3', False)] + ) + + def test_policy_delete_not_found(self): + arglist = ['my_policy'] + self.mock_client.delete_policy.side_effect = sdk_exc.ResourceNotFound + parsed_args = self.check_parser(self.cmd, arglist, []) + error = self.assertRaises(exc.CommandError, self.cmd.take_action, + parsed_args) + self.assertIn('Failed to delete 1 of the 1 specified policy(s).', + str(error)) + + def test_policy_delete_one_found_one_not_found(self): + arglist = ['policy1', 'policy2'] + self.mock_client.delete_policy.side_effect = ( + [None, sdk_exc.ResourceNotFound] + ) + parsed_args = self.check_parser(self.cmd, arglist, []) + error = self.assertRaises(exc.CommandError, + self.cmd.take_action, parsed_args) + self.mock_client.delete_policy.assert_has_calls( + [mock.call('policy1', False), mock.call('policy2', False)] + ) + self.assertEqual('Failed to delete 1 of the 2 specified policy(s).', + str(error)) + + @mock.patch('sys.stdin', spec=six.StringIO) + def test_policy_delete_prompt_yes(self, mock_stdin): + arglist = ['my_policy'] + mock_stdin.isatty.return_value = True + mock_stdin.readline.return_value = 'y' + parsed_args = self.check_parser(self.cmd, arglist, []) + + self.cmd.take_action(parsed_args) + + mock_stdin.readline.assert_called_with() + self.mock_client.delete_policy.assert_called_with('my_policy', + False) + + @mock.patch('sys.stdin', spec=six.StringIO) + def test_policy_delete_prompt_no(self, mock_stdin): + arglist = ['my_policy'] + mock_stdin.isatty.return_value = True + mock_stdin.readline.return_value = 'n' + parsed_args = self.check_parser(self.cmd, arglist, []) + + self.cmd.take_action(parsed_args) + + mock_stdin.readline.assert_called_with() + self.mock_client.delete_policy.assert_not_called() diff --git a/setup.cfg b/setup.cfg index 2f6bcf6e..1ce09155 100644 --- a/setup.cfg +++ b/setup.cfg @@ -36,6 +36,7 @@ openstack.clustering.v1 = cluster_node_show = senlinclient.osc.v1.node:ShowNode cluster_node_update = senlinclient.osc.v1.node:UpdateNode cluster_policy_create = senlinclient.osc.v1.policy:CreatePolicy + cluster_policy_delete = senlinclient.osc.v1.policy:DeletePolicy cluster_policy_list = senlinclient.osc.v1.policy:ListPolicy cluster_policy_show = senlinclient.osc.v1.policy:ShowPolicy cluster_policy_update = senlinclient.osc.v1.policy:UpdatePolicy