From 1064889902572488f58426e9cdadb898c4354649 Mon Sep 17 00:00:00 2001 From: Danny Hermes Date: Fri, 19 Feb 2016 18:45:27 -0800 Subject: [PATCH] Allowing credentials that don't implement create_scoped(). --- gcloud/bigtable/client.py | 6 ++++- gcloud/bigtable/test_client.py | 10 ++++++-- gcloud/connection.py | 8 ++++-- gcloud/credentials.py | 8 ++---- gcloud/test_connection.py | 13 ++++++++-- gcloud/test_credentials.py | 46 +++++++++++----------------------- 6 files changed, 47 insertions(+), 44 deletions(-) diff --git a/gcloud/bigtable/client.py b/gcloud/bigtable/client.py index 56d46352c072..fcab5e0a7c8e 100644 --- a/gcloud/bigtable/client.py +++ b/gcloud/bigtable/client.py @@ -144,7 +144,11 @@ def __init__(self, project=None, credentials=None, scopes.append(ADMIN_SCOPE) self._admin = bool(admin) - self._credentials = credentials.create_scoped(scopes) + try: + credentials = credentials.create_scoped(scopes) + except AttributeError: + pass + self._credentials = credentials self.user_agent = user_agent self.timeout_seconds = timeout_seconds diff --git a/gcloud/bigtable/test_client.py b/gcloud/bigtable/test_client.py index 88d34482227e..c0641346e7f3 100644 --- a/gcloud/bigtable/test_client.py +++ b/gcloud/bigtable/test_client.py @@ -41,7 +41,8 @@ def _constructor_test_helper(self, expected_scopes, creds, expected_creds = expected_creds or creds self.assertTrue(client._credentials is expected_creds) - self.assertEqual(client._credentials.scopes, expected_scopes) + if expected_scopes is not None: + self.assertEqual(client._credentials.scopes, expected_scopes) self.assertEqual(client.project, PROJECT) self.assertEqual(client.timeout_seconds, timeout_seconds) @@ -90,7 +91,7 @@ def test_constructor_both_admin_and_read_only(self): self._constructor_test_helper([], creds, admin=True, read_only=True) - def test_constructor_implict_credentials(self): + def test_constructor_implicit_credentials(self): from gcloud._testing import _Monkey from gcloud.bigtable import client as MUT @@ -104,6 +105,11 @@ def mock_get_credentials(): self._constructor_test_helper(expected_scopes, None, expected_creds=creds) + def test_constructor_credentials_wo_create_scoped(self): + creds = object() + expected_scopes = None + self._constructor_test_helper(expected_scopes, creds) + def _copy_test_helper(self, read_only=False, admin=False): credentials = _Credentials('value') project = 'PROJECT' diff --git a/gcloud/connection.py b/gcloud/connection.py index 84b4b33bb7d1..f965497c2c9d 100644 --- a/gcloud/connection.py +++ b/gcloud/connection.py @@ -115,8 +115,12 @@ def _create_scoped_credentials(credentials, scope): :class:`NoneType` :returns: A new credentials object that has a scope added (if needed). """ - if credentials and credentials.create_scoped_required(): - credentials = credentials.create_scoped(scope) + if credentials: + try: + if credentials.create_scoped_required(): + credentials = credentials.create_scoped(scope) + except AttributeError: + pass return credentials diff --git a/gcloud/credentials.py b/gcloud/credentials.py index 7e995bdc8597..a078fbc7921b 100644 --- a/gcloud/credentials.py +++ b/gcloud/credentials.py @@ -27,7 +27,6 @@ crypto = None from oauth2client import client -from oauth2client.client import _get_application_default_credential_from_file from oauth2client import crypt from oauth2client.service_account import ServiceAccountCredentials try: @@ -125,11 +124,8 @@ def get_for_service_account_json(json_credentials_path, scope=None): :returns: New service account or Google (for a user JSON key file) credentials object. """ - credentials = _get_application_default_credential_from_file( - json_credentials_path) - if scope is not None: - credentials = credentials.create_scoped(scope) - return credentials + return ServiceAccountCredentials.from_json_keyfile_name( + json_credentials_path, scopes=scope) def get_for_service_account_p12(client_email, private_key_path, scope=None): diff --git a/gcloud/test_connection.py b/gcloud/test_connection.py index 2b7ba10af1d8..9de078ff8e47 100644 --- a/gcloud/test_connection.py +++ b/gcloud/test_connection.py @@ -30,7 +30,9 @@ def test_ctor_defaults(self): def test_ctor_explicit(self): credentials = _Credentials() + self.assertEqual(credentials._create_scoped_calls, 0) conn = self._makeOne(credentials) + self.assertEqual(credentials._create_scoped_calls, 1) self.assertTrue(conn.credentials is credentials) self.assertEqual(conn._http, None) @@ -40,6 +42,12 @@ def test_ctor_explicit_http(self): self.assertEqual(conn.credentials, None) self.assertTrue(conn.http is http) + def test_ctor_credentials_wo_create_scoped(self): + credentials = object() + conn = self._makeOne(credentials) + self.assertTrue(conn.credentials is credentials) + self.assertEqual(conn._http, None) + def test_http_w_existing(self): conn = self._makeOne() conn._http = http = object() @@ -371,11 +379,12 @@ class _Credentials(object): def __init__(self, authorized=None): self._authorized = authorized + self._create_scoped_calls = 0 def authorize(self, http): self._called_with = http return self._authorized - @staticmethod - def create_scoped_required(): + def create_scoped_required(self): + self._create_scoped_calls += 1 return False diff --git a/gcloud/test_credentials.py b/gcloud/test_credentials.py index 1fd6ca3244ee..7cef89e20ba4 100644 --- a/gcloud/test_credentials.py +++ b/gcloud/test_credentials.py @@ -127,42 +127,26 @@ def test_it(self): from gcloud._testing import _Monkey from gcloud import credentials as MUT - CREDS = _Credentials() - _filenames = [] - - def get_creds(filename): - _filenames.append(filename) - return CREDS - FILENAME = object() + MOCK_CRED_CLASS = _MockServiceAccountCredentials() + with _Monkey(MUT, ServiceAccountCredentials=MOCK_CRED_CLASS): + result = self._callFUT(FILENAME) - renames = {'_get_application_default_credential_from_file': get_creds} - with _Monkey(MUT, **renames): - self._callFUT(FILENAME) - - self.assertEqual(_filenames, [FILENAME]) - self.assertFalse(hasattr(CREDS, '_scopes')) + self.assertEqual(result, MOCK_CRED_CLASS._result) + self.assertEqual(MOCK_CRED_CLASS.json_called, [(FILENAME, None)]) def test_it_with_scope(self): from gcloud._testing import _Monkey from gcloud import credentials as MUT - CREDS = _Credentials() - _filenames = [] - - def get_creds(filename): - _filenames.append(filename) - return CREDS - FILENAME = object() SCOPE = object() + MOCK_CRED_CLASS = _MockServiceAccountCredentials() + with _Monkey(MUT, ServiceAccountCredentials=MOCK_CRED_CLASS): + result = self._callFUT(FILENAME, scope=SCOPE) - renames = {'_get_application_default_credential_from_file': get_creds} - with _Monkey(MUT, **renames): - self._callFUT(FILENAME, scope=SCOPE) - - self.assertEqual(_filenames, [FILENAME]) - self.assertEqual(CREDS._scopes, SCOPE) + self.assertEqual(result, MOCK_CRED_CLASS._result) + self.assertEqual(MOCK_CRED_CLASS.json_called, [(FILENAME, SCOPE)]) class Test_generate_signed_url(unittest2.TestCase): @@ -604,13 +588,8 @@ def test_w_timedelta_days(self): class _Credentials(object): - service_account_name = 'testing@example.com' - def create_scoped(self, scopes): - self._scopes = scopes - return self - class _Client(object): @@ -692,8 +671,13 @@ class _MockServiceAccountCredentials(object): def __init__(self): self.p12_called = [] + self.json_called = [] self._result = _Credentials() def from_p12_keyfile(self, email, path, scopes=None): self.p12_called.append((email, path, scopes)) return self._result + + def from_json_keyfile_name(self, path, scopes=None): + self.json_called.append((path, scopes)) + return self._result