summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--swiftclient/client.py4
-rw-r--r--swiftclient/service.py2
-rwxr-xr-xswiftclient/shell.py26
-rw-r--r--tests/unit/test_shell.py73
4 files changed, 88 insertions, 17 deletions
diff --git a/swiftclient/client.py b/swiftclient/client.py
index def40bf..8cbedc7 100644
--- a/swiftclient/client.py
+++ b/swiftclient/client.py
@@ -396,7 +396,9 @@ def get_auth(auth_url, user, key, **kwargs):
if not (os_options.get('tenant_name') or os_options.get('tenant_id')
or os_options.get('project_name')
or os_options.get('project_id')):
- raise ClientException('No tenant specified')
+ if auth_version in AUTH_VERSIONS_V2:
+ raise ClientException('No tenant specified')
+ raise ClientException('No project name or project id specified.')
cacert = kwargs.get('cacert', None)
storage_url, token = get_auth_keystone(auth_url, user,
diff --git a/swiftclient/service.py b/swiftclient/service.py
index 4315295..281947e 100644
--- a/swiftclient/service.py
+++ b/swiftclient/service.py
@@ -434,7 +434,7 @@ class SwiftService(object):
})
return res
except ClientException as err:
- if err.http_status == 404:
+ if err.http_status != 404:
res.update({
'success': False,
'error': err
diff --git a/swiftclient/shell.py b/swiftclient/shell.py
index 619ec5c..015c9d9 100755
--- a/swiftclient/shell.py
+++ b/swiftclient/shell.py
@@ -488,13 +488,15 @@ def st_stat(parser, args, output_manager):
_opts = vars(options)
with SwiftService(options=_opts) as swift:
- if not args:
- stat_result = swift.stat()
- items = stat_result['items']
- headers = stat_result['headers']
- print_account_stats(items, headers, output_manager)
- else:
- try:
+ try:
+ if not args:
+ stat_result = swift.stat()
+ if not stat_result['success']:
+ raise stat_result['error']
+ items = stat_result['items']
+ headers = stat_result['headers']
+ print_account_stats(items, headers, output_manager)
+ else:
container = args[0]
if '/' in container:
output_manager.error(
@@ -505,6 +507,8 @@ def st_stat(parser, args, output_manager):
args = args[1:]
if not args:
stat_result = swift.stat(container=container)
+ if not stat_result['success']:
+ raise stat_result['error']
items = stat_result['items']
headers = stat_result['headers']
print_container_stats(items, headers, output_manager)
@@ -527,8 +531,8 @@ def st_stat(parser, args, output_manager):
'Usage: %s stat %s\n%s', BASENAME,
st_stat_options, st_stat_help)
- except SwiftError as e:
- output_manager.error(e.value)
+ except SwiftError as e:
+ output_manager.error(e.value)
st_post_options = '''[--read-acl <acl>] [--write-acl <acl>] [--sync-to]
@@ -961,8 +965,8 @@ def parse_args(parser, args, enforce_requires=True):
if (not (options.auth and options.user and options.key)
and options.auth_version != '3'):
- # Use keystone auth if any of the old-style args are missing
- options.auth_version = '2.0'
+ # Use keystone auth if any of the old-style args are missing
+ options.auth_version = '2.0'
# Use new-style args if old ones not present
if not options.auth and options.os_auth_url:
diff --git a/tests/unit/test_shell.py b/tests/unit/test_shell.py
index 8e61cb4..29d7472 100644
--- a/tests/unit/test_shell.py
+++ b/tests/unit/test_shell.py
@@ -24,6 +24,7 @@ import swiftclient
from swiftclient.service import SwiftError
import swiftclient.shell
import swiftclient.utils
+from swiftclient.multithreading import OutputManager
from os.path import basename, dirname
from tests.unit.test_swiftclient import MockHttpTest
@@ -551,13 +552,13 @@ class TestParsing(unittest.TestCase):
# check the expected opts are set
for key, v in opts.items():
actual = getattr(actual_opts, key)
- self.assertEqual(v, actual, 'Expected %s for key %s, found %s'
- % (v, key, actual))
+ self.assertEqual(v, actual, 'Expected %s for key %s, found %s' %
+ (v, key, actual))
for key, v in os_opts.items():
actual = getattr(actual_opts, "os_" + key)
- self.assertEqual(v, actual, 'Expected %s for key %s, found %s'
- % (v, key, actual))
+ self.assertEqual(v, actual, 'Expected %s for key %s, found %s' %
+ (v, key, actual))
# check the os_options dict values are set
self.assertTrue(hasattr(actual_opts, 'os_options'))
@@ -725,6 +726,55 @@ class TestParsing(unittest.TestCase):
args = _make_args("stat", opts, os_opts)
self.assertRaises(SystemExit, swiftclient.shell.main, args)
+ def test_no_tenant_name_or_id_v2(self):
+ os_opts = {"password": "secret",
+ "username": "user",
+ "auth_url": "http://example.com:5000/v3",
+ "tenant_name": "",
+ "tenant_id": ""}
+
+ out = six.StringIO()
+ err = six.StringIO()
+ mock_output = _make_output_manager(out, err)
+ with mock.patch('swiftclient.shell.OutputManager', mock_output):
+ args = _make_args("stat", {}, os_opts)
+ self.assertRaises(SystemExit, swiftclient.shell.main, args)
+ self.assertEqual(err.getvalue().strip(), 'No tenant specified')
+
+ out = six.StringIO()
+ err = six.StringIO()
+ mock_output = _make_output_manager(out, err)
+ with mock.patch('swiftclient.shell.OutputManager', mock_output):
+ args = _make_args("stat", {}, os_opts, cmd_args=["testcontainer"])
+ self.assertRaises(SystemExit, swiftclient.shell.main, args)
+ self.assertEqual(err.getvalue().strip(), 'No tenant specified')
+
+ def test_no_tenant_name_or_id_v3(self):
+ os_opts = {"password": "secret",
+ "username": "user",
+ "auth_url": "http://example.com:5000/v3",
+ "tenant_name": "",
+ "tenant_id": ""}
+
+ out = six.StringIO()
+ err = six.StringIO()
+ mock_output = _make_output_manager(out, err)
+ with mock.patch('swiftclient.shell.OutputManager', mock_output):
+ args = _make_args("stat", {"auth_version": "3"}, os_opts)
+ self.assertRaises(SystemExit, swiftclient.shell.main, args)
+ self.assertEqual(err.getvalue().strip(),
+ 'No project name or project id specified.')
+
+ out = six.StringIO()
+ err = six.StringIO()
+ mock_output = _make_output_manager(out, err)
+ with mock.patch('swiftclient.shell.OutputManager', mock_output):
+ args = _make_args("stat", {"auth_version": "3"},
+ os_opts, cmd_args=["testcontainer"])
+ self.assertRaises(SystemExit, swiftclient.shell.main, args)
+ self.assertEqual(err.getvalue().strip(),
+ 'No project name or project id specified.')
+
def test_insufficient_env_vars_v3(self):
args = _make_args("stat", {}, {})
opts = {"auth_version": "3"}
@@ -1043,3 +1093,18 @@ class TestKeystoneOptions(MockHttpTest):
opts = {'auth-version': '2.0'}
self._test_options(opts, os_opts)
+
+
+def _make_output_manager(stdout, stderr):
+ class MockOutputManager(OutputManager):
+ # This class is used to mock OutputManager so that we can
+ # override stdout and stderr. Mocking sys.stdout & sys.stdout
+ # doesn't work because they are argument defaults in the
+ # OutputManager constructor and those defaults are pinned to
+ # the value of sys.stdout/stderr before we get chance to mock them.
+ def __init__(self, print_stream=None, error_stream=None):
+ super(MockOutputManager, self).__init__()
+ self.print_stream = stdout
+ self.error_stream = stderr
+
+ return MockOutputManager