summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
authorsunyajing <yajing.sun@easystack.cn>2016-05-28 11:01:22 +0800
committersunyajing <yajing.sun@easystack.cn>2016-05-28 16:38:22 +0800
commit3e11661074e1a7e051e0ebff5800f8f1aac85153 (patch)
tree8714135039224e6e1cc338cbd75dd038e8022655 /openstackclient
parent9da02d14eadc39da6f97b3df095af8b0c452a5b4 (diff)
downloadpython-openstackclient-3e11661074e1a7e051e0ebff5800f8f1aac85153.tar.gz
Add "image unset" command
This patch add a command that supports unsetting image tags and properties Change-Id: I6f2cf45a61ff89da6664f3a34ae49fdd85d8c986 Closes-Bug:#1582968
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/image/v2/image.py89
-rw-r--r--openstackclient/tests/image/v2/fakes.py2
-rw-r--r--openstackclient/tests/image/v2/test_image.py93
3 files changed, 182 insertions, 2 deletions
diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py
index a9c0f1fd..a81f092c 100644
--- a/openstackclient/image/v2/image.py
+++ b/openstackclient/image/v2/image.py
@@ -805,8 +805,8 @@ class SetImage(command.Command):
# Checks if anything that requires getting the image
if not (kwargs or parsed_args.deactivate or parsed_args.activate):
- self.log.warning(_("No arguments specified"))
- return {}, {}
+ msg = _("No arguments specified")
+ raise exceptions.CommandError(msg)
image = utils.find_resource(
image_client.images, parsed_args.image)
@@ -856,3 +856,88 @@ class ShowImage(command.ShowOne):
info = _format_image(image)
return zip(*sorted(six.iteritems(info)))
+
+
+class UnsetImage(command.Command):
+ """Unset image tags and properties"""
+
+ def get_parser(self, prog_name):
+ parser = super(UnsetImage, self).get_parser(prog_name)
+ parser.add_argument(
+ "image",
+ metavar="<image>",
+ help=_("Image to modify (name or ID)"),
+ )
+ parser.add_argument(
+ "--tag",
+ dest="tags",
+ metavar="<tag>",
+ default=[],
+ action='append',
+ help=_("Unset a tag on this image "
+ "(repeat option to set multiple tags)"),
+ )
+ parser.add_argument(
+ "--property",
+ dest="properties",
+ metavar="<property_key>",
+ default=[],
+ action='append',
+ help=_("Unset a property on this image "
+ "(repeat option to set multiple properties)"),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ image_client = self.app.client_manager.image
+ image = utils.find_resource(
+ image_client.images,
+ parsed_args.image,
+ )
+
+ if not (parsed_args.tags or parsed_args.properties):
+ msg = _("No arguments specified")
+ raise exceptions.CommandError(msg)
+
+ kwargs = {}
+ tagret = 0
+ propret = 0
+ if parsed_args.tags:
+ for k in parsed_args.tags:
+ try:
+ image_client.image_tags.delete(image.id, k)
+ except Exception:
+ self.log.error(_("tag unset failed,"
+ " '%s' is a nonexistent tag ") % k)
+ tagret += 1
+
+ if parsed_args.properties:
+ for k in parsed_args.properties:
+ try:
+ assert(k in image.keys())
+ except AssertionError:
+ self.log.error(_("property unset failed,"
+ " '%s' is a nonexistent property ") % k)
+ propret += 1
+ image_client.images.update(
+ image.id,
+ parsed_args.properties,
+ **kwargs)
+
+ tagtotal = len(parsed_args.tags)
+ proptotal = len(parsed_args.properties)
+ if (tagret > 0 and propret > 0):
+ msg = (_("Failed to unset %(tagret)s of %(tagtotal)s tags,"
+ "Failed to unset %(propret)s of %(proptotal)s properties.")
+ % {'tagret': tagret, 'tagtotal': tagtotal,
+ 'propret': propret, 'proptotal': proptotal})
+ raise exceptions.CommandError(msg)
+ elif tagret > 0:
+ msg = (_("Failed to unset %(target)s of %(tagtotal)s tags.")
+ % {'tagret': tagret, 'tagtotal': tagtotal})
+ raise exceptions.CommandError(msg)
+ elif propret > 0:
+ msg = (_("Failed to unset %(propret)s of %(proptotal)s"
+ " properties.")
+ % {'propret': propret, 'proptotal': proptotal})
+ raise exceptions.CommandError(msg)
diff --git a/openstackclient/tests/image/v2/fakes.py b/openstackclient/tests/image/v2/fakes.py
index a662a585..24aaec51 100644
--- a/openstackclient/tests/image/v2/fakes.py
+++ b/openstackclient/tests/image/v2/fakes.py
@@ -157,6 +157,8 @@ class FakeImagev2Client(object):
self.images.resource_class = fakes.FakeResource(None, {})
self.image_members = mock.Mock()
self.image_members.resource_class = fakes.FakeResource(None, {})
+ self.image_tags = mock.Mock()
+ self.image_tags.resource_class = fakes.FakeResource(None, {})
self.auth_token = kwargs['token']
self.management_url = kwargs['endpoint']
diff --git a/openstackclient/tests/image/v2/test_image.py b/openstackclient/tests/image/v2/test_image.py
index beebdef9..ca20d83d 100644
--- a/openstackclient/tests/image/v2/test_image.py
+++ b/openstackclient/tests/image/v2/test_image.py
@@ -37,6 +37,8 @@ class TestImage(image_fakes.TestImagev2):
self.images_mock.reset_mock()
self.image_members_mock = self.app.client_manager.image.image_members
self.image_members_mock.reset_mock()
+ self.image_tags_mock = self.app.client_manager.image.image_tags
+ self.image_tags_mock.reset_mock()
# Get shortcut to the Mocks in identity client
self.project_mock = self.app.client_manager.identity.projects
@@ -1184,3 +1186,94 @@ class TestImageShow(TestImage):
self.assertEqual(image_fakes.IMAGE_columns, columns)
self.assertEqual(image_fakes.IMAGE_SHOW_data, data)
+
+
+class TestImageUnset(TestImage):
+
+ attrs = {}
+ attrs['tags'] = ['test']
+ attrs['prop'] = 'test'
+ image = image_fakes.FakeImage.create_one_image(attrs)
+
+ def setUp(self):
+ super(TestImageUnset, self).setUp()
+
+ # Set up the schema
+ self.model = warlock.model_factory(
+ image_fakes.IMAGE_schema,
+ schemas.SchemaBasedModel,
+ )
+
+ self.images_mock.get.return_value = self.image
+ self.image_tags_mock.delete.return_value = self.image
+
+ # Get the command object to test
+ self.cmd = image.UnsetImage(self.app, None)
+
+ def test_image_unset_tag_option(self):
+
+ arglist = [
+ '--tag', 'test',
+ self.image.id,
+ ]
+
+ verifylist = [
+ ('tags', ['test']),
+ ('image', self.image.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+
+ self.image_tags_mock.delete.assert_called_with(
+ self.image.id, 'test'
+ )
+ self.assertIsNone(result)
+
+ def test_image_unset_property_option(self):
+
+ arglist = [
+ '--property', 'prop',
+ self.image.id,
+ ]
+
+ verifylist = [
+ ('properties', ['prop']),
+ ('image', self.image.id)
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+
+ kwargs = {}
+ self.images_mock.update.assert_called_with(
+ self.image.id,
+ parsed_args.properties,
+ **kwargs)
+
+ self.assertIsNone(result)
+
+ def test_image_unset_mixed_option(self):
+
+ arglist = [
+ '--tag', 'test',
+ '--property', 'prop',
+ self.image.id,
+ ]
+
+ verifylist = [
+ ('tags', ['test']),
+ ('properties', ['prop']),
+ ('image', self.image.id)
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ result = self.cmd.take_action(parsed_args)
+
+ kwargs = {}
+ self.images_mock.update.assert_called_with(
+ self.image.id,
+ parsed_args.properties,
+ **kwargs)
+
+ self.image_tags_mock.delete.assert_called_with(
+ self.image.id, 'test'
+ )
+ self.assertIsNone(result)