diff --git a/doc/source/command-objects/compute-agent.rst b/doc/source/command-objects/compute-agent.rst index 395ee4f372..b00a981d1f 100644 --- a/doc/source/command-objects/compute-agent.rst +++ b/doc/source/command-objects/compute-agent.rst @@ -44,17 +44,17 @@ Create compute agent compute agent delete -------------------- -Delete compute agent command +Delete compute agent(s) .. program:: compute agent delete .. code:: bash - os compute agent delete + os compute agent delete [ ...] .. _compute_agent-delete: .. describe:: - ID of agent to delete + ID of agent(s) to delete compute agent list ------------------ diff --git a/openstackclient/compute/v2/agent.py b/openstackclient/compute/v2/agent.py index e358399db3..064fe5a66b 100644 --- a/openstackclient/compute/v2/agent.py +++ b/openstackclient/compute/v2/agent.py @@ -18,6 +18,7 @@ import six from openstackclient.common import command +from openstackclient.common import exceptions from openstackclient.common import utils from openstackclient.i18n import _ @@ -75,20 +76,35 @@ class CreateAgent(command.ShowOne): class DeleteAgent(command.Command): - """Delete compute agent command""" + """Delete compute agent(s)""" def get_parser(self, prog_name): parser = super(DeleteAgent, self).get_parser(prog_name) parser.add_argument( "id", metavar="", - help=_("ID of agent to delete") + nargs='+', + help=_("ID of agent(s) to delete") ) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute - compute_client.agents.delete(parsed_args.id) + result = 0 + for id in parsed_args.id: + try: + compute_client.agents.delete(id) + except Exception as e: + result += 1 + self.app.log.error(_("Failed to delete agent with " + "ID '%(id)s': %(e)s") + % {'id': id, 'e': e}) + + if result > 0: + total = len(parsed_args.id) + msg = (_("%(result)s of %(total)s agents failed " + "to delete.") % {'result': result, 'total': total}) + raise exceptions.CommandError(msg) class ListAgent(command.Lister): diff --git a/openstackclient/tests/compute/v2/test_agent.py b/openstackclient/tests/compute/v2/test_agent.py index bdff8c5e2a..d3d1ff29e0 100644 --- a/openstackclient/tests/compute/v2/test_agent.py +++ b/openstackclient/tests/compute/v2/test_agent.py @@ -13,6 +13,10 @@ # under the License. # +import mock + +from mock import call +from openstackclient.common import exceptions from openstackclient.compute.v2 import agent from openstackclient.tests.compute.v2 import fakes as compute_fakes @@ -89,26 +93,73 @@ class TestAgentCreate(TestAgent): class TestAgentDelete(TestAgent): + fake_agents = compute_fakes.FakeAgent.create_agents(count=2) + def setUp(self): super(TestAgentDelete, self).setUp() - self.agents_mock.get.return_value = self.fake_agent + self.agents_mock.get.return_value = self.fake_agents self.cmd = agent.DeleteAgent(self.app, None) - def test_one_agent_delete(self): + def test_delete_one_agent(self): arglist = [ - 'test' + self.fake_agents[0].agent_id ] verifylist = [ - ('id', 'test'), + ('id', [self.fake_agents[0].agent_id]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - self.agents_mock.delete.assert_called_with(parsed_args.id) + self.agents_mock.delete.assert_called_with( + self.fake_agents[0].agent_id) self.assertIsNone(result) + def test_delete_multiple_agents(self): + arglist = [] + for n in self.fake_agents: + arglist.append(n.agent_id) + verifylist = [ + ('id', arglist), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + + calls = [] + for n in self.fake_agents: + calls.append(call(n.agent_id)) + self.agents_mock.delete.assert_has_calls(calls) + self.assertIsNone(result) + + def test_delete_multiple_agents_exception(self): + arglist = [ + self.fake_agents[0].agent_id, + self.fake_agents[1].agent_id, + 'x-y-z', + ] + verifylist = [ + ('id', arglist), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + ret_delete = [ + None, + None, + exceptions.NotFound('404') + ] + self.agents_mock.delete = mock.Mock(side_effect=ret_delete) + + self.assertRaises(exceptions.CommandError, self.cmd.take_action, + parsed_args) + calls = [ + call(self.fake_agents[0].agent_id), + call(self.fake_agents[1].agent_id), + ] + self.agents_mock.delete.assert_has_calls(calls) + class TestAgentList(TestAgent): diff --git a/releasenotes/notes/compute-agent-deff48988e81b30e.yaml b/releasenotes/notes/compute-agent-deff48988e81b30e.yaml new file mode 100644 index 0000000000..2f3c3f2e7e --- /dev/null +++ b/releasenotes/notes/compute-agent-deff48988e81b30e.yaml @@ -0,0 +1,3 @@ +--- +upgrade: + - Command ``compute agent delete`` now supports deleting multiple agents.