Allow objects to be streamed to stdout

Change-Id: Icd8de6b2122fe77926d93da9bda08f56c3672a7a
This commit is contained in:
Honza Pokorny 2017-06-21 12:53:38 -03:00
parent c0719c36d1
commit ae35a29169
7 changed files with 70 additions and 7 deletions

View File

@ -114,7 +114,8 @@ Save object locally
.. option:: --file <filename> .. option:: --file <filename>
Destination filename (defaults to object name) Destination filename (defaults to object name);
using - as the filename will print the file to stdout
.. describe:: <container> .. describe:: <container>

View File

@ -16,6 +16,7 @@
import io import io
import logging import logging
import os import os
import sys
from osc_lib import utils from osc_lib import utils
import six import six
@ -376,12 +377,16 @@ class APIv1(api.BaseAPI):
stream=True, stream=True,
) )
if response.status_code == 200: if response.status_code == 200:
if not os.path.exists(os.path.dirname(file)): if file == '-':
if len(os.path.dirname(file)) > 0:
os.makedirs(os.path.dirname(file))
with open(file, 'wb') as f:
for chunk in response.iter_content(64 * 1024): for chunk in response.iter_content(64 * 1024):
f.write(chunk) sys.stdout.write(chunk)
else:
if not os.path.exists(os.path.dirname(file)):
if len(os.path.dirname(file)) > 0:
os.makedirs(os.path.dirname(file))
with open(file, 'wb') as f:
for chunk in response.iter_content(64 * 1024):
f.write(chunk)
def object_set( def object_set(
self, self,

View File

@ -204,7 +204,8 @@ class SaveObject(command.Command):
parser.add_argument( parser.add_argument(
"--file", "--file",
metavar="<filename>", metavar="<filename>",
help=_("Destination filename (defaults to object name)"), help=_("Destination filename (defaults to object name); using '-'"
" as the filename will print the file to stdout"),
) )
parser.add_argument( parser.add_argument(
'container', 'container',

View File

@ -66,6 +66,10 @@ class ObjectTests(base.TestCase):
+ ' ' + object_file + ' --file ' + tmp_file) + ' ' + object_file + ' --file ' + tmp_file)
# TODO(stevemar): Assert returned fields # TODO(stevemar): Assert returned fields
raw_output = self.openstack('object save ' + self.CONTAINER_NAME
+ ' ' + object_file + ' --file -')
self.assertEqual(raw_output, 'test content')
self.openstack('object show ' + self.CONTAINER_NAME self.openstack('object show ' + self.CONTAINER_NAME
+ ' ' + object_file) + ' ' + object_file)
# TODO(stevemar): Assert returned fields # TODO(stevemar): Assert returned fields

View File

@ -13,6 +13,8 @@
# under the License. # under the License.
# #
import six
from keystoneauth1 import session from keystoneauth1 import session
from openstackclient.api import object_store_v1 as object_store from openstackclient.api import object_store_v1 as object_store
@ -67,6 +69,8 @@ OBJECT = {
'last_modified': object_modified_1, 'last_modified': object_modified_1,
} }
object_1_content = six.b('object 1 content')
OBJECT_2 = { OBJECT_2 = {
'name': object_name_2, 'name': object_name_2,
'bytes': object_bytes_2, 'bytes': object_bytes_2,

View File

@ -13,8 +13,10 @@
import copy import copy
import mock
from osc_lib import exceptions from osc_lib import exceptions
from requests_mock.contrib import fixture from requests_mock.contrib import fixture
import six
from openstackclient.object.v1 import object as object_cmds from openstackclient.object.v1 import object as object_cmds
from openstackclient.tests.unit.object.v1 import fakes as object_fakes from openstackclient.tests.unit.object.v1 import fakes as object_fakes
@ -202,3 +204,44 @@ class TestObjectShow(TestObjectAll):
'manifest', 'manifest',
) )
self.assertEqual(datalist, data) self.assertEqual(datalist, data)
class TestObjectSave(TestObjectAll):
def setUp(self):
super(TestObjectSave, self).setUp()
# Get the command object to test
self.cmd = object_cmds.SaveObject(self.app, None)
def test_save_to_stdout(self):
self.requests_mock.register_uri(
'GET',
object_fakes.ENDPOINT +
'/' +
object_fakes.container_name +
'/' +
object_fakes.object_name_1,
status_code=200,
content=object_fakes.object_1_content
)
arglist = [
object_fakes.container_name,
object_fakes.object_name_1,
'--file',
'-'
]
verifylist = [
('container', object_fakes.container_name),
('object', object_fakes.object_name_1),
('file', '-'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
with mock.patch('sys.stdout', new=six.BytesIO()) as fake_stdout:
self.cmd.take_action(parsed_args)
self.assertEqual(fake_stdout.getvalue(), object_fakes.object_1_content)

View File

@ -0,0 +1,5 @@
---
features:
- |
Add support for streaming Swift objects to stdout when using the ``object
save`` command, by specifying ``--filename -``.