summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2014-10-24 16:16:04 +0000
committerGerrit Code Review <review@openstack.org>2014-10-24 16:16:04 +0000
commitd07ae4236a3d025540b8174d497ce1277198c72f (patch)
treed2b593edbb319c6c7eab7d31ed7cd337d005a5ee /openstackclient
parentd140d8940f99f42d0cc9d2953b26726cbc096a5e (diff)
parentca783f46595a7d90cea0ad8491b65aa5f9370a04 (diff)
downloadpython-openstackclient-d07ae4236a3d025540b8174d497ce1277198c72f.tar.gz
Merge "Close files on image create"
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/image/v1/image.py53
-rw-r--r--openstackclient/tests/image/v1/test_image.py17
2 files changed, 42 insertions, 28 deletions
diff --git a/openstackclient/image/v1/image.py b/openstackclient/image/v1/image.py
index 465e9d7b..32dd388c 100644
--- a/openstackclient/image/v1/image.py
+++ b/openstackclient/image/v1/image.py
@@ -15,6 +15,7 @@
"""Image V1 Action Implementations"""
+import io
import logging
import os
import six
@@ -214,10 +215,9 @@ class CreateImage(show.ShowOne):
elif parsed_args.file:
# Send an open file handle to glanceclient so it will
# do a chunked transfer
- kwargs["data"] = open(parsed_args.file, "rb")
+ kwargs["data"] = io.open(parsed_args.file, "rb")
else:
# Read file from stdin
- kwargs["data"] = None
if sys.stdin.isatty() is not True:
if msvcrt:
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
@@ -225,29 +225,36 @@ class CreateImage(show.ShowOne):
# do a chunked transfer
kwargs["data"] = sys.stdin
+ # Wrap the call to catch exceptions in order to close files
try:
- image = utils.find_resource(
- image_client.images,
- parsed_args.name,
- )
-
- # Preserve previous properties if any are being set now
- if image.properties:
- if parsed_args.properties:
- image.properties.update(kwargs['properties'])
- kwargs['properties'] = image.properties
-
- except exceptions.CommandError:
- if not parsed_args.volume:
- # This is normal for a create or reserve (create w/o an image)
- # But skip for create from volume
- image = image_client.images.create(**kwargs)
- else:
- # Update an existing reservation
+ try:
+ image = utils.find_resource(
+ image_client.images,
+ parsed_args.name,
+ )
- # If an image is specified via --file, --location or
- # --copy-from let the API handle it
- image = image_client.images.update(image.id, **kwargs)
+ # Preserve previous properties if any are being set now
+ if image.properties:
+ if parsed_args.properties:
+ image.properties.update(kwargs['properties'])
+ kwargs['properties'] = image.properties
+
+ except exceptions.CommandError:
+ if not parsed_args.volume:
+ # This is normal for a create or reserve (create w/o
+ # an image), but skip for create from volume
+ image = image_client.images.create(**kwargs)
+ else:
+ # Update an existing reservation
+
+ # If an image is specified via --file, --location or
+ # --copy-from let the API handle it
+ image = image_client.images.update(image.id, **kwargs)
+ finally:
+ # Clean up open files - make sure data isn't a string
+ if ('data' in kwargs and hasattr(kwargs['data'], 'close') and
+ kwargs['data'] != sys.stdin):
+ kwargs['data'].close()
info = {}
info.update(image._info)
diff --git a/openstackclient/tests/image/v1/test_image.py b/openstackclient/tests/image/v1/test_image.py
index 3f97b151..a0566930 100644
--- a/openstackclient/tests/image/v1/test_image.py
+++ b/openstackclient/tests/image/v1/test_image.py
@@ -139,14 +139,17 @@ class TestImageCreate(TestImage):
self.assertEqual(image_fakes.IMAGE_columns, columns)
self.assertEqual(image_fakes.IMAGE_data, data)
- @mock.patch('six.moves.builtins.open')
- def test_image_create_file(self, open_mock):
+ @mock.patch('openstackclient.image.v1.image.io.open', name='Open')
+ def test_image_create_file(self, mock_open):
+ mock_file = mock.MagicMock(name='File')
+ mock_open.return_value = mock_file
+ mock_open.read.return_value = image_fakes.image_data
mock_exception = {
'find.side_effect': exceptions.CommandError('x'),
'get.side_effect': exceptions.CommandError('x'),
}
self.images_mock.configure_mock(**mock_exception)
- open_mock.return_value = image_fakes.image_data
+
arglist = [
'--file', 'filer',
'--unprotected',
@@ -169,7 +172,11 @@ class TestImageCreate(TestImage):
# DisplayCommandBase.take_action() returns two tuples
columns, data = self.cmd.take_action(parsed_args)
- open_mock.assert_called_with('filer', 'rb')
+ # Ensure input file is opened
+ mock_open.assert_called_with('filer', 'rb')
+
+ # Ensure the input file is closed
+ mock_file.close.assert_called_with()
# ImageManager.get(name)
self.images_mock.get.assert_called_with(image_fakes.image_name)
@@ -185,7 +192,7 @@ class TestImageCreate(TestImage):
'Alpha': '1',
'Beta': '2',
},
- data=image_fakes.image_data,
+ data=mock_file,
)
# Verify update() was not called, if it was show the args