Skip to content

Commit 7bcd9dc

Browse files
chore: move _auth_init out of Instance class (#589)
1 parent a31077e commit 7bcd9dc

File tree

5 files changed

+57
-66
lines changed

5 files changed

+57
-66
lines changed

google/cloud/sql/connector/instance.py

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
_seconds_until_refresh,
2323
_is_valid,
2424
)
25-
from google.cloud.sql.connector.utils import write_to_file
25+
from google.cloud.sql.connector.utils import write_to_file, _auth_init
2626
from google.cloud.sql.connector.version import __version__ as version
2727
from google.cloud.sql.connector.exceptions import (
2828
TLSVersionError,
@@ -36,11 +36,9 @@
3636
import aiohttp
3737
import datetime
3838
from enum import Enum
39-
import google.auth
40-
from google.auth.credentials import Credentials, with_scopes_if_required
39+
from google.auth.credentials import Credentials
4140
from cryptography.x509 import load_pem_x509_certificate
4241
from cryptography.hazmat.backends import default_backend
43-
import google.auth.transport.requests
4442
import ssl
4543
from tempfile import TemporaryDirectory
4644
from typing import (
@@ -249,35 +247,14 @@ def __init__(
249247
"Arg credentials must be type 'google.auth.credentials.Credentials' "
250248
"or None (to use Application Default Credentials)"
251249
)
252-
253-
self._auth_init(credentials)
254-
250+
self._credentials = _auth_init(credentials)
255251
self._refresh_rate_limiter = AsyncRateLimiter(
256252
max_capacity=2, rate=1 / 30, loop=self._loop
257253
)
258254
self._refresh_in_progress = asyncio.locks.Event()
259255
self._current = self._schedule_refresh(0)
260256
self._next = self._current
261257

262-
def _auth_init(self, credentials: Optional[Credentials]) -> None:
263-
"""Creates and assigns a Google Python API service object for
264-
Google Cloud SQL Admin API.
265-
266-
:type credentials: google.auth.credentials.Credentials
267-
:param credentials
268-
Credentials object used to authenticate connections to Cloud SQL server.
269-
If not specified, Application Default Credentials are used.
270-
"""
271-
scopes = ["https://www.googleapis.com/auth/sqlservice.admin"]
272-
# if Credentials object is passed in, use for authentication
273-
if isinstance(credentials, Credentials):
274-
credentials = with_scopes_if_required(credentials, scopes=scopes)
275-
# otherwise use application default credentials
276-
else:
277-
credentials, project = google.auth.default(scopes=scopes)
278-
279-
self._credentials = credentials
280-
281258
def force_refresh(self) -> None:
282259
"""
283260
Forces a new refresh attempt immediately to be used for future connection attempts.

google/cloud/sql/connector/utils.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
from cryptography.hazmat.backends import default_backend
1818
from cryptography.hazmat.primitives import serialization
1919
from cryptography.hazmat.primitives.asymmetric import rsa
20+
from google.auth import default
21+
from google.auth.credentials import Credentials, with_scopes_if_required
2022

21-
from typing import Tuple
23+
from typing import Tuple, Optional
2224

2325

2426
async def generate_keys() -> Tuple[bytes, str]:
@@ -102,3 +104,23 @@ def format_database_user(database_version: str, user: str) -> str:
102104
return user.split("@")[0]
103105

104106
return user
107+
108+
109+
def _auth_init(credentials: Optional[Credentials]) -> Credentials:
110+
"""Creates google.auth credentials object with scopes required to make
111+
calls to the Cloud SQL Admin APIs.
112+
113+
:type credentials: google.auth.credentials.Credentials
114+
:param credentials
115+
Credentials object used to authenticate connections to Cloud SQL server.
116+
If not specified, Application Default Credentials are used.
117+
"""
118+
scopes = ["https://www.googleapis.com/auth/sqlservice.admin"]
119+
# if Credentials object is passed in, use for authentication
120+
if isinstance(credentials, Credentials):
121+
credentials = with_scopes_if_required(credentials, scopes=scopes)
122+
# otherwise use application default credentials
123+
else:
124+
credentials, _ = default(scopes=scopes)
125+
126+
return credentials

tests/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ async def instance(
154154
keys = event_loop.create_task(generate_keys())
155155
_, client_key = await keys
156156

157-
with patch("google.auth.default") as mock_auth:
157+
with patch("google.cloud.sql.connector.utils.default") as mock_auth:
158158
mock_auth.return_value = fake_credentials, None
159159
# mock Cloud SQL Admin API calls
160160
with aioresponses() as mocked:
@@ -188,7 +188,7 @@ async def connector(fake_credentials: Credentials) -> AsyncGenerator[Connector,
188188
project, region, instance_name = instance_connection_name.split(":")
189189
# initialize connector
190190
connector = Connector()
191-
with patch("google.auth.default") as mock_auth:
191+
with patch("google.cloud.sql.connector.utils.default") as mock_auth:
192192
mock_auth.return_value = fake_credentials, None
193193
# mock Cloud SQL Admin API calls
194194
mock_instance = FakeCSQLInstance(project, region, instance_name)

tests/unit/test_instance.py

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ async def test_Instance_init(
5656
keys = asyncio.wrap_future(
5757
asyncio.run_coroutine_threadsafe(generate_keys(), event_loop), loop=event_loop
5858
)
59-
with patch("google.auth.default") as mock_auth:
59+
with patch("google.cloud.sql.connector.utils.default") as mock_auth:
6060
mock_auth.return_value = fake_credentials, None
6161
instance = Instance(connect_string, "pymysql", keys, event_loop)
6262
project_result = instance._project
@@ -206,42 +206,6 @@ async def test_force_refresh_cancels_pending_refresh(
206206
assert isinstance(await instance._current, InstanceMetadata)
207207

208208

209-
@pytest.mark.asyncio
210-
async def test_auth_init_with_credentials_object(
211-
instance: Instance, fake_credentials: Credentials
212-
) -> None:
213-
"""
214-
Test that Instance's _auth_init initializes _credentials
215-
when passed a google.auth.credentials.Credentials object.
216-
"""
217-
setattr(instance, "_credentials", None)
218-
with patch(
219-
"google.cloud.sql.connector.instance.with_scopes_if_required"
220-
) as mock_auth:
221-
mock_auth.return_value = fake_credentials
222-
instance._auth_init(credentials=fake_credentials)
223-
assert isinstance(instance._credentials, Credentials)
224-
mock_auth.assert_called_once()
225-
await instance.close()
226-
227-
228-
@pytest.mark.asyncio
229-
async def test_auth_init_with_default_credentials(
230-
instance: Instance, fake_credentials: Credentials
231-
) -> None:
232-
"""
233-
Test that Instance's _auth_init initializes _credentials
234-
with application default credentials when credentials are not specified.
235-
"""
236-
setattr(instance, "_credentials", None)
237-
with patch("google.auth.default") as mock_auth:
238-
mock_auth.return_value = fake_credentials, None
239-
instance._auth_init(credentials=None)
240-
assert isinstance(instance._credentials, Credentials)
241-
mock_auth.assert_called_once()
242-
await instance.close()
243-
244-
245209
@pytest.mark.asyncio
246210
async def test_Instance_close(instance: Instance) -> None:
247211
"""

tests/unit/test_utils.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
"""
1616

1717
from google.cloud.sql.connector import utils
18+
from google.auth.credentials import Credentials
19+
from mock import patch
1820

1921
import pytest # noqa F401 Needed to run the tests
2022

@@ -75,3 +77,29 @@ def test_format_database_user_mysql() -> None:
7577
user2 = utils.format_database_user("MYSQL_8_0", "test")
7678
assert user == "test"
7779
assert user2 == "test"
80+
81+
82+
def test_auth_init_with_credentials_object(fake_credentials: Credentials) -> None:
83+
"""
84+
Test that _auth_init initializes credentials with scopes
85+
when passed a google.auth.credentials.Credentials object.
86+
"""
87+
with patch("google.cloud.sql.connector.utils.with_scopes_if_required") as mock_auth:
88+
mock_auth.return_value = fake_credentials
89+
credentials = utils._auth_init(credentials=fake_credentials)
90+
assert isinstance(credentials, Credentials)
91+
mock_auth.assert_called_once()
92+
93+
94+
def test_auth_init_with_default_credentials(
95+
fake_credentials: Credentials,
96+
) -> None:
97+
"""
98+
Test that _auth_init initializes _credentials
99+
with application default credentials when credentials are not specified.
100+
"""
101+
with patch("google.cloud.sql.connector.utils.default") as mock_auth:
102+
mock_auth.return_value = fake_credentials, None
103+
credentials = utils._auth_init(credentials=None)
104+
assert isinstance(credentials, Credentials)
105+
mock_auth.assert_called_once()

0 commit comments

Comments
 (0)