Merge "Make swift post output an error message when failing"

This commit is contained in:
Jenkins 2014-11-13 03:30:01 +00:00 committed by Gerrit Code Review
commit 202bbab2d0
3 changed files with 134 additions and 78 deletions
swiftclient
tests/unit

@ -594,44 +594,31 @@ class SwiftService(object):
'error': err, 'error': err,
'response_dict': response_dict 'response_dict': response_dict
}) })
return res return res
else: if not objects:
if not objects: res["action"] = "post_container"
res["action"] = "post_container" response_dict = {}
response_dict = {} headers = split_headers(
headers = split_headers( options['meta'], 'X-Container-Meta-')
options['meta'], 'X-Container-Meta-') headers.update(
headers.update( split_headers(options['header'], ''))
split_headers(options['header'], '')) if options['read_acl'] is not None:
if options['read_acl'] is not None: headers['X-Container-Read'] = options['read_acl']
headers['X-Container-Read'] = options['read_acl'] if options['write_acl'] is not None:
if options['write_acl'] is not None: headers['X-Container-Write'] = options['write_acl']
headers['X-Container-Write'] = options['write_acl'] if options['sync_to'] is not None:
if options['sync_to'] is not None: headers['X-Container-Sync-To'] = options['sync_to']
headers['X-Container-Sync-To'] = options['sync_to'] if options['sync_key'] is not None:
if options['sync_key'] is not None: headers['X-Container-Sync-Key'] = options['sync_key']
headers['X-Container-Sync-Key'] = options['sync_key'] res['headers'] = headers
res['headers'] = headers try:
try: post = self.thread_manager.container_pool.submit(
post = self.thread_manager.container_pool.submit( self._post_container_job, container,
self._post_container_job, container, headers, response_dict
headers, response_dict )
) get_future_result(post)
get_future_result(post) except ClientException as err:
except ClientException as err: if err.http_status != 404:
if err.http_status != 404:
res.update({
'action': 'post_container',
'success': False,
'error': err,
'response_dict': response_dict
})
return res
raise SwiftError(
"Container '%s' not found" % container,
container=container
)
except Exception as err:
res.update({ res.update({
'action': 'post_container', 'action': 'post_container',
'success': False, 'success': False,
@ -639,37 +626,49 @@ class SwiftService(object):
'response_dict': response_dict 'response_dict': response_dict
}) })
return res return res
else: raise SwiftError(
post_futures = [] "Container '%s' not found" % container,
post_objects = self._make_post_objects(objects) container=container
for post_object in post_objects: )
obj = post_object.object_name except Exception as err:
obj_options = post_object.options res.update({
response_dict = {} 'action': 'post_container',
headers = split_headers( 'success': False,
options['meta'], 'X-Object-Meta-') 'error': err,
# add header options to the headers object for the request. 'response_dict': response_dict
headers.update( })
split_headers(options['header'], '')) return res
if obj_options is not None: else:
if 'meta' in obj_options: post_futures = []
headers.update( post_objects = self._make_post_objects(objects)
split_headers( for post_object in post_objects:
obj_options['meta'], 'X-Object-Meta' obj = post_object.object_name
) obj_options = post_object.options
) response_dict = {}
if 'headers' in obj_options: headers = split_headers(
headers.update( options['meta'], 'X-Object-Meta-')
split_headers(obj_options['header'], '') # add header options to the headers object for the request.
headers.update(
split_headers(options['header'], ''))
if obj_options is not None:
if 'meta' in obj_options:
headers.update(
split_headers(
obj_options['meta'], 'X-Object-Meta'
) )
)
if 'headers' in obj_options:
headers.update(
split_headers(obj_options['header'], '')
)
post = self.thread_manager.object_uu_pool.submit( post = self.thread_manager.object_uu_pool.submit(
self._post_object_job, container, obj, self._post_object_job, container, obj,
headers, response_dict headers, response_dict
) )
post_futures.append(post) post_futures.append(post)
return ResultsIterator(post_futures) return ResultsIterator(post_futures)
@staticmethod @staticmethod
def _make_post_objects(objects): def _make_post_objects(objects):

@ -547,8 +547,7 @@ If the container is not found, it will be created automatically.
Positional arguments: Positional arguments:
[container] Name of container to post to. [container] Name of container to post to.
[object] Name of object to post. Specify multiple times [object] Name of object to post.
for multiple objects.
Optional arguments: Optional arguments:
--read-acl <acl> Read ACL for containers. Quick summary of ACL syntax: --read-acl <acl> Read ACL for containers. Quick summary of ACL syntax:
@ -600,7 +599,7 @@ def st_post(parser, args, output_manager):
with SwiftService(options=_opts) as swift: with SwiftService(options=_opts) as swift:
try: try:
if not args: if not args:
swift.post() result = swift.post()
else: else:
container = args[0] container = args[0]
if '/' in container: if '/' in container:
@ -616,15 +615,16 @@ def st_post(parser, args, output_manager):
results_iterator = swift.post( results_iterator = swift.post(
container=container, objects=objects container=container, objects=objects
) )
for result in results_iterator: # only 1 result result = next(results_iterator)
if not result["success"]:
raise(result["error"])
else: else:
output_manager.error( output_manager.error(
'Usage: %s post %s\n%s', BASENAME, 'Usage: %s post %s\n%s', BASENAME,
st_post_options, st_post_help) st_post_options, st_post_help)
return
else: else:
swift.post(container=container) result = swift.post(container=container)
if not result["success"]:
raise(result["error"])
except SwiftError as e: except SwiftError as e:
output_manager.error(e.value) output_manager.error(e.value)

@ -390,26 +390,68 @@ class TestShell(unittest.TestCase):
@mock.patch('swiftclient.service.Connection') @mock.patch('swiftclient.service.Connection')
def test_post_account(self, connection): def test_post_account(self, connection):
argv = ["", "post"] argv = ["", "post"]
connection.return_value.head_object.return_value = {}
swiftclient.shell.main(argv) swiftclient.shell.main(argv)
connection.return_value.post_account.assert_called_with( connection.return_value.post_account.assert_called_with(
headers={}, response_dict={}) headers={}, response_dict={})
@mock.patch('swiftclient.shell.OutputManager.error')
@mock.patch('swiftclient.service.Connection')
def test_post_account_bad_auth(self, connection, error):
argv = ["", "post"]
connection.return_value.post_account.side_effect = \
swiftclient.ClientException('bad auth')
swiftclient.shell.main(argv)
error.assert_called_with('bad auth')
@mock.patch('swiftclient.shell.OutputManager.error')
@mock.patch('swiftclient.service.Connection')
def test_post_account_not_found(self, connection, error):
argv = ["", "post"]
connection.return_value.post_account.side_effect = \
swiftclient.ClientException('test', http_status=404)
swiftclient.shell.main(argv)
error.assert_called_with('Account not found')
@mock.patch('swiftclient.service.Connection')
def test_post_container(self, connection):
argv = ["", "post", "container"] argv = ["", "post", "container"]
connection.return_value.head_object.return_value = {}
swiftclient.shell.main(argv) swiftclient.shell.main(argv)
connection.return_value.post_container.assert_called_with( connection.return_value.post_container.assert_called_with(
'container', headers={}, response_dict={}) 'container', headers={}, response_dict={})
@mock.patch('swiftclient.shell.OutputManager.error')
@mock.patch('swiftclient.service.Connection') @mock.patch('swiftclient.service.Connection')
def test_post_container(self, connection): def test_post_container_bad_auth(self, connection, error):
argv = ["", "post", "container"]
connection.return_value.post_container.side_effect = \
swiftclient.ClientException('bad auth')
swiftclient.shell.main(argv)
error.assert_called_with('bad auth')
@mock.patch('swiftclient.service.Connection')
def test_post_container_not_found_causes_put(self, connection):
argv = ["", "post", "container"]
connection.return_value.post_container.side_effect = \
swiftclient.ClientException('test', http_status=404)
swiftclient.shell.main(argv)
self.assertEqual('container',
connection.return_value.put_container.call_args[0][0])
@mock.patch('swiftclient.shell.OutputManager.error')
def test_post_container_with_bad_name(self, error):
argv = ["", "post", "conta/iner"]
swiftclient.shell.main(argv)
self.assertTrue(error.called)
self.assertTrue(error.call_args[0][0].startswith('WARNING: / in'))
@mock.patch('swiftclient.service.Connection')
def test_post_container_with_options(self, connection):
argv = ["", "post", "container", argv = ["", "post", "container",
"--read-acl", "test2:tester2", "--read-acl", "test2:tester2",
"--write-acl", "test3:tester3 test4", "--write-acl", "test3:tester3 test4",
"--sync-to", "othersite", "--sync-to", "othersite",
"--sync-key", "secret", "--sync-key", "secret",
] ]
connection.return_value.head_object.return_value = {}
swiftclient.shell.main(argv) swiftclient.shell.main(argv)
connection.return_value.post_container.assert_called_with( connection.return_value.post_container.assert_called_with(
'container', headers={ 'container', headers={
@ -424,13 +466,28 @@ class TestShell(unittest.TestCase):
"--meta", "Color:Blue", "--meta", "Color:Blue",
"--header", "content-type:text/plain" "--header", "content-type:text/plain"
] ]
connection.return_value.head_object.return_value = {}
swiftclient.shell.main(argv) swiftclient.shell.main(argv)
connection.return_value.post_object.assert_called_with( connection.return_value.post_object.assert_called_with(
'container', 'object', headers={ 'container', 'object', headers={
'Content-Type': 'text/plain', 'Content-Type': 'text/plain',
'X-Object-Meta-Color': 'Blue'}, response_dict={}) 'X-Object-Meta-Color': 'Blue'}, response_dict={})
@mock.patch('swiftclient.shell.OutputManager.error')
@mock.patch('swiftclient.service.Connection')
def test_post_object_bad_auth(self, connection, error):
argv = ["", "post", "container", "object"]
connection.return_value.post_object.side_effect = \
swiftclient.ClientException("bad auth")
swiftclient.shell.main(argv)
error.assert_called_with('bad auth')
@mock.patch('swiftclient.shell.OutputManager.error')
def test_post_object_too_many_args(self, error):
argv = ["", "post", "container", "object", "bad_arg"]
swiftclient.shell.main(argv)
self.assertTrue(error.called)
self.assertTrue(error.call_args[0][0].startswith('Usage'))
@mock.patch('swiftclient.shell.generate_temp_url') @mock.patch('swiftclient.shell.generate_temp_url')
def test_temp_url(self, temp_url): def test_temp_url(self, temp_url):
argv = ["", "tempurl", "GET", "60", "/v1/AUTH_account/c/o", argv = ["", "tempurl", "GET", "60", "/v1/AUTH_account/c/o",