From 3cd1faa7afdfc829ee218f86b9bc9d914c0d0b75 Mon Sep 17 00:00:00 2001
From: "Zack M. Davis" <zdavis@swiftstack.com>
Date: Fri, 24 Jul 2015 10:57:29 -0700
Subject: [PATCH] make Connection.get_auth set url and token attributes on self

When a Connection is first __init__ialized (without providing a
preauthurl or preauthtoken), the url and token attributes are None; they
get set (to be reused on future requests) after one of the wrapper
methods internally using _retry (head_account, get_container,
put_object, and similar friends) is called. However, this had not been
the case for get_auth, much to the momentary confusion and
disappointment of programmers using swiftclient who expected to be able
to get the token or storage URL off the Connection object after calling
get_auth (perhaps in order to make an unusual kind of request that
swiftclient doesn't already have a function for). This commit makes
get_auth set the url and token attributes as one might expect.

Change-Id: I0d9593eb5b072c8e3fa84f7d5a4c948c0bc6037a
---
 swiftclient/client.py          | 15 ++++++++-------
 tests/unit/test_swiftclient.py | 11 +++++++++++
 2 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/swiftclient/client.py b/swiftclient/client.py
index 0ddf4e8b..74e60c0a 100644
--- a/swiftclient/client.py
+++ b/swiftclient/client.py
@@ -1258,13 +1258,14 @@ class Connection(object):
                 self.http_conn = None
 
     def get_auth(self):
-        return get_auth(self.authurl, self.user, self.key,
-                        snet=self.snet,
-                        auth_version=self.auth_version,
-                        os_options=self.os_options,
-                        cacert=self.cacert,
-                        insecure=self.insecure,
-                        timeout=self.timeout)
+        self.url, self.token = get_auth(self.authurl, self.user, self.key,
+                                        snet=self.snet,
+                                        auth_version=self.auth_version,
+                                        os_options=self.os_options,
+                                        cacert=self.cacert,
+                                        insecure=self.insecure,
+                                        timeout=self.timeout)
+        return self.url, self.token
 
     def http_connection(self, url=None):
         return http_connection(url if url else self.url,
diff --git a/tests/unit/test_swiftclient.py b/tests/unit/test_swiftclient.py
index 1cfe2044..73c0e944 100644
--- a/tests/unit/test_swiftclient.py
+++ b/tests/unit/test_swiftclient.py
@@ -1481,6 +1481,17 @@ class TestConnection(MockHttpTest):
             ('HEAD', '/v1/AUTH_pre_url', '', {'x-auth-token': 'post_token'}),
         ])
 
+    def test_get_auth_sets_url_and_token(self):
+        with mock.patch('swiftclient.client.get_auth') as mock_get_auth:
+            mock_get_auth.return_value = (
+                "https://storage.url/v1/AUTH_storage_acct", "AUTH_token"
+            )
+            conn = c.Connection("https://auth.url/auth/v2.0", "user", "passkey",
+                                tenant_name="tenant")
+            conn.get_auth()
+        self.assertEqual("https://storage.url/v1/AUTH_storage_acct", conn.url)
+        self.assertEqual("AUTH_token", conn.token)
+
     def test_timeout_passed_down(self):
         # We want to avoid mocking http_connection(), and most especially
         # avoid passing it down in argument. However, we cannot simply