diff --git a/openstackclient/image/v1/image.py b/openstackclient/image/v1/image.py index 60d6170901..b92da8ce5b 100644 --- a/openstackclient/image/v1/image.py +++ b/openstackclient/image/v1/image.py @@ -713,6 +713,12 @@ class ShowImage(command.ShowOne): def get_parser(self, prog_name): parser = super(ShowImage, self).get_parser(prog_name) + parser.add_argument( + "--human-readable", + default=False, + action='store_true', + help=_("Print image size in a human-friendly format."), + ) parser.add_argument( "image", metavar="", @@ -729,5 +735,8 @@ class ShowImage(command.ShowOne): info = {} info.update(image._info) + if parsed_args.human_readable: + if 'size' in info: + info['size'] = utils.format_size(info['size']) info['properties'] = utils.format_dict(info.get('properties', {})) return zip(*sorted(six.iteritems(info))) diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py index 766de4de57..ad21cbd7ec 100644 --- a/openstackclient/image/v2/image.py +++ b/openstackclient/image/v2/image.py @@ -905,6 +905,12 @@ class ShowImage(command.ShowOne): def get_parser(self, prog_name): parser = super(ShowImage, self).get_parser(prog_name) + parser.add_argument( + "--human-readable", + default=False, + action='store_true', + help=_("Print image size in a human-friendly format."), + ) parser.add_argument( "image", metavar="", @@ -918,6 +924,8 @@ class ShowImage(command.ShowOne): image_client.images, parsed_args.image, ) + if parsed_args.human_readable: + image['size'] = utils.format_size(image['size']) info = _format_image(image) return zip(*sorted(six.iteritems(info))) diff --git a/openstackclient/tests/unit/image/v1/fakes.py b/openstackclient/tests/unit/image/v1/fakes.py index 080356ee6c..4b6d278c68 100644 --- a/openstackclient/tests/unit/image/v1/fakes.py +++ b/openstackclient/tests/unit/image/v1/fakes.py @@ -34,6 +34,7 @@ image_properties = { } image_properties_str = "Alpha='a', Beta='b', Gamma='g'" image_data = 'line 1\nline 2\n' +image_size = 0 IMAGE = { 'id': image_id, @@ -46,6 +47,7 @@ IMAGE = { 'is_public': image_public, 'protected': image_protected, 'properties': image_properties, + 'size': image_size, } IMAGE_columns = tuple(sorted(IMAGE)) diff --git a/openstackclient/tests/unit/image/v1/test_image.py b/openstackclient/tests/unit/image/v1/test_image.py index 036c833651..41ddc49fa5 100644 --- a/openstackclient/tests/unit/image/v1/test_image.py +++ b/openstackclient/tests/unit/image/v1/test_image.py @@ -692,7 +692,8 @@ class TestImageSet(TestImage): class TestImageShow(TestImage): - _image = image_fakes.FakeImage.create_one_image() + _image = image_fakes.FakeImage.create_one_image( + attrs={'size': 2000}) columns = ( 'container_format', 'disk_format', @@ -704,6 +705,7 @@ class TestImageShow(TestImage): 'owner', 'properties', 'protected', + 'size', ) data = ( _image.container_format, @@ -716,6 +718,7 @@ class TestImageShow(TestImage): _image.owner, utils.format_dict(_image.properties), _image.protected, + _image.size, ) def setUp(self): @@ -745,3 +748,25 @@ class TestImageShow(TestImage): self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) + + def test_image_show_human_readable(self): + arglist = [ + '--human-readable', + self._image.id, + ] + verifylist = [ + ('human_readable', True), + ('image', self._image.id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # In base command class ShowOne in cliff, abstract method take_action() + # returns a two-part tuple with a tuple of column names and a tuple of + # data to be shown. + columns, data = self.cmd.take_action(parsed_args) + self.images_mock.get.assert_called_with( + self._image.id, + ) + + size_index = columns.index('size') + self.assertEqual(data[size_index], '2K') diff --git a/openstackclient/tests/unit/image/v2/fakes.py b/openstackclient/tests/unit/image/v2/fakes.py index 7b2145873b..0255ce38dc 100644 --- a/openstackclient/tests/unit/image/v2/fakes.py +++ b/openstackclient/tests/unit/image/v2/fakes.py @@ -32,6 +32,7 @@ image_owner = 'baal' image_protected = False image_visibility = 'public' image_tags = [] +image_size = 0 IMAGE = { 'id': image_id, @@ -39,7 +40,8 @@ IMAGE = { 'owner': image_owner, 'protected': image_protected, 'visibility': image_visibility, - 'tags': image_tags + 'tags': image_tags, + 'size': image_size } IMAGE_columns = tuple(sorted(IMAGE)) @@ -106,7 +108,8 @@ IMAGE_schema = { "size": { "type": [ "null", - "integer" + "integer", + "string" ], "description": "Size of image file in bytes (READ-ONLY)" }, @@ -185,7 +188,7 @@ class FakeImage(object): A dictionary with all attrbutes of image :return: A FakeResource object with id, name, owner, protected, - visibility and tags attrs + visibility, tags and size attrs """ attrs = attrs or {} diff --git a/openstackclient/tests/unit/image/v2/test_image.py b/openstackclient/tests/unit/image/v2/test_image.py index 164185dfda..65764e98e0 100644 --- a/openstackclient/tests/unit/image/v2/test_image.py +++ b/openstackclient/tests/unit/image/v2/test_image.py @@ -1288,6 +1288,9 @@ class TestImageSet(TestImage): class TestImageShow(TestImage): + new_image = image_fakes.FakeImage.create_one_image( + attrs={'size': 1000}) + def setUp(self): super(TestImageShow, self).setUp() @@ -1322,6 +1325,29 @@ class TestImageShow(TestImage): self.assertEqual(image_fakes.IMAGE_columns, columns) self.assertEqual(image_fakes.IMAGE_SHOW_data, data) + def test_image_show_human_readable(self): + self.images_mock.get.return_value = self.new_image + arglist = [ + '--human-readable', + self.new_image.id, + ] + verifylist = [ + ('human_readable', True), + ('image', self.new_image.id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # In base command class ShowOne in cliff, abstract method take_action() + # returns a two-part tuple with a tuple of column names and a tuple of + # data to be shown. + columns, data = self.cmd.take_action(parsed_args) + self.images_mock.get.assert_called_with( + self.new_image.id, + ) + + size_index = columns.index('size') + self.assertEqual(data[size_index], '1K') + class TestImageUnset(TestImage): diff --git a/releasenotes/notes/bug-1640086-21d7e5f2ce18f53c.yaml b/releasenotes/notes/bug-1640086-21d7e5f2ce18f53c.yaml new file mode 100644 index 0000000000..83d6f7bd47 --- /dev/null +++ b/releasenotes/notes/bug-1640086-21d7e5f2ce18f53c.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Add ``--human-readable`` option to ``image show`` to display + image size in human readable format (such as K, M, G, T,..) + [Bug `1640086 `_]