From 0fcaffa6b0ddd2d1861680f19c34f7a38984fdda Mon Sep 17 00:00:00 2001 From: Stephen Watson Date: Wed, 15 Mar 2017 15:07:22 -0700 Subject: [PATCH] OSC 3/4 Add remaining CT commands Add cluster template delete, show, and update including unit tests. Implements: blueprint openstackclient-support Change-Id: I457b6eb9f1944a6a90e1e8fe2b2154cbfbe48f23 --- magnumclient/osc/v1/cluster_templates.py | 97 +++++++++++++ .../osc/unit/v1/test_cluster_templates.py | 137 ++++++++++++++++++ setup.cfg | 3 + 3 files changed, 237 insertions(+) diff --git a/magnumclient/osc/v1/cluster_templates.py b/magnumclient/osc/v1/cluster_templates.py index 22873619..0b45b9f1 100644 --- a/magnumclient/osc/v1/cluster_templates.py +++ b/magnumclient/osc/v1/cluster_templates.py @@ -251,6 +251,37 @@ class CreateClusterTemplate(command.ShowOne): return _show_cluster_template(ct) +class DeleteClusterTemplate(command.Command): + """Delete a Cluster Template.""" + _description = _("Delete a Cluster Template.") + + def get_parser(self, prog_name): + parser = super(DeleteClusterTemplate, self).get_parser(prog_name) + parser.add_argument( + 'cluster-templates', + metavar='', + nargs='+', + help=_('ID or name of the (cluster template)s to delete.')) + + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)", parsed_args) + + mag_client = self.app.client_manager.container_infra + + for cluster_template in getattr(parsed_args, 'cluster-templates'): + try: + mag_client.cluster_templates.delete(cluster_template) + print( + "Request to delete cluster template %s has been accepted." + % cluster_template) + except Exception as e: + print("Delete for cluster template " + "%(cluster_template)s failed: %(e)s" % + {'cluster_template': cluster_template, 'e': e}) + + class ListTemplateCluster(command.Lister): """List Cluster Templates.""" _description = _("List Cluster Templates.") @@ -297,3 +328,69 @@ class ListTemplateCluster(command.Lister): columns, (osc_utils.get_item_properties(ct, columns) for ct in cts) ) + + +class ShowClusterTemplate(command.ShowOne): + """Show a Cluster Template.""" + _description = _("Show a Cluster Template.") + + log = logging.getLogger(__name__ + ".ShowClusterTemplate") + + def get_parser(self, prog_name): + parser = super(ShowClusterTemplate, self).get_parser(prog_name) + parser.add_argument( + 'cluster-template', + metavar='', + help=_('ID or name of the cluster template to show.')) + + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)", parsed_args) + + mag_client = self.app.client_manager.container_infra + ct = getattr(parsed_args, 'cluster-template', None) + cluster_template = mag_client.cluster_templates.get(ct) + + return _show_cluster_template(cluster_template) + + +class UpdateClusterTemplate(command.ShowOne): + """Update a Cluster Template.""" + + log = logging.getLogger(__name__ + ".UpdateClusterTemplate") + + def get_parser(self, prog_name): + parser = super(UpdateClusterTemplate, self).get_parser(prog_name) + parser.add_argument( + 'cluster-template', + metavar='', + help=_('The name or UUID of cluster template to update')) + + parser.add_argument( + 'op', + metavar='', + choices=['add', 'replace', 'remove'], + help=_("Operations: one of 'add', 'replace' or 'remove'")) + + parser.add_argument( + 'attributes', + metavar='', + nargs='+', + action='append', + default=[], + help=_( + "Attributes to add/replace or remove (only PATH is necessary " + "on remove)")) + + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)", parsed_args) + + mag_client = self.app.client_manager.container_infra + patch = magnum_utils.args_array_to_patch(parsed_args.op, + parsed_args.attributes[0]) + name = getattr(parsed_args, 'cluster-template', None) + ct = mag_client.cluster_templates.update(name, patch) + return _show_cluster_template(ct) diff --git a/magnumclient/tests/osc/unit/v1/test_cluster_templates.py b/magnumclient/tests/osc/unit/v1/test_cluster_templates.py index d7bbadac..be5a8fa2 100644 --- a/magnumclient/tests/osc/unit/v1/test_cluster_templates.py +++ b/magnumclient/tests/osc/unit/v1/test_cluster_templates.py @@ -15,10 +15,13 @@ import copy import mock +from mock import call from magnumclient.osc.v1 import cluster_templates as osc_ct from magnumclient.tests.osc.unit.v1 import fakes as magnum_fakes +from osc_lib import exceptions as osc_exceptions + class TestClusterTemplate(magnum_fakes.TestMagnumClientOSCV1): default_create_args = { @@ -134,6 +137,55 @@ class TestClusterTemplateCreate(TestClusterTemplate): self.check_parser, self.cmd, arglist, verifylist) +class TestClusterTemplateDelete(TestClusterTemplate): + + def setUp(self): + super(TestClusterTemplateDelete, self).setUp() + + self.cluster_templates_mock.delete = mock.Mock() + self.cluster_templates_mock.delete.return_value = None + + # Get the command object to test + self.cmd = osc_ct.DeleteClusterTemplate(self.app, None) + + def test_cluster_template_delete_one(self): + arglist = ['foo'] + verifylist = [('cluster-templates', ['foo'])] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.cmd.take_action(parsed_args) + self.cluster_templates_mock.delete.assert_called_with('foo') + + def test_cluster_template_delete_multiple(self): + arglist = ['foo', 'bar'] + verifylist = [('cluster-templates', ['foo', 'bar'])] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.cmd.take_action(parsed_args) + self.cluster_templates_mock.delete.assert_has_calls([call('foo'), + call('bar')]) + + def test_cluster_template_delete_bad_uuid(self): + self.cluster_templates_mock.delete.side_effect = ( + osc_exceptions.NotFound(404)) + arglist = ['foo'] + verifylist = [('cluster-templates', ['foo'])] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + returns = self.cmd.take_action(parsed_args) + + self.assertEqual(returns, None) + + def test_cluster_template_delete_no_uuid(self): + arglist = [] + verifylist = [('cluster-templates', [])] + + self.assertRaises(magnum_fakes.MagnumParseException, + self.check_parser, self.cmd, arglist, verifylist) + + class TestClusterTemplateList(TestClusterTemplate): attr = dict() attr['name'] = 'fake-ct-1' @@ -224,3 +276,88 @@ class TestClusterTemplateList(TestClusterTemplate): self.assertRaises(magnum_fakes.MagnumParseException, self.check_parser, self.cmd, arglist, verifylist) + + +class TestClusterTemplateShow(TestClusterTemplate): + attr = dict() + attr['name'] = 'fake-ct-1' + + _cluster_template = ( + magnum_fakes.FakeClusterTemplate.create_one_cluster_template(attr)) + + columns = osc_ct.CLUSTER_TEMPLATE_ATTRIBUTES + + def setUp(self): + super(TestClusterTemplateShow, self).setUp() + + datalist = map(lambda x: getattr(self._cluster_template, x), + self.columns) + + self.show_data_list = tuple(map(lambda x: x if x is not None else '-', + datalist)) + + self.cluster_templates_mock.get = mock.Mock() + self.cluster_templates_mock.get.return_value = self._cluster_template + + # Get the command object to test + self.cmd = osc_ct.ShowClusterTemplate(self.app, None) + + def test_cluster_template_show(self): + arglist = ['fake-ct-1'] + verifylist = [('cluster-template', 'fake-ct-1')] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + self.cluster_templates_mock.get.assert_called_with('fake-ct-1') + self.assertEqual(self.columns, columns) + self.assertEqual(self.show_data_list, data) + + def test_cluster_template_show_no_ct_fail(self): + arglist = [] + verifylist = [] + + self.assertRaises(magnum_fakes.MagnumParseException, + self.check_parser, self.cmd, arglist, verifylist) + + +class TestClusterTemplateUpdate(TestClusterTemplate): + + def setUp(self): + super(TestClusterTemplateUpdate, self).setUp() + + attr = dict() + attr['name'] = 'fake-ct-1' + ct = magnum_fakes.FakeClusterTemplate.create_one_cluster_template(attr) + + self.cluster_templates_mock.update = mock.Mock() + self.cluster_templates_mock.update.return_value = ct + + # Get the command object to test + self.cmd = osc_ct.UpdateClusterTemplate(self.app, None) + + def test_cluster_template_update_pass(self): + arglist = ['foo', 'remove', 'bar'] + verifylist = [ + ('cluster-template', 'foo'), + ('op', 'remove'), + ('attributes', [['bar']]) + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.cmd.take_action(parsed_args) + self.cluster_templates_mock.update.assert_called_with( + 'foo', + [{'op': 'remove', 'path': '/bar'}] + ) + + def test_cluster_template_update_bad_op(self): + arglist = ['foo', 'bar', 'snafu'] + verifylist = [ + ('cluster-template', 'foo'), + ('op', 'bar'), + ('attributes', ['snafu']) + ] + + self.assertRaises(magnum_fakes.MagnumParseException, + self.check_parser, self.cmd, arglist, verifylist) diff --git a/setup.cfg b/setup.cfg index 52089181..7c060138 100644 --- a/setup.cfg +++ b/setup.cfg @@ -31,7 +31,10 @@ openstack.cli.extension = openstack.container_infra.v1 = coe_cluster_template_create = magnumclient.osc.v1.cluster_templates:CreateClusterTemplate + coe_cluster_template_delete = magnumclient.osc.v1.cluster_templates:DeleteClusterTemplate coe_cluster_template_list = magnumclient.osc.v1.cluster_templates:ListTemplateCluster + coe_cluster_template_show = magnumclient.osc.v1.cluster_templates:ShowClusterTemplate + coe_cluster_template_update = magnumclient.osc.v1.cluster_templates:UpdateClusterTemplate coe_cluster_create = magnumclient.osc.v1.clusters:CreateCluster coe_cluster_list = magnumclient.osc.v1.clusters:ListCluster