From 6962cc963e6e17e709524ecf6a395e2d0c8b8370 Mon Sep 17 00:00:00 2001 From: Badhmapriya Boopalan Date: Tue, 15 Nov 2016 19:55:46 +0000 Subject: [PATCH] To display image size in human friendly format Include option '--human-readable' to 'image show' command. This option displays image size in human readable format (such as K, M, G, T,..) Related Commit: I0ef74c2ec978483fe49156c88acf5c369a8fa5c2 Closes-Bug: #1640086 Change-Id: I28cd5702925d51303d0607ed8dccf12c56434682 --- openstackclient/image/v1/image.py | 9 +++++++ openstackclient/image/v2/image.py | 8 ++++++ openstackclient/tests/unit/image/v1/fakes.py | 2 ++ .../tests/unit/image/v1/test_image.py | 27 ++++++++++++++++++- openstackclient/tests/unit/image/v2/fakes.py | 9 ++++--- .../tests/unit/image/v2/test_image.py | 26 ++++++++++++++++++ .../notes/bug-1640086-21d7e5f2ce18f53c.yaml | 6 +++++ 7 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 releasenotes/notes/bug-1640086-21d7e5f2ce18f53c.yaml diff --git a/openstackclient/image/v1/image.py b/openstackclient/image/v1/image.py index cf389d17b7..48c90eb0cf 100644 --- a/openstackclient/image/v1/image.py +++ b/openstackclient/image/v1/image.py @@ -706,6 +706,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="", @@ -722,5 +728,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 657277c0dc..cb3537b623 100644 --- a/openstackclient/image/v2/image.py +++ b/openstackclient/image/v2/image.py @@ -848,6 +848,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="", @@ -861,6 +867,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 aef74f0467..6b7560aa40 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 8e2f587d29..3f02f62d46 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 ebc9c3a759..a69a42de27 100644 --- a/openstackclient/tests/unit/image/v2/test_image.py +++ b/openstackclient/tests/unit/image/v2/test_image.py @@ -1177,6 +1177,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() @@ -1211,6 +1214,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 `_]