Skip to content

Commit cc086b6

Browse files
committed
Add client factories.
These factory classmethods generate credentials / connection from supplied values, paralleling the factories in 'gcloud.connection.Connection'.
1 parent 42889a5 commit cc086b6

File tree

3 files changed

+146
-7
lines changed

3 files changed

+146
-7
lines changed

docs/pubsub-usage.rst

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -282,16 +282,14 @@ Create a client using the defaults from the environment:
282282
>>> from gcloud.pubsub.client import Client
283283
>>> client = Client()
284284

285-
Create a client using an explicit connection, but the default project:
285+
Create a client using explicit credentials, but the default project:
286286

287287
.. doctest::
288288

289289
>>> from gcloud.pubsub.client import Client
290-
>>> from gcloud.pubsub.connection import Connection
291-
>>> connection = Connection.from_service_account_json('/path/to/creds.json')
292-
>>> client = Client(connection=connection)
290+
>>> client = Client.from_service_account_json('/path/to/creds.json')
293291

294-
Create a client using an explicit project ID, but the connetion inferred
292+
Create a client using an explicit project ID, but the credentials inferred
295293
from the environment:
296294

297295
.. doctest::

gcloud/pubsub/client.py

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from gcloud._helpers import _ClientProxy
2424
from gcloud.pubsub._implicit_environ import _require_connection
2525
from gcloud.pubsub import api
26+
from gcloud.pubsub.connection import Connection
2627
from gcloud.pubsub.subscription import Subscription
2728
from gcloud.pubsub.topic import Topic
2829

@@ -35,8 +36,8 @@ class Client(object):
3536
from the environment.
3637
3738
:type project: str or None
38-
:param connection: The configured project. Defaults to the value inferred
39-
from the environment.
39+
:param project: The configured project. Defaults to the value inferred
40+
from the environment.
4041
"""
4142

4243
def __init__(self, connection=None, project=None):
@@ -45,6 +46,73 @@ def __init__(self, connection=None, project=None):
4546
project = get_default_project()
4647
self.project = project
4748

49+
@classmethod
50+
def from_service_account_json(cls, json_credentials_path, project=None,
51+
*args, **kwargs):
52+
"""Factory to retrieve JSON credentials while creating connection.
53+
54+
:type json_credentials_path: string
55+
:param json_credentials_path: The path to a private key file (this file
56+
was given to you when you created the
57+
service account). This file must contain
58+
a JSON object with a private key and
59+
other credentials information (downloaded
60+
from the Google APIs console).
61+
62+
:type project: str or None
63+
:param project: The configured project. Defaults to the value inferred
64+
from the environment.
65+
66+
:rtype: :class:`gcloud.pubsub.client.Client`
67+
:returns: A client, configured with a connection created with the
68+
retrieved JSON credentials, and the supplied project.
69+
"""
70+
connection = Connection.from_service_account_json(
71+
json_credentials_path, *args, **kwargs)
72+
return cls(connection=connection, project=project)
73+
74+
@classmethod
75+
def from_service_account_p12(cls, client_email, private_key_path,
76+
project=None, *args, **kwargs):
77+
"""Factory to retrieve P12 credentials while creating connection.
78+
79+
.. note::
80+
Unless you have an explicit reason to use a PKCS12 key for your
81+
service account, we recommend using a JSON key.
82+
83+
:type client_email: string
84+
:param client_email: The e-mail attached to the service account.
85+
86+
:type private_key_path: string
87+
:param private_key_path: The path to a private key file (this file was
88+
given to you when you created the service
89+
account). This file must be in P12 format.
90+
91+
:type project: str or None
92+
:param project: The configured project. Defaults to the value inferred
93+
from the environment.
94+
95+
:rtype: :class:`gcloud.pubsub.client.Client`
96+
:returns: A client, configured with a connection created with the
97+
retrieved P12 credentials, and the supplied project.
98+
"""
99+
connection = Connection.from_service_account_p12(
100+
client_email, private_key_path, *args, **kwargs)
101+
return cls(connection=connection, project=project)
102+
103+
@classmethod
104+
def from_environment(cls, project=None, *args, **kwargs):
105+
"""Factory to retrieve implicit credentials while creating connection.
106+
107+
:rtype: :class:`gcloud.pubsub.client.Client`
108+
:returns: The connection created with the retrieved implicit
109+
credentials.
110+
:returns: A client, configured with a connection created with the
111+
retrieved implicit credentials, and the supplied project
112+
"""
113+
connection = Connection.from_environment(*args, **kwargs)
114+
return cls(connection=connection, project=project)
115+
48116
def topic(self, name):
49117
"""Proxy for :class:`gcloud.pubsub.topic.Topic`.
50118

gcloud/pubsub/test_client.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,73 @@ def test_ctor_explicit(self):
4242
self.assertTrue(client.connection is connection)
4343
self.assertEqual(client.project, PROJECT)
4444

45+
def test_from_service_account_json(self):
46+
from gcloud._testing import _Monkey
47+
from gcloud import connection
48+
49+
PROJECT = 'PROJECT'
50+
KLASS = self._getTargetClass()
51+
CREDS = _Credentials()
52+
53+
_called = []
54+
55+
def mock_creds(*args):
56+
_called.append(args)
57+
return CREDS
58+
59+
JSON_CREDS_PATH = '/path/to/credentials.json'
60+
with _Monkey(connection, get_for_service_account_json=mock_creds):
61+
client = KLASS.from_service_account_json(JSON_CREDS_PATH, PROJECT)
62+
63+
self.assertTrue(client.connection.credentials is CREDS)
64+
self.assertEqual(_called, [(JSON_CREDS_PATH,)])
65+
self.assertEqual(client.project, PROJECT)
66+
67+
def test_from_service_account_p12(self):
68+
from gcloud._testing import _Monkey
69+
from gcloud import connection
70+
71+
PROJECT = 'PROJECT'
72+
KLASS = self._getTargetClass()
73+
CREDS = _Credentials()
74+
75+
_called = []
76+
77+
def mock_creds(*args):
78+
_called.append(args)
79+
return CREDS
80+
81+
CLIENT_EMAIL = 'client@example.com'
82+
P12_PRIVKEY_PATH = '/path/to/privkey.p12'
83+
with _Monkey(connection, get_for_service_account_p12=mock_creds):
84+
client = KLASS.from_service_account_p12(
85+
CLIENT_EMAIL, P12_PRIVKEY_PATH, PROJECT)
86+
87+
self.assertTrue(client.connection.credentials is CREDS)
88+
self.assertEqual(_called, [(CLIENT_EMAIL, P12_PRIVKEY_PATH,)])
89+
self.assertEqual(client.project, PROJECT)
90+
91+
def test_from_environment(self):
92+
from gcloud._testing import _Monkey
93+
from gcloud import connection
94+
95+
PROJECT = 'PROJECT'
96+
KLASS = self._getTargetClass()
97+
CREDS = _Credentials()
98+
99+
_called = []
100+
101+
def mock_creds(*args):
102+
_called.append(args)
103+
return CREDS
104+
105+
with _Monkey(connection, get_credentials=mock_creds):
106+
client = KLASS.from_environment(PROJECT)
107+
108+
self.assertTrue(client.connection.credentials is CREDS)
109+
self.assertEqual(_called, [()])
110+
self.assertEqual(client.project, PROJECT)
111+
45112
def test_topic(self):
46113
from gcloud.pubsub.client import _Topic
47114
from gcloud.pubsub.topic import Topic
@@ -224,3 +291,9 @@ class _Dummy(object):
224291

225292
def __init__(self, **kw):
226293
self.__dict__.update(kw)
294+
295+
296+
class _Credentials(object):
297+
298+
def create_scoped_required(self):
299+
return False

0 commit comments

Comments
 (0)