diff --git a/doc/source/command-objects/container.rst b/doc/source/command-objects/container.rst index e6517e9bb8..130a6b3dad 100644 --- a/doc/source/command-objects/container.rst +++ b/doc/source/command-objects/container.rst @@ -28,8 +28,13 @@ Delete container .. code:: bash os container delete + [-r] | [--recursive] [ ...] +.. option:: --recursive, -r + + Recursively delete objects in container before container delete + .. describe:: Container(s) to delete @@ -40,7 +45,7 @@ container list List containers .. program:: container list -.. code::bash +.. code:: bash os container list [--prefix ] diff --git a/functional/tests/object/v1/test_object.py b/functional/tests/object/v1/test_object.py index 289e1ca77c..cd98012cb6 100644 --- a/functional/tests/object/v1/test_object.py +++ b/functional/tests/object/v1/test_object.py @@ -74,5 +74,8 @@ class ObjectTests(test.TestCase): + ' ' + self.OBJECT_NAME) self.assertEqual(0, len(raw_output)) - raw_output = self.openstack('container delete ' + self.CONTAINER_NAME) + self.openstack('object create ' + self.CONTAINER_NAME + + ' ' + self.OBJECT_NAME) + raw_output = self.openstack('container delete -r ' + + self.CONTAINER_NAME) self.assertEqual(0, len(raw_output)) diff --git a/openstackclient/object/v1/container.py b/openstackclient/object/v1/container.py index e70afd9d0e..80b8423824 100644 --- a/openstackclient/object/v1/container.py +++ b/openstackclient/object/v1/container.py @@ -58,6 +58,12 @@ class DeleteContainer(command.Command): def get_parser(self, prog_name): parser = super(DeleteContainer, self).get_parser(prog_name) + parser.add_argument( + '--recursive', '-r', + action='store_true', + default=False, + help='Recursively delete objects and container', + ) parser.add_argument( 'containers', metavar='', @@ -69,6 +75,14 @@ class DeleteContainer(command.Command): def take_action(self, parsed_args): for container in parsed_args.containers: + if parsed_args.recursive: + objs = self.app.client_manager.object_store.object_list( + container=container) + for obj in objs: + self.app.client_manager.object_store.object_delete( + container=container, + object=obj['name'], + ) self.app.client_manager.object_store.container_delete( container=container, ) diff --git a/openstackclient/tests/object/v1/test_container.py b/openstackclient/tests/object/v1/test_container.py index afcb3386b4..d34d73e2cd 100644 --- a/openstackclient/tests/object/v1/test_container.py +++ b/openstackclient/tests/object/v1/test_container.py @@ -44,6 +44,96 @@ class TestContainer(object_fakes.TestObjectv1): self.api = self.app.client_manager.object_store +@mock.patch('openstackclient.api.object_store_v1.APIv1.object_delete') +@mock.patch('openstackclient.api.object_store_v1.APIv1.object_list') +@mock.patch('openstackclient.api.object_store_v1.APIv1.container_delete') +class TestContainerDelete(TestContainer): + + def setUp(self): + super(TestContainerDelete, self).setUp() + + # Get the command object to test + self.cmd = container.DeleteContainer(self.app, None) + + def test_container_delete(self, c_mock, o_list_mock, o_delete_mock): + c_mock.return_value = None + + arglist = [ + object_fakes.container_name, + ] + verifylist = [ + ('containers', [object_fakes.container_name]), + ('recursive', False), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.assertEqual(None, self.cmd.take_action(parsed_args)) + + kwargs = {} + c_mock.assert_called_with( + container=object_fakes.container_name, + **kwargs + ) + self.assertFalse(o_list_mock.called) + self.assertFalse(o_delete_mock.called) + + def test_recursive_delete(self, c_mock, o_list_mock, o_delete_mock): + c_mock.return_value = None + o_list_mock.return_value = [object_fakes.OBJECT] + o_delete_mock.return_value = None + + arglist = [ + '--recursive', + object_fakes.container_name, + ] + verifylist = [ + ('containers', [object_fakes.container_name]), + ('recursive', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.assertEqual(None, self.cmd.take_action(parsed_args)) + + kwargs = {} + c_mock.assert_called_with( + container=object_fakes.container_name, + **kwargs + ) + o_list_mock.assert_called_with(container=object_fakes.container_name) + o_delete_mock.assert_called_with( + container=object_fakes.container_name, + object=object_fakes.OBJECT['name'], + ) + + def test_r_delete(self, c_mock, o_list_mock, o_delete_mock): + c_mock.return_value = None + o_list_mock.return_value = [object_fakes.OBJECT] + o_delete_mock.return_value = None + + arglist = [ + '-r', + object_fakes.container_name, + ] + verifylist = [ + ('containers', [object_fakes.container_name]), + ('recursive', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.assertEqual(None, self.cmd.take_action(parsed_args)) + + kwargs = {} + c_mock.assert_called_with( + container=object_fakes.container_name, + **kwargs + ) + o_list_mock.assert_called_with(container=object_fakes.container_name) + o_delete_mock.assert_called_with( + container=object_fakes.container_name, + object=object_fakes.OBJECT['name'], + ) + + @mock.patch( 'openstackclient.api.object_store_v1.APIv1.container_list' )