Skip to content

Commit 91cc731

Browse files
Jenkinsopenstack-gerrit
authored andcommitted
Merge "Allow objects to be streamed to stdout"
2 parents eb19c16 + ae35a29 commit 91cc731

7 files changed

Lines changed: 70 additions & 7 deletions

File tree

doc/source/cli/command-objects/object.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ Save object locally
114114
115115
.. option:: --file <filename>
116116

117-
Destination filename (defaults to object name)
117+
Destination filename (defaults to object name);
118+
using - as the filename will print the file to stdout
118119

119120
.. describe:: <container>
120121

openstackclient/api/object_store_v1.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import io
1717
import logging
1818
import os
19+
import sys
1920

2021
from osc_lib import utils
2122
import six
@@ -376,12 +377,16 @@ def object_save(
376377
stream=True,
377378
)
378379
if response.status_code == 200:
379-
if not os.path.exists(os.path.dirname(file)):
380-
if len(os.path.dirname(file)) > 0:
381-
os.makedirs(os.path.dirname(file))
382-
with open(file, 'wb') as f:
380+
if file == '-':
383381
for chunk in response.iter_content(64 * 1024):
384-
f.write(chunk)
382+
sys.stdout.write(chunk)
383+
else:
384+
if not os.path.exists(os.path.dirname(file)):
385+
if len(os.path.dirname(file)) > 0:
386+
os.makedirs(os.path.dirname(file))
387+
with open(file, 'wb') as f:
388+
for chunk in response.iter_content(64 * 1024):
389+
f.write(chunk)
385390

386391
def object_set(
387392
self,

openstackclient/object/v1/object.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@ def get_parser(self, prog_name):
204204
parser.add_argument(
205205
"--file",
206206
metavar="<filename>",
207-
help=_("Destination filename (defaults to object name)"),
207+
help=_("Destination filename (defaults to object name); using '-'"
208+
" as the filename will print the file to stdout"),
208209
)
209210
parser.add_argument(
210211
'container',

openstackclient/tests/functional/object/v1/test_object.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ def _test_object(self, object_file):
6666
+ ' ' + object_file + ' --file ' + tmp_file)
6767
# TODO(stevemar): Assert returned fields
6868

69+
raw_output = self.openstack('object save ' + self.CONTAINER_NAME
70+
+ ' ' + object_file + ' --file -')
71+
self.assertEqual(raw_output, 'test content')
72+
6973
self.openstack('object show ' + self.CONTAINER_NAME
7074
+ ' ' + object_file)
7175
# TODO(stevemar): Assert returned fields

openstackclient/tests/unit/object/v1/fakes.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
# under the License.
1414
#
1515

16+
import six
17+
1618
from keystoneauth1 import session
1719

1820
from openstackclient.api import object_store_v1 as object_store
@@ -67,6 +69,8 @@
6769
'last_modified': object_modified_1,
6870
}
6971

72+
object_1_content = six.b('object 1 content')
73+
7074
OBJECT_2 = {
7175
'name': object_name_2,
7276
'bytes': object_bytes_2,

openstackclient/tests/unit/object/v1/test_object_all.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313

1414
import copy
1515

16+
import mock
1617
from osc_lib import exceptions
1718
from requests_mock.contrib import fixture
19+
import six
1820

1921
from openstackclient.object.v1 import object as object_cmds
2022
from openstackclient.tests.unit.object.v1 import fakes as object_fakes
@@ -202,3 +204,44 @@ def test_object_show(self):
202204
'manifest',
203205
)
204206
self.assertEqual(datalist, data)
207+
208+
209+
class TestObjectSave(TestObjectAll):
210+
211+
def setUp(self):
212+
super(TestObjectSave, self).setUp()
213+
214+
# Get the command object to test
215+
self.cmd = object_cmds.SaveObject(self.app, None)
216+
217+
def test_save_to_stdout(self):
218+
self.requests_mock.register_uri(
219+
'GET',
220+
object_fakes.ENDPOINT +
221+
'/' +
222+
object_fakes.container_name +
223+
'/' +
224+
object_fakes.object_name_1,
225+
status_code=200,
226+
content=object_fakes.object_1_content
227+
)
228+
229+
arglist = [
230+
object_fakes.container_name,
231+
object_fakes.object_name_1,
232+
'--file',
233+
'-'
234+
]
235+
236+
verifylist = [
237+
('container', object_fakes.container_name),
238+
('object', object_fakes.object_name_1),
239+
('file', '-'),
240+
]
241+
242+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
243+
244+
with mock.patch('sys.stdout', new=six.BytesIO()) as fake_stdout:
245+
self.cmd.take_action(parsed_args)
246+
247+
self.assertEqual(fake_stdout.getvalue(), object_fakes.object_1_content)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
features:
3+
- |
4+
Add support for streaming Swift objects to stdout when using the ``object
5+
save`` command, by specifying ``--filename -``.

0 commit comments

Comments
 (0)