Skip to content

Commit 3fc744c

Browse files
authored
Merge pull request #3148 from dhermes/make-ds-gapic-emulator
Adding (back) support for datastore emulator.
2 parents 68a2a90 + 85eaeae commit 3fc744c

File tree

4 files changed

+59
-12
lines changed

4 files changed

+59
-12
lines changed

datastore/google/cloud/datastore/_gax.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from google.gax.errors import GaxError
2323
from google.gax.grpc import exc_to_code
2424
from google.gax.utils import metrics
25+
from grpc import insecure_channel
2526
from grpc import StatusCode
2627
import six
2728

@@ -131,8 +132,14 @@ def make_datastore_api(client):
131132
:rtype: :class:`.datastore.v1.datastore_client.DatastoreClient`
132133
:returns: A datastore API instance with the proper credentials.
133134
"""
134-
channel = make_secure_channel(
135-
client._credentials, DEFAULT_USER_AGENT,
136-
datastore_client.DatastoreClient.SERVICE_ADDRESS)
135+
parse_result = six.moves.urllib_parse.urlparse(
136+
client._base_url)
137+
host = parse_result.netloc
138+
if parse_result.scheme == 'https':
139+
channel = make_secure_channel(
140+
client._credentials, DEFAULT_USER_AGENT, host)
141+
else:
142+
channel = insecure_channel(host)
143+
137144
return GAPICDatastoreAPI(
138145
channel=channel, lib_name='gccl', lib_version=__version__)

datastore/unit_tests/test__gax.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,19 +158,44 @@ def _call_fut(self, client):
158158
return_value=mock.sentinel.ds_client)
159159
@mock.patch('google.cloud.datastore._gax.make_secure_channel',
160160
return_value=mock.sentinel.channel)
161-
def test_it(self, make_chan, mock_klass):
161+
def test_live_api(self, make_chan, mock_klass):
162162
from google.cloud.gapic.datastore.v1 import datastore_client
163163
from google.cloud._http import DEFAULT_USER_AGENT
164164
from google.cloud.datastore import __version__
165165

166+
host = datastore_client.DatastoreClient.SERVICE_ADDRESS
167+
base_url = 'https://' + host
166168
client = mock.Mock(
167-
_credentials=mock.sentinel.credentials, spec=['_credentials'])
169+
_base_url=base_url,
170+
_credentials=mock.sentinel.credentials,
171+
spec=['_base_url', '_credentials'])
168172
ds_api = self._call_fut(client)
169173
self.assertIs(ds_api, mock.sentinel.ds_client)
170174

171175
make_chan.assert_called_once_with(
172-
mock.sentinel.credentials, DEFAULT_USER_AGENT,
173-
datastore_client.DatastoreClient.SERVICE_ADDRESS)
176+
mock.sentinel.credentials, DEFAULT_USER_AGENT, host)
177+
mock_klass.assert_called_once_with(
178+
channel=mock.sentinel.channel, lib_name='gccl',
179+
lib_version=__version__)
180+
181+
@mock.patch(
182+
'google.cloud.datastore._gax.GAPICDatastoreAPI',
183+
return_value=mock.sentinel.ds_client)
184+
@mock.patch('google.cloud.datastore._gax.insecure_channel',
185+
return_value=mock.sentinel.channel)
186+
def test_emulator(self, make_chan, mock_klass):
187+
from google.cloud.datastore import __version__
188+
189+
host = 'localhost:8901'
190+
base_url = 'http://' + host
191+
client = mock.Mock(
192+
_base_url=base_url,
193+
_credentials=mock.sentinel.credentials,
194+
spec=['_base_url', '_credentials'])
195+
ds_api = self._call_fut(client)
196+
self.assertIs(ds_api, mock.sentinel.ds_client)
197+
198+
make_chan.assert_called_once_with(host)
174199
mock_klass.assert_called_once_with(
175200
channel=mock.sentinel.channel, lib_name='gccl',
176201
lib_version=__version__)

system_tests/system_test_utils.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import sys
1818
import time
1919

20+
import google.auth.credentials
2021
from google.auth.environment_vars import CREDENTIALS as TEST_CREDENTIALS
2122

2223

@@ -29,16 +30,28 @@
2930
"""
3031

3132

32-
class EmulatorCreds(object):
33+
class EmulatorCreds(google.auth.credentials.Credentials):
3334
"""A mock credential object.
3435
3536
Used to avoid unnecessary token refreshing or reliance on the network
3637
while an emulator is running.
3738
"""
3839

39-
@staticmethod
40-
def create_scoped_required():
41-
return False
40+
def __init__(self): # pylint: disable=super-init-not-called
41+
self.token = b'seekrit'
42+
self.expiry = None
43+
44+
@property
45+
def valid(self):
46+
"""Would-be validity check of the credentials.
47+
48+
Always is :data:`True`.
49+
"""
50+
return True
51+
52+
def refresh(self, unused_request): # pylint: disable=unused-argument
53+
"""Off-limits implementation for abstract method."""
54+
raise RuntimeError('Should never be refreshed.')
4255

4356

4457
def check_environ():

tox.ini

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,9 @@ commands =
300300
{[emulator]emulatorcmd} --package=datastore
301301
setenv = {[emulator]setenv}
302302
passenv = {[testing]passenv}
303-
deps = {[emulator]deps}
303+
deps =
304+
{[emulator]deps}
305+
Sphinx
304306

305307
[testenv:pubsub-emulator]
306308
commands =

0 commit comments

Comments
 (0)