summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClay Gerrard <clay.gerrard@gmail.com>2014-04-08 21:14:13 -0700
committerTim Burke <tim.burke@gmail.com>2015-06-15 12:38:21 -0700
commit17feec709c02612c285ebddaf712876b619aa5ed (patch)
treeaa3b468cff83a9b40f520c5fad8f6659ce8ad1ff
parentec3e2ab3a099b1276ae5d87fda936567f64423dc (diff)
downloadpython-swiftclient-17feec709c02612c285ebddaf712876b619aa5ed.tar.gz
Add some bash helpers for auth stuff
Change-Id: If61ac9a050e7a115f37dbf4e74b904ac5dfd2052
-rwxr-xr-xswiftclient/shell.py54
-rw-r--r--tests/unit/test_shell.py102
-rw-r--r--tests/unit/utils.py6
3 files changed, 156 insertions, 6 deletions
diff --git a/swiftclient/shell.py b/swiftclient/shell.py
index 430efd2..31147f1 100755
--- a/swiftclient/shell.py
+++ b/swiftclient/shell.py
@@ -31,14 +31,19 @@ from swiftclient.utils import config_true_value, generate_temp_url, prt_bytes
from swiftclient.multithreading import OutputManager
from swiftclient.exceptions import ClientException
from swiftclient import __version__ as client_version
-from swiftclient.service import SwiftService, SwiftError, SwiftUploadObject
+from swiftclient.service import SwiftService, SwiftError, \
+ SwiftUploadObject, get_conn
from swiftclient.command_helpers import print_account_stats, \
print_container_stats, print_object_stats
+try:
+ from shlex import quote as sh_quote
+except ImportError:
+ from pipes import quote as sh_quote
BASENAME = 'swift'
-commands = ('delete', 'download', 'list', 'post',
- 'stat', 'upload', 'capabilities', 'info', 'tempurl')
+commands = ('delete', 'download', 'list', 'post', 'stat', 'upload',
+ 'capabilities', 'info', 'tempurl', 'auth')
def immediate_exit(signum, frame):
@@ -905,6 +910,46 @@ def st_capabilities(parser, args, output_manager):
st_info = st_capabilities
+st_auth_help = '''
+Display auth related authentication variables in shell friendly format.
+
+ Commands to run to export storage url and auth token into
+ OS_STORAGE_URL and OS_AUTH_TOKEN:
+
+ swift auth
+
+ Commands to append to a runcom file (e.g. ~/.bashrc, /etc/profile) for
+ automatic authentication:
+
+ swift auth -v -U test:tester -K testing \
+ -A http://localhost:8080/auth/v1.0
+
+'''.strip('\n')
+
+
+def st_auth(parser, args, thread_manager):
+ (options, args) = parse_args(parser, args)
+ _opts = vars(options)
+ if options.verbose > 1:
+ if options.auth_version in ('1', '1.0'):
+ print('export ST_AUTH=%s' % sh_quote(options.auth))
+ print('export ST_USER=%s' % sh_quote(options.user))
+ print('export ST_KEY=%s' % sh_quote(options.key))
+ else:
+ print('export OS_IDENTITY_API_VERSION=%s' % sh_quote(
+ options.auth_version))
+ print('export OS_AUTH_VERSION=%s' % sh_quote(options.auth_version))
+ print('export OS_AUTH_URL=%s' % sh_quote(options.auth))
+ for k, v in sorted(_opts.items()):
+ if v and k.startswith('os_') and \
+ k not in ('os_auth_url', 'os_options'):
+ print('export %s=%s' % (k.upper(), sh_quote(v)))
+ else:
+ conn = get_conn(_opts)
+ url, token = conn.get_auth()
+ print('export OS_STORAGE_URL=%s' % sh_quote(url))
+ print('export OS_AUTH_TOKEN=%s' % sh_quote(token))
+
st_tempurl_options = '<method> <seconds> <path> <key>'
@@ -1073,7 +1118,8 @@ Positional arguments:
or object.
upload Uploads files or directories to the given container.
capabilities List cluster capabilities.
- tempurl Create a temporary URL
+ tempurl Create a temporary URL.
+ auth Display auth related environment variables.
Examples:
%%prog download --help
diff --git a/tests/unit/test_shell.py b/tests/unit/test_shell.py
index 98cef85..56c96f8 100644
--- a/tests/unit/test_shell.py
+++ b/tests/unit/test_shell.py
@@ -19,8 +19,10 @@ import mock
import os
import tempfile
import unittest
+import textwrap
from testtools import ExpectedException
+
import six
import swiftclient
@@ -46,6 +48,11 @@ mocked_os_environ = {
'ST_USER': 'test:tester',
'ST_KEY': 'testing'
}
+clean_os_environ = {}
+environ_prefixes = ('ST_', 'OS_')
+for key in os.environ:
+ if any(key.startswith(m) for m in environ_prefixes):
+ clean_os_environ[key] = ''
clean_os_environ = {}
environ_prefixes = ('ST_', 'OS_')
@@ -1529,6 +1536,101 @@ class TestAuth(MockHttpTest):
}),
])
+ def test_auth(self):
+ headers = {
+ 'x-auth-token': 'AUTH_tk5b6b12',
+ 'x-storage-url': 'https://swift.storage.example.com/v1/AUTH_test',
+ }
+ mock_resp = self.fake_http_connection(200, headers=headers)
+ with mock.patch('swiftclient.client.http_connection', new=mock_resp):
+ stdout = six.StringIO()
+ with mock.patch('sys.stdout', new=stdout):
+ argv = [
+ '',
+ 'auth',
+ '--auth', 'https://swift.storage.example.com/auth/v1.0',
+ '--user', 'test:tester', '--key', 'testing',
+ ]
+ swiftclient.shell.main(argv)
+
+ expected = """
+ export OS_STORAGE_URL=https://swift.storage.example.com/v1/AUTH_test
+ export OS_AUTH_TOKEN=AUTH_tk5b6b12
+ """
+ self.assertEquals(textwrap.dedent(expected).lstrip(),
+ stdout.getvalue())
+
+ def test_auth_verbose(self):
+ with mock.patch('swiftclient.client.http_connection') as mock_conn:
+ stdout = six.StringIO()
+ with mock.patch('sys.stdout', new=stdout):
+ argv = [
+ '',
+ 'auth',
+ '--auth', 'https://swift.storage.example.com/auth/v1.0',
+ '--user', 'test:tester', '--key', 'te$tin&',
+ '--verbose',
+ ]
+ swiftclient.shell.main(argv)
+
+ expected = """
+ export ST_AUTH=https://swift.storage.example.com/auth/v1.0
+ export ST_USER=test:tester
+ export ST_KEY='te$tin&'
+ """
+ self.assertEquals(textwrap.dedent(expected).lstrip(),
+ stdout.getvalue())
+ self.assertEqual([], mock_conn.mock_calls)
+
+ def test_auth_v2(self):
+ os_options = {'tenant_name': 'demo'}
+ with mock.patch('swiftclient.client.get_auth_keystone',
+ new=fake_get_auth_keystone(os_options)):
+ stdout = six.StringIO()
+ with mock.patch('sys.stdout', new=stdout):
+ argv = [
+ '',
+ 'auth', '-V2',
+ '--auth', 'https://keystone.example.com/v2.0/',
+ '--os-tenant-name', 'demo',
+ '--os-username', 'demo', '--os-password', 'admin',
+ ]
+ swiftclient.shell.main(argv)
+
+ expected = """
+ export OS_STORAGE_URL=http://url/
+ export OS_AUTH_TOKEN=token
+ """
+ self.assertEquals(textwrap.dedent(expected).lstrip(),
+ stdout.getvalue())
+
+ def test_auth_verbose_v2(self):
+ with mock.patch('swiftclient.client.get_auth_keystone') \
+ as mock_keystone:
+ stdout = six.StringIO()
+ with mock.patch('sys.stdout', new=stdout):
+ argv = [
+ '',
+ 'auth', '-V2',
+ '--auth', 'https://keystone.example.com/v2.0/',
+ '--os-tenant-name', 'demo',
+ '--os-username', 'demo', '--os-password', '$eKr3t',
+ '--verbose',
+ ]
+ swiftclient.shell.main(argv)
+
+ expected = """
+ export OS_IDENTITY_API_VERSION=2.0
+ export OS_AUTH_VERSION=2.0
+ export OS_AUTH_URL=https://keystone.example.com/v2.0/
+ export OS_PASSWORD='$eKr3t'
+ export OS_TENANT_NAME=demo
+ export OS_USERNAME=demo
+ """
+ self.assertEquals(textwrap.dedent(expected).lstrip(),
+ stdout.getvalue())
+ self.assertEqual([], mock_keystone.mock_calls)
+
class TestCrossAccountObjectAccess(TestBase, MockHttpTest):
"""
diff --git a/tests/unit/utils.py b/tests/unit/utils.py
index 955296e..0a45437 100644
--- a/tests/unit/utils.py
+++ b/tests/unit/utils.py
@@ -38,8 +38,10 @@ def fake_get_auth_keystone(expected_os_options=None, exc=None,
if exc:
raise exc('test')
# TODO: some way to require auth_url, user and key?
- if expected_os_options and actual_os_options != expected_os_options:
- return "", None
+ if expected_os_options:
+ for key, value in actual_os_options.items():
+ if value and value != expected_os_options.get(key):
+ return "", None
if 'required_kwargs' in kwargs:
for k, v in kwargs['required_kwargs'].items():
if v != actual_kwargs.get(k):