From 26dc1ea3a965c81357cf3f9e206ae054b45b751c Mon Sep 17 00:00:00 2001 From: jackwotherspoon Date: Mon, 20 Dec 2021 18:17:17 +0000 Subject: [PATCH 1/8] feat: add support for service account key files --- google/cloud/sql/connector/connector.py | 12 +++++++-- .../connector/instance_connection_manager.py | 27 ++++++++++++------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/google/cloud/sql/connector/connector.py b/google/cloud/sql/connector/connector.py index 06168b29..92a57db0 100755 --- a/google/cloud/sql/connector/connector.py +++ b/google/cloud/sql/connector/connector.py @@ -23,7 +23,7 @@ from google.cloud.sql.connector.utils import generate_keys from threading import Thread -from typing import Any, Dict +from typing import Any, Dict, Optional logger = logging.getLogger(name=__name__) @@ -43,9 +43,14 @@ class Connector: Enables IAM based authentication (Postgres only). :type timeout: int - :param timeout: + :param timeout The time limit for a connection before raising a TimeoutError. + :type service_account_file: Optional (str) + :param service_account_file + Path to JSON service account key file to be used for authentication. + If not specified, Application Default Credentials are used. + """ def __init__( @@ -53,6 +58,7 @@ def __init__( ip_types: IPTypes = IPTypes.PUBLIC, enable_iam_auth: bool = False, timeout: int = 30, + service_account_file: Optional[str] = None, ) -> None: self._loop: asyncio.AbstractEventLoop = asyncio.new_event_loop() self._thread: Thread = Thread(target=self._loop.run_forever, daemon=True) @@ -66,6 +72,7 @@ def __init__( self._timeout = timeout self._enable_iam_auth = enable_iam_auth self._ip_types = ip_types + self._service_account_file = service_account_file def connect( self, instance_connection_string: str, driver: str, **kwargs: Any @@ -112,6 +119,7 @@ def connect( driver, self._keys, self._loop, + self._service_account_file, enable_iam_auth, ) self._instances[instance_connection_string] = icm diff --git a/google/cloud/sql/connector/instance_connection_manager.py b/google/cloud/sql/connector/instance_connection_manager.py index d19ceaf7..88c32afd 100644 --- a/google/cloud/sql/connector/instance_connection_manager.py +++ b/google/cloud/sql/connector/instance_connection_manager.py @@ -229,6 +229,7 @@ def __init__( driver_name: str, keys: concurrent.futures.Future, loop: asyncio.AbstractEventLoop, + service_account_file: Optional[str], enable_iam_auth: bool = False, ) -> None: # Validate connection string @@ -250,7 +251,7 @@ def __init__( self._user_agent_string = f"{APPLICATION_NAME}/{version}+{driver_name}" self._loop = loop self._keys = asyncio.wrap_future(keys, loop=self._loop) - self._auth_init() + self._auth_init(service_account_file) self._refresh_rate_limiter = AsyncRateLimiter( max_capacity=2, rate=1 / 30, loop=self._loop @@ -343,17 +344,25 @@ async def _get_instance_data(self) -> InstanceMetadata: self._enable_iam_auth, ) - def _auth_init(self) -> None: + def _auth_init(self, service_account_file) -> None: """Creates and assigns a Google Python API service object for Google Cloud SQL Admin API. - """ - credentials, project = google.auth.default( - scopes=[ - "https://www.googleapis.com/auth/sqlservice.admin", - "https://www.googleapis.com/auth/cloud-platform", - ] - ) + :type service_account_file: Optional (str) + :param service_account_file + Path to JSON service account key file to be used for authentication. + If not specified, Application Default Credentials are used. + """ + scopes = [ + "https://www.googleapis.com/auth/sqlservice.admin", + "https://www.googleapis.com/auth/cloud-platform", + ] + if service_account_file: + credentials, project = google.auth.load_credentials_from_file( + filename=service_account_file, scopes=scopes + ) + else: + credentials, project = google.auth.default(scopes=scopes) self._credentials = credentials From 908687854a291977c1e5fb77be65ba97f1b4406a Mon Sep 17 00:00:00 2001 From: jackwotherspoon Date: Mon, 20 Dec 2021 21:05:40 +0000 Subject: [PATCH 2/8] chore: add ability to pass in credentials object --- google/cloud/sql/connector/connector.py | 15 +++++------ .../connector/instance_connection_manager.py | 26 ++++++++++++------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/google/cloud/sql/connector/connector.py b/google/cloud/sql/connector/connector.py index 92a57db0..a142667b 100755 --- a/google/cloud/sql/connector/connector.py +++ b/google/cloud/sql/connector/connector.py @@ -21,9 +21,9 @@ IPTypes, ) from google.cloud.sql.connector.utils import generate_keys - +from google.auth.credentials import Credentials from threading import Thread -from typing import Any, Dict, Optional +from typing import Any, Dict, Union logger = logging.getLogger(name=__name__) @@ -46,11 +46,10 @@ class Connector: :param timeout The time limit for a connection before raising a TimeoutError. - :type service_account_file: Optional (str) - :param service_account_file + :type service_account_creds: Optional (str) + :param service_account_creds Path to JSON service account key file to be used for authentication. If not specified, Application Default Credentials are used. - """ def __init__( @@ -58,7 +57,7 @@ def __init__( ip_types: IPTypes = IPTypes.PUBLIC, enable_iam_auth: bool = False, timeout: int = 30, - service_account_file: Optional[str] = None, + service_account_creds: Union[str, Credentials, None] = None, ) -> None: self._loop: asyncio.AbstractEventLoop = asyncio.new_event_loop() self._thread: Thread = Thread(target=self._loop.run_forever, daemon=True) @@ -72,7 +71,7 @@ def __init__( self._timeout = timeout self._enable_iam_auth = enable_iam_auth self._ip_types = ip_types - self._service_account_file = service_account_file + self._service_account_creds = service_account_creds def connect( self, instance_connection_string: str, driver: str, **kwargs: Any @@ -119,7 +118,7 @@ def connect( driver, self._keys, self._loop, - self._service_account_file, + self._service_account_creds, enable_iam_auth, ) self._instances[instance_connection_string] = icm diff --git a/google/cloud/sql/connector/instance_connection_manager.py b/google/cloud/sql/connector/instance_connection_manager.py index 88c32afd..37fc12ec 100644 --- a/google/cloud/sql/connector/instance_connection_manager.py +++ b/google/cloud/sql/connector/instance_connection_manager.py @@ -27,7 +27,7 @@ import datetime from enum import Enum import google.auth -from google.auth.credentials import Credentials +from google.auth.credentials import Credentials, with_scopes_if_required import google.auth.transport.requests import OpenSSL import platform @@ -39,6 +39,7 @@ Awaitable, Dict, Optional, + Union, TYPE_CHECKING, ) @@ -229,7 +230,7 @@ def __init__( driver_name: str, keys: concurrent.futures.Future, loop: asyncio.AbstractEventLoop, - service_account_file: Optional[str], + service_account_creds: Union[str, Credentials, None] = None, enable_iam_auth: bool = False, ) -> None: # Validate connection string @@ -251,7 +252,7 @@ def __init__( self._user_agent_string = f"{APPLICATION_NAME}/{version}+{driver_name}" self._loop = loop self._keys = asyncio.wrap_future(keys, loop=self._loop) - self._auth_init(service_account_file) + self._auth_init(service_account_creds) self._refresh_rate_limiter = AsyncRateLimiter( max_capacity=2, rate=1 / 30, loop=self._loop @@ -344,23 +345,30 @@ async def _get_instance_data(self) -> InstanceMetadata: self._enable_iam_auth, ) - def _auth_init(self, service_account_file) -> None: + def _auth_init(self, service_account_creds) -> None: """Creates and assigns a Google Python API service object for Google Cloud SQL Admin API. - :type service_account_file: Optional (str) - :param service_account_file - Path to JSON service account key file to be used for authentication. + :type service_account_creds: + Optional [str | google.auth.credentials.Credentials] + :param service_account_creds + Path to JSON service account key file to be used for authentication + or google.auth.credentials.Credentials object. If not specified, Application Default Credentials are used. """ scopes = [ "https://www.googleapis.com/auth/sqlservice.admin", "https://www.googleapis.com/auth/cloud-platform", ] - if service_account_file: + # if Credentials object is passed in, use for authentication + if isinstance(service_account_creds, Credentials): + credentials = with_scopes_if_required(service_account_creds, scopes=scopes) + # if string is passed in, load credentials from file + elif isinstance(service_account_creds, str): credentials, project = google.auth.load_credentials_from_file( - filename=service_account_file, scopes=scopes + filename=service_account_creds, scopes=scopes ) + # otherwise use application default credentials else: credentials, project = google.auth.default(scopes=scopes) From d5c872d9b89a2c2bec2b00c6e03d88a37c17d8f4 Mon Sep 17 00:00:00 2001 From: jackwotherspoon Date: Tue, 21 Dec 2021 23:02:03 +0000 Subject: [PATCH 3/8] chore: add unit test and error message for service account creds --- .../connector/instance_connection_manager.py | 28 ++++++++ .../unit/test_instance_connection_manager.py | 71 +++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/google/cloud/sql/connector/instance_connection_manager.py b/google/cloud/sql/connector/instance_connection_manager.py index 37fc12ec..3f5c0d80 100644 --- a/google/cloud/sql/connector/instance_connection_manager.py +++ b/google/cloud/sql/connector/instance_connection_manager.py @@ -118,6 +118,15 @@ def __init__(self, *args: Any) -> None: super(PlatformNotSupportedError, self).__init__(self, *args) +class ServiceAccountCredentialsTypeError(Exception): + """ + Raised when service account credentials type is not proper type. + """ + + def __init__(self, *args: Any) -> None: + super(ServiceAccountCredentialsTypeError, self).__init__(self, *args) + + class InstanceMetadata: ip_addrs: Dict[str, Any] context: ssl.SSLContext @@ -178,6 +187,13 @@ class InstanceConnectionManager: The user agent string to append to SQLAdmin API requests :type user_agent_string: str + :type service_account_creds: + Optional [str | google.auth.credentials.Credentials] + :param service_account_creds + Path to JSON service account key file to be used for authentication + or google.auth.credentials.Credentials object. + If not specified, Application Default Credentials are used. + :param enable_iam_auth Enables IAM based authentication for Postgres instances. :type enable_iam_auth: bool @@ -252,6 +268,18 @@ def __init__( self._user_agent_string = f"{APPLICATION_NAME}/{version}+{driver_name}" self._loop = loop self._keys = asyncio.wrap_future(keys, loop=self._loop) + # validate credentials type + if ( + not isinstance(service_account_creds, str) + and not isinstance(service_account_creds, Credentials) + and service_account_creds is not None + ): + raise ServiceAccountCredentialsTypeError( + "Arg service_account_creds must be type 'str' (path to valid credentials " + "key file), or type 'google.auth.credentials.Credentials' or None " + "(Application Default Credentials)" + ) + self._auth_init(service_account_creds) self._refresh_rate_limiter = AsyncRateLimiter( diff --git a/tests/unit/test_instance_connection_manager.py b/tests/unit/test_instance_connection_manager.py index 2a906ecc..8586df45 100644 --- a/tests/unit/test_instance_connection_manager.py +++ b/tests/unit/test_instance_connection_manager.py @@ -15,16 +15,25 @@ """ import asyncio +from unittest import mock +from unittest.mock import Mock, patch import datetime from google.cloud.sql.connector.rate_limiter import AsyncRateLimiter from typing import Any import pytest # noqa F401 Needed to run the tests +from google.auth.credentials import Credentials from google.cloud.sql.connector.instance_connection_manager import ( InstanceConnectionManager, + ServiceAccountCredentialsTypeError, ) from google.cloud.sql.connector.utils import generate_keys +@pytest.fixture +def mock_credentials() -> Credentials: + return Mock(spec=Credentials) + + @pytest.fixture def icm( async_loop: asyncio.AbstractEventLoop, connect_string: str @@ -73,6 +82,21 @@ def test_InstanceConnectionManager_init(async_loop: asyncio.AbstractEventLoop) - ) +def test_InstanceConnectionManager_init_bad_service_account_creds( + async_loop: asyncio.AbstractEventLoop, +) -> None: + """ + Test to check whether the __init__ method of InstanceConnectionManager + throws proper error for bad service_account_creds arg type. + """ + connect_string = "test-project:test-region:test-instance" + keys = asyncio.run_coroutine_threadsafe(generate_keys(), async_loop) + with pytest.raises(ServiceAccountCredentialsTypeError): + assert InstanceConnectionManager( + connect_string, "pymysql", keys, async_loop, service_account_creds=1 + ) + + @pytest.mark.asyncio async def test_perform_refresh_replaces_result( icm: InstanceConnectionManager, test_rate_limiter: AsyncRateLimiter @@ -171,3 +195,50 @@ async def test_force_refresh_cancels_pending_refresh( assert pending_refresh.cancelled() is True assert isinstance(icm._current.result(), MockMetadata) + + +def test_auth_init_with_credentials_object( + icm: InstanceConnectionManager, mock_credentials: Credentials +) -> None: + """ + Test that InstanceConnectionManager's _auth_init initializes _credentials + when passed a google.auth.credentials.Credentials object. + """ + setattr(icm, "_credentials", None) + with patch( + "google.cloud.sql.connector.instance_connection_manager.with_scopes_if_required" + ) as mock_auth: + mock_auth.return_value = mock_credentials + icm._auth_init(service_account_creds=mock_credentials) + assert isinstance(icm._credentials, Credentials) + mock_auth.assert_called_once() + + +def test_auth_init_with_credentials_file( + icm: InstanceConnectionManager, mock_credentials: Credentials +) -> None: + """ + Test that InstanceConnectionManager's _auth_init initializes _credentials + when passed a service account key file. + """ + setattr(icm, "_credentials", None) + with patch("google.auth.load_credentials_from_file") as mock_auth: + mock_auth.return_value = mock_credentials, None + icm._auth_init(service_account_creds="credentials.json") + assert isinstance(icm._credentials, Credentials) + mock_auth.assert_called_once() + + +def test_auth_init_with_default_credentials( + icm: InstanceConnectionManager, mock_credentials: Credentials +) -> None: + """ + Test that InstanceConnectionManager's _auth_init initializes _credentials + with application default credentials when credentials are not specified. + """ + setattr(icm, "_credentials", None) + with patch("google.auth.default") as mock_auth: + mock_auth.return_value = mock_credentials, None + icm._auth_init(service_account_creds=None) + assert isinstance(icm._credentials, Credentials) + mock_auth.assert_called_once() From 8abefbcfb947a681df58bb4f05f4435cbc5505a5 Mon Sep 17 00:00:00 2001 From: jackwotherspoon Date: Tue, 21 Dec 2021 23:08:57 +0000 Subject: [PATCH 4/8] chore: update doc strings --- google/cloud/sql/connector/connector.py | 6 ++++-- google/cloud/sql/connector/instance_connection_manager.py | 3 +-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/google/cloud/sql/connector/connector.py b/google/cloud/sql/connector/connector.py index a142667b..bb24ce1a 100755 --- a/google/cloud/sql/connector/connector.py +++ b/google/cloud/sql/connector/connector.py @@ -46,9 +46,11 @@ class Connector: :param timeout The time limit for a connection before raising a TimeoutError. - :type service_account_creds: Optional (str) + :type service_account_creds: + Optional [str | google.auth.credentials.Credentials] :param service_account_creds - Path to JSON service account key file to be used for authentication. + Path to JSON service account key file to be used for authentication + or google.auth.credentials.Credentials object. If not specified, Application Default Credentials are used. """ diff --git a/google/cloud/sql/connector/instance_connection_manager.py b/google/cloud/sql/connector/instance_connection_manager.py index 3f5c0d80..a86cbace 100644 --- a/google/cloud/sql/connector/instance_connection_manager.py +++ b/google/cloud/sql/connector/instance_connection_manager.py @@ -377,8 +377,7 @@ def _auth_init(self, service_account_creds) -> None: """Creates and assigns a Google Python API service object for Google Cloud SQL Admin API. - :type service_account_creds: - Optional [str | google.auth.credentials.Credentials] + :type service_account_creds: str | google.auth.credentials.Credentials | None :param service_account_creds Path to JSON service account key file to be used for authentication or google.auth.credentials.Credentials object. From 7f3b06af2982e745644d65b16299ab799150afca Mon Sep 17 00:00:00 2001 From: jackwotherspoon Date: Tue, 21 Dec 2021 23:12:16 +0000 Subject: [PATCH 5/8] chore: remove unused import --- tests/unit/test_instance_connection_manager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/test_instance_connection_manager.py b/tests/unit/test_instance_connection_manager.py index 8586df45..4aa6571d 100644 --- a/tests/unit/test_instance_connection_manager.py +++ b/tests/unit/test_instance_connection_manager.py @@ -15,7 +15,6 @@ """ import asyncio -from unittest import mock from unittest.mock import Mock, patch import datetime from google.cloud.sql.connector.rate_limiter import AsyncRateLimiter From 1e6353e115d9fc40dc7e01723430cdce2a459918 Mon Sep 17 00:00:00 2001 From: jackwotherspoon Date: Wed, 22 Dec 2021 15:14:57 +0000 Subject: [PATCH 6/8] chore: add type hint --- google/cloud/sql/connector/instance_connection_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google/cloud/sql/connector/instance_connection_manager.py b/google/cloud/sql/connector/instance_connection_manager.py index a86cbace..aaf1a47f 100644 --- a/google/cloud/sql/connector/instance_connection_manager.py +++ b/google/cloud/sql/connector/instance_connection_manager.py @@ -373,7 +373,7 @@ async def _get_instance_data(self) -> InstanceMetadata: self._enable_iam_auth, ) - def _auth_init(self, service_account_creds) -> None: + def _auth_init(self, service_account_creds: Union[str, Credentials, None]) -> None: """Creates and assigns a Google Python API service object for Google Cloud SQL Admin API. From 4465ba07b9c3b40d06164f5bedb03489fa4a4dc2 Mon Sep 17 00:00:00 2001 From: jackwotherspoon Date: Thu, 23 Dec 2021 15:50:32 +0000 Subject: [PATCH 7/8] chore: update param name and remove creds from file --- google/cloud/sql/connector/connector.py | 16 +++--- .../connector/instance_connection_manager.py | 50 +++++++------------ .../unit/test_instance_connection_manager.py | 25 ++-------- 3 files changed, 30 insertions(+), 61 deletions(-) diff --git a/google/cloud/sql/connector/connector.py b/google/cloud/sql/connector/connector.py index bb24ce1a..1fc092dd 100755 --- a/google/cloud/sql/connector/connector.py +++ b/google/cloud/sql/connector/connector.py @@ -23,7 +23,7 @@ from google.cloud.sql.connector.utils import generate_keys from google.auth.credentials import Credentials from threading import Thread -from typing import Any, Dict, Union +from typing import Any, Dict, Optional logger = logging.getLogger(name=__name__) @@ -46,11 +46,9 @@ class Connector: :param timeout The time limit for a connection before raising a TimeoutError. - :type service_account_creds: - Optional [str | google.auth.credentials.Credentials] - :param service_account_creds - Path to JSON service account key file to be used for authentication - or google.auth.credentials.Credentials object. + :type credentials: google.auth.credentials.Credentials + :param credentials + Credentials object used to authenticate connections to Cloud SQL server. If not specified, Application Default Credentials are used. """ @@ -59,7 +57,7 @@ def __init__( ip_types: IPTypes = IPTypes.PUBLIC, enable_iam_auth: bool = False, timeout: int = 30, - service_account_creds: Union[str, Credentials, None] = None, + credentials: Optional[Credentials] = None, ) -> None: self._loop: asyncio.AbstractEventLoop = asyncio.new_event_loop() self._thread: Thread = Thread(target=self._loop.run_forever, daemon=True) @@ -73,7 +71,7 @@ def __init__( self._timeout = timeout self._enable_iam_auth = enable_iam_auth self._ip_types = ip_types - self._service_account_creds = service_account_creds + self._credentials = credentials def connect( self, instance_connection_string: str, driver: str, **kwargs: Any @@ -120,7 +118,7 @@ def connect( driver, self._keys, self._loop, - self._service_account_creds, + self._credentials, enable_iam_auth, ) self._instances[instance_connection_string] = icm diff --git a/google/cloud/sql/connector/instance_connection_manager.py b/google/cloud/sql/connector/instance_connection_manager.py index aaf1a47f..d4c6169f 100644 --- a/google/cloud/sql/connector/instance_connection_manager.py +++ b/google/cloud/sql/connector/instance_connection_manager.py @@ -39,7 +39,6 @@ Awaitable, Dict, Optional, - Union, TYPE_CHECKING, ) @@ -118,13 +117,13 @@ def __init__(self, *args: Any) -> None: super(PlatformNotSupportedError, self).__init__(self, *args) -class ServiceAccountCredentialsTypeError(Exception): +class CredentialsTypeError(Exception): """ - Raised when service account credentials type is not proper type. + Raised when credentials parameter is not proper type. """ def __init__(self, *args: Any) -> None: - super(ServiceAccountCredentialsTypeError, self).__init__(self, *args) + super(CredentialsTypeError, self).__init__(self, *args) class InstanceMetadata: @@ -187,11 +186,9 @@ class InstanceConnectionManager: The user agent string to append to SQLAdmin API requests :type user_agent_string: str - :type service_account_creds: - Optional [str | google.auth.credentials.Credentials] - :param service_account_creds - Path to JSON service account key file to be used for authentication - or google.auth.credentials.Credentials object. + :type credentials: google.auth.credentials.Credentials + :param credentials + Credentials object used to authenticate connections to Cloud SQL server. If not specified, Application Default Credentials are used. :param enable_iam_auth @@ -246,7 +243,7 @@ def __init__( driver_name: str, keys: concurrent.futures.Future, loop: asyncio.AbstractEventLoop, - service_account_creds: Union[str, Credentials, None] = None, + credentials: Optional[Credentials] = None, enable_iam_auth: bool = False, ) -> None: # Validate connection string @@ -269,18 +266,13 @@ def __init__( self._loop = loop self._keys = asyncio.wrap_future(keys, loop=self._loop) # validate credentials type - if ( - not isinstance(service_account_creds, str) - and not isinstance(service_account_creds, Credentials) - and service_account_creds is not None - ): - raise ServiceAccountCredentialsTypeError( - "Arg service_account_creds must be type 'str' (path to valid credentials " - "key file), or type 'google.auth.credentials.Credentials' or None " - "(Application Default Credentials)" + if not isinstance(credentials, Credentials) and credentials is not None: + raise CredentialsTypeError( + "Arg credentials must be type 'google.auth.credentials.Credentials' " + "or None (to use Application Default Credentials)" ) - self._auth_init(service_account_creds) + self._auth_init(credentials) self._refresh_rate_limiter = AsyncRateLimiter( max_capacity=2, rate=1 / 30, loop=self._loop @@ -373,14 +365,13 @@ async def _get_instance_data(self) -> InstanceMetadata: self._enable_iam_auth, ) - def _auth_init(self, service_account_creds: Union[str, Credentials, None]) -> None: + def _auth_init(self, credentials: Optional[Credentials]) -> None: """Creates and assigns a Google Python API service object for Google Cloud SQL Admin API. - :type service_account_creds: str | google.auth.credentials.Credentials | None - :param service_account_creds - Path to JSON service account key file to be used for authentication - or google.auth.credentials.Credentials object. + :type credentials: google.auth.credentials.Credentials + :param credentials + Credentials object used to authenticate connections to Cloud SQL server. If not specified, Application Default Credentials are used. """ scopes = [ @@ -388,13 +379,8 @@ def _auth_init(self, service_account_creds: Union[str, Credentials, None]) -> No "https://www.googleapis.com/auth/cloud-platform", ] # if Credentials object is passed in, use for authentication - if isinstance(service_account_creds, Credentials): - credentials = with_scopes_if_required(service_account_creds, scopes=scopes) - # if string is passed in, load credentials from file - elif isinstance(service_account_creds, str): - credentials, project = google.auth.load_credentials_from_file( - filename=service_account_creds, scopes=scopes - ) + if isinstance(credentials, Credentials): + credentials = with_scopes_if_required(credentials, scopes=scopes) # otherwise use application default credentials else: credentials, project = google.auth.default(scopes=scopes) diff --git a/tests/unit/test_instance_connection_manager.py b/tests/unit/test_instance_connection_manager.py index 4aa6571d..c5e2f644 100644 --- a/tests/unit/test_instance_connection_manager.py +++ b/tests/unit/test_instance_connection_manager.py @@ -23,7 +23,7 @@ from google.auth.credentials import Credentials from google.cloud.sql.connector.instance_connection_manager import ( InstanceConnectionManager, - ServiceAccountCredentialsTypeError, + CredentialsTypeError, ) from google.cloud.sql.connector.utils import generate_keys @@ -81,18 +81,18 @@ def test_InstanceConnectionManager_init(async_loop: asyncio.AbstractEventLoop) - ) -def test_InstanceConnectionManager_init_bad_service_account_creds( +def test_InstanceConnectionManager_init_bad_credentials( async_loop: asyncio.AbstractEventLoop, ) -> None: """ Test to check whether the __init__ method of InstanceConnectionManager - throws proper error for bad service_account_creds arg type. + throws proper error for bad credentials arg type. """ connect_string = "test-project:test-region:test-instance" keys = asyncio.run_coroutine_threadsafe(generate_keys(), async_loop) - with pytest.raises(ServiceAccountCredentialsTypeError): + with pytest.raises(CredentialsTypeError): assert InstanceConnectionManager( - connect_string, "pymysql", keys, async_loop, service_account_creds=1 + connect_string, "pymysql", keys, async_loop, credentials=1 ) @@ -213,21 +213,6 @@ def test_auth_init_with_credentials_object( mock_auth.assert_called_once() -def test_auth_init_with_credentials_file( - icm: InstanceConnectionManager, mock_credentials: Credentials -) -> None: - """ - Test that InstanceConnectionManager's _auth_init initializes _credentials - when passed a service account key file. - """ - setattr(icm, "_credentials", None) - with patch("google.auth.load_credentials_from_file") as mock_auth: - mock_auth.return_value = mock_credentials, None - icm._auth_init(service_account_creds="credentials.json") - assert isinstance(icm._credentials, Credentials) - mock_auth.assert_called_once() - - def test_auth_init_with_default_credentials( icm: InstanceConnectionManager, mock_credentials: Credentials ) -> None: From 759bb06d378e49b6aa47a37f75ca13757606cdbf Mon Sep 17 00:00:00 2001 From: jackwotherspoon Date: Thu, 23 Dec 2021 15:57:03 +0000 Subject: [PATCH 8/8] chore: update param in test --- tests/unit/test_instance_connection_manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_instance_connection_manager.py b/tests/unit/test_instance_connection_manager.py index c5e2f644..830c0aef 100644 --- a/tests/unit/test_instance_connection_manager.py +++ b/tests/unit/test_instance_connection_manager.py @@ -208,7 +208,7 @@ def test_auth_init_with_credentials_object( "google.cloud.sql.connector.instance_connection_manager.with_scopes_if_required" ) as mock_auth: mock_auth.return_value = mock_credentials - icm._auth_init(service_account_creds=mock_credentials) + icm._auth_init(credentials=mock_credentials) assert isinstance(icm._credentials, Credentials) mock_auth.assert_called_once() @@ -223,6 +223,6 @@ def test_auth_init_with_default_credentials( setattr(icm, "_credentials", None) with patch("google.auth.default") as mock_auth: mock_auth.return_value = mock_credentials, None - icm._auth_init(service_account_creds=None) + icm._auth_init(credentials=None) assert isinstance(icm._credentials, Credentials) mock_auth.assert_called_once()