summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
authorMike Fedosin <mfedosin@redhat.com>2018-01-04 17:49:28 +0100
committerMike Fedosin <mfedosin@redhat.com>2018-01-05 19:36:49 +0100
commited1b59848fd2a6b7bed7618ab5ac0db00e8110dc (patch)
tree3c8dff292adf6b4dab26a6f4deab5efc9c776f4c /openstackclient
parentb13a323128072f6f56619a816f5be165796171a4 (diff)
downloadpython-openstackclient-ed1b59848fd2a6b7bed7618ab5ac0db00e8110dc.tar.gz
Check that Glance returns image data before processing it
Now if Glance v2 cannot find image data it returns an empty response with 204 status code, instead of raising an error. Glance client handles this situation and wraps the response with a RequestIdProxy object, whose 'wrapped' attribute is None. But when openstack client tries to parse this object using glanceclient's save_image util function, it fails with "NoneType object is not iterable" message, for the object doesn't contain any data. This patch adds additional check to prevent such behaviour and raises SystemExit exception if no data was returned from the server. Glance v1 is not affected, because it raises an error if can't find an image data. Change-Id: I016a60462ba586f9fa7585c2cfafffd7be38de7b Closes-Bug: #1741223
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/image/v2/image.py7
-rw-r--r--openstackclient/tests/unit/image/v2/test_image.py51
2 files changed, 58 insertions, 0 deletions
diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py
index d793c459..3db9311e 100644
--- a/openstackclient/image/v2/image.py
+++ b/openstackclient/image/v2/image.py
@@ -17,6 +17,7 @@
import argparse
import logging
+import sys
from glanceclient.common import utils as gc_utils
from osc_lib.cli import parseractions
@@ -649,6 +650,12 @@ class SaveImage(command.Command):
)
data = image_client.images.data(image.id)
+ if data.wrapped is None:
+ msg = _('Image %s has no data.') % image.id
+ LOG.error(msg)
+ sys.stdout.write(msg + '\n')
+ raise SystemExit
+
gc_utils.save_image(data, parsed_args.file)
diff --git a/openstackclient/tests/unit/image/v2/test_image.py b/openstackclient/tests/unit/image/v2/test_image.py
index 383619ef..e1a79d13 100644
--- a/openstackclient/tests/unit/image/v2/test_image.py
+++ b/openstackclient/tests/unit/image/v2/test_image.py
@@ -15,6 +15,7 @@
import copy
+from glanceclient.common import utils as glanceclient_utils
from glanceclient.v2 import schemas
import mock
from osc_lib import exceptions
@@ -1505,3 +1506,53 @@ class TestImageUnset(TestImage):
self.image.id, 'test'
)
self.assertIsNone(result)
+
+
+class TestImageSave(TestImage):
+
+ image = image_fakes.FakeImage.create_one_image({})
+
+ def setUp(self):
+ super(TestImageSave, self).setUp()
+
+ # Generate a request id
+ self.resp = mock.MagicMock()
+ self.resp.headers['x-openstack-request-id'] = 'req_id'
+
+ # Get the command object to test
+ self.cmd = image.SaveImage(self.app, None)
+
+ def test_save_data(self):
+ req_id_proxy = glanceclient_utils.RequestIdProxy(
+ ['some_data', self.resp]
+ )
+ self.images_mock.data.return_value = req_id_proxy
+
+ arglist = ['--file', '/path/to/file', self.image.id]
+
+ verifylist = [
+ ('file', '/path/to/file'),
+ ('image', self.image.id)
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ with mock.patch('glanceclient.common.utils.save_image') as mocked_save:
+ self.cmd.take_action(parsed_args)
+ mocked_save.assert_called_once_with(req_id_proxy, '/path/to/file')
+
+ def test_save_no_data(self):
+ req_id_proxy = glanceclient_utils.RequestIdProxy(
+ [None, self.resp]
+ )
+ self.images_mock.data.return_value = req_id_proxy
+
+ arglist = ['--file', '/path/to/file', self.image.id]
+
+ verifylist = [
+ ('file', '/path/to/file'),
+ ('image', self.image.id)
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # Raise SystemExit if no data was provided.
+ self.assertRaises(SystemExit, self.cmd.take_action, parsed_args)