diff --git a/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/async_client.py b/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/async_client.py index 5c3afda2..e70d43e3 100644 --- a/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/async_client.py +++ b/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/async_client.py @@ -94,8 +94,36 @@ class DataTransferServiceAsyncClient: DataTransferServiceClient.parse_common_location_path ) - from_service_account_info = DataTransferServiceClient.from_service_account_info - from_service_account_file = DataTransferServiceClient.from_service_account_file + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + DataTransferServiceAsyncClient: The constructed client. + """ + return DataTransferServiceClient.from_service_account_info.__func__(DataTransferServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + DataTransferServiceAsyncClient: The constructed client. + """ + return DataTransferServiceClient.from_service_account_file.__func__(DataTransferServiceAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property diff --git a/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/client.py b/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/client.py index 8bf606e4..4aac13d8 100644 --- a/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/client.py +++ b/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/client.py @@ -328,21 +328,17 @@ def __init__( util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) ) - ssl_credentials = None + client_cert_source_func = None is_mtls = False if use_client_cert: if client_options.client_cert_source: - import grpc # type: ignore - - cert, key = client_options.client_cert_source() - ssl_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) is_mtls = True + client_cert_source_func = client_options.client_cert_source else: - creds = SslCredentials() - is_mtls = creds.is_mtls - ssl_credentials = creds.ssl_credentials if is_mtls else None + is_mtls = mtls.has_default_client_cert_source() + client_cert_source_func = ( + mtls.default_client_cert_source() if is_mtls else None + ) # Figure out which api endpoint to use. if client_options.api_endpoint is not None: @@ -385,7 +381,7 @@ def __init__( credentials_file=client_options.credentials_file, host=api_endpoint, scopes=client_options.scopes, - ssl_channel_credentials=ssl_credentials, + client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, ) diff --git a/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/pagers.py b/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/pagers.py index 39e831ba..425e8eed 100644 --- a/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/pagers.py +++ b/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/pagers.py @@ -15,7 +15,16 @@ # limitations under the License. # -from typing import Any, AsyncIterable, Awaitable, Callable, Iterable, Sequence, Tuple +from typing import ( + Any, + AsyncIterable, + Awaitable, + Callable, + Iterable, + Sequence, + Tuple, + Optional, +) from google.cloud.bigquery_datatransfer_v1.types import datatransfer from google.cloud.bigquery_datatransfer_v1.types import transfer diff --git a/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/transports/grpc.py b/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/transports/grpc.py index 12ce7f93..1f613e03 100644 --- a/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/transports/grpc.py +++ b/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/transports/grpc.py @@ -62,6 +62,7 @@ def __init__( api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -92,6 +93,10 @@ def __init__( ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials for grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. client_info (google.api_core.gapic_v1.client_info.ClientInfo): @@ -108,6 +113,11 @@ def __init__( """ self._ssl_channel_credentials = ssl_channel_credentials + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -117,11 +127,6 @@ def __init__( self._grpc_channel = channel self._ssl_channel_credentials = None elif api_mtls_endpoint: - warnings.warn( - "api_mtls_endpoint and client_cert_source are deprecated", - DeprecationWarning, - ) - host = ( api_mtls_endpoint if ":" in api_mtls_endpoint @@ -165,12 +170,18 @@ def __init__( scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id ) + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + # create a new channel. The provided one is ignored. self._grpc_channel = type(self).create_channel( host, credentials=credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, + ssl_credentials=self._ssl_channel_credentials, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ diff --git a/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/transports/grpc_asyncio.py b/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/transports/grpc_asyncio.py index 41eeb000..cc4a7cce 100644 --- a/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/transports/grpc_asyncio.py +++ b/google/cloud/bigquery_datatransfer_v1/services/data_transfer_service/transports/grpc_asyncio.py @@ -106,6 +106,7 @@ def __init__( api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: @@ -137,6 +138,10 @@ def __init__( ``api_mtls_endpoint`` is None. ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials for grpc channel. It is ignored if ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. client_info (google.api_core.gapic_v1.client_info.ClientInfo): @@ -153,6 +158,11 @@ def __init__( """ self._ssl_channel_credentials = ssl_channel_credentials + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -162,11 +172,6 @@ def __init__( self._grpc_channel = channel self._ssl_channel_credentials = None elif api_mtls_endpoint: - warnings.warn( - "api_mtls_endpoint and client_cert_source are deprecated", - DeprecationWarning, - ) - host = ( api_mtls_endpoint if ":" in api_mtls_endpoint @@ -210,12 +215,18 @@ def __init__( scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id ) + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + # create a new channel. The provided one is ignored. self._grpc_channel = type(self).create_channel( host, credentials=credentials, credentials_file=credentials_file, - ssl_credentials=ssl_channel_credentials, + ssl_credentials=self._ssl_channel_credentials, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ diff --git a/google/cloud/bigquery_datatransfer_v1/types/__init__.py b/google/cloud/bigquery_datatransfer_v1/types/__init__.py index f793415b..b886143f 100644 --- a/google/cloud/bigquery_datatransfer_v1/types/__init__.py +++ b/google/cloud/bigquery_datatransfer_v1/types/__init__.py @@ -15,70 +15,70 @@ # limitations under the License. # -from .transfer import ( - EmailPreferences, - ScheduleOptions, - TransferConfig, - TransferRun, - TransferMessage, - TransferType, - TransferState, -) from .datatransfer import ( - DataSourceParameter, + CheckValidCredsRequest, + CheckValidCredsResponse, + CreateTransferConfigRequest, DataSource, + DataSourceParameter, + DeleteTransferConfigRequest, + DeleteTransferRunRequest, GetDataSourceRequest, - ListDataSourcesRequest, - ListDataSourcesResponse, - CreateTransferConfigRequest, - UpdateTransferConfigRequest, GetTransferConfigRequest, - DeleteTransferConfigRequest, GetTransferRunRequest, - DeleteTransferRunRequest, + ListDataSourcesRequest, + ListDataSourcesResponse, ListTransferConfigsRequest, ListTransferConfigsResponse, - ListTransferRunsRequest, - ListTransferRunsResponse, ListTransferLogsRequest, ListTransferLogsResponse, - CheckValidCredsRequest, - CheckValidCredsResponse, + ListTransferRunsRequest, + ListTransferRunsResponse, ScheduleTransferRunsRequest, ScheduleTransferRunsResponse, StartManualTransferRunsRequest, StartManualTransferRunsResponse, + UpdateTransferConfigRequest, +) +from .transfer import ( + EmailPreferences, + ScheduleOptions, + TransferConfig, + TransferMessage, + TransferRun, + TransferState, + TransferType, ) __all__ = ( - "EmailPreferences", - "ScheduleOptions", - "TransferConfig", - "TransferRun", - "TransferMessage", - "TransferType", - "TransferState", - "DataSourceParameter", + "CheckValidCredsRequest", + "CheckValidCredsResponse", + "CreateTransferConfigRequest", "DataSource", + "DataSourceParameter", + "DeleteTransferConfigRequest", + "DeleteTransferRunRequest", "GetDataSourceRequest", - "ListDataSourcesRequest", - "ListDataSourcesResponse", - "CreateTransferConfigRequest", - "UpdateTransferConfigRequest", "GetTransferConfigRequest", - "DeleteTransferConfigRequest", "GetTransferRunRequest", - "DeleteTransferRunRequest", + "ListDataSourcesRequest", + "ListDataSourcesResponse", "ListTransferConfigsRequest", "ListTransferConfigsResponse", - "ListTransferRunsRequest", - "ListTransferRunsResponse", "ListTransferLogsRequest", "ListTransferLogsResponse", - "CheckValidCredsRequest", - "CheckValidCredsResponse", + "ListTransferRunsRequest", + "ListTransferRunsResponse", "ScheduleTransferRunsRequest", "ScheduleTransferRunsResponse", "StartManualTransferRunsRequest", "StartManualTransferRunsResponse", + "UpdateTransferConfigRequest", + "EmailPreferences", + "ScheduleOptions", + "TransferConfig", + "TransferMessage", + "TransferRun", + "TransferState", + "TransferType", ) diff --git a/synth.metadata b/synth.metadata index f4b1ded2..4a2a12d1 100644 --- a/synth.metadata +++ b/synth.metadata @@ -11,8 +11,8 @@ "git": { "name": "googleapis", "remote": "https://github.com/googleapis/googleapis.git", - "sha": "520682435235d9c503983a360a2090025aa47cd1", - "internalRef": "350246057" + "sha": "c13fb8cb376bb666de80ed33e11550955b4357af", + "internalRef": "363304304" } }, { @@ -93,6 +93,7 @@ "CONTRIBUTING.rst", "LICENSE", "MANIFEST.in", + "README.rst", "docs/_static/custom.css", "docs/_templates/layout.html", "docs/bigquery_datatransfer_v1/data_transfer_service.rst", @@ -137,4 +138,4 @@ "tests/unit/gapic/bigquery_datatransfer_v1/__init__.py", "tests/unit/gapic/bigquery_datatransfer_v1/test_data_transfer_service.py" ] -} \ No newline at end of file +} diff --git a/synth.py b/synth.py index abfa2af9..260d5d40 100644 --- a/synth.py +++ b/synth.py @@ -37,7 +37,7 @@ ), include_protos=True, ) - s.move(library, excludes=["setup.py", "docs/index.rst"]) + s.move(library, excludes=["*.tar.gz", "setup.py", "docs/index.rst"]) # ---------------------------------------------------------------------------- @@ -56,12 +56,12 @@ s.replace( "google/cloud/bigquery_datatransfer_v1/__init__.py", r"from \.services\.data_transfer_service import DataTransferServiceClient", - "\g<0>\nfrom .services.data_transfer_service import DataTransferServiceAsyncClient", + "\\g<0>\nfrom .services.data_transfer_service import DataTransferServiceAsyncClient", ) s.replace( "google/cloud/bigquery_datatransfer_v1/__init__.py", r"'DataTransferServiceClient',", - '\g<0>\n "DataTransferServiceAsyncClient"', + '\\g<0>\n "DataTransferServiceAsyncClient"', ) diff --git a/tests/unit/gapic/bigquery_datatransfer_v1/__init__.py b/tests/unit/gapic/bigquery_datatransfer_v1/__init__.py index 8b137891..42ffdf2b 100644 --- a/tests/unit/gapic/bigquery_datatransfer_v1/__init__.py +++ b/tests/unit/gapic/bigquery_datatransfer_v1/__init__.py @@ -1 +1,16 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/tests/unit/gapic/bigquery_datatransfer_v1/test_data_transfer_service.py b/tests/unit/gapic/bigquery_datatransfer_v1/test_data_transfer_service.py index d21e3acc..345a6b56 100644 --- a/tests/unit/gapic/bigquery_datatransfer_v1/test_data_transfer_service.py +++ b/tests/unit/gapic/bigquery_datatransfer_v1/test_data_transfer_service.py @@ -97,15 +97,19 @@ def test__get_default_mtls_endpoint(): ) -def test_data_transfer_service_client_from_service_account_info(): +@pytest.mark.parametrize( + "client_class", [DataTransferServiceClient, DataTransferServiceAsyncClient,] +) +def test_data_transfer_service_client_from_service_account_info(client_class): creds = credentials.AnonymousCredentials() with mock.patch.object( service_account.Credentials, "from_service_account_info" ) as factory: factory.return_value = creds info = {"valid": True} - client = DataTransferServiceClient.from_service_account_info(info) + client = client_class.from_service_account_info(info) assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "bigquerydatatransfer.googleapis.com:443" @@ -121,9 +125,11 @@ def test_data_transfer_service_client_from_service_account_file(client_class): factory.return_value = creds client = client_class.from_service_account_file("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) client = client_class.from_service_account_json("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "bigquerydatatransfer.googleapis.com:443" @@ -188,7 +194,7 @@ def test_data_transfer_service_client_client_options( credentials_file=None, host="squid.clam.whelk", scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -204,7 +210,7 @@ def test_data_transfer_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -220,7 +226,7 @@ def test_data_transfer_service_client_client_options( credentials_file=None, host=client.DEFAULT_MTLS_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -248,7 +254,7 @@ def test_data_transfer_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id="octopus", client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -309,29 +315,25 @@ def test_data_transfer_service_client_mtls_env_auto( client_cert_source=client_cert_source_callback ) with mock.patch.object(transport_class, "__init__") as patched: - ssl_channel_creds = mock.Mock() - with mock.patch( - "grpc.ssl_channel_credentials", return_value=ssl_channel_creds - ): - patched.return_value = None - client = client_class(client_options=options) + patched.return_value = None + client = client_class(client_options=options) - if use_client_cert_env == "false": - expected_ssl_channel_creds = None - expected_host = client.DEFAULT_ENDPOINT - else: - expected_ssl_channel_creds = ssl_channel_creds - expected_host = client.DEFAULT_MTLS_ENDPOINT + if use_client_cert_env == "false": + expected_client_cert_source = None + expected_host = client.DEFAULT_ENDPOINT + else: + expected_client_cert_source = client_cert_source_callback + expected_host = client.DEFAULT_MTLS_ENDPOINT - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=expected_host, - scopes=None, - ssl_channel_credentials=expected_ssl_channel_creds, - quota_project_id=None, - client_info=transports.base.DEFAULT_CLIENT_INFO, - ) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) # Check the case ADC client cert is provided. Whether client cert is used depends on # GOOGLE_API_USE_CLIENT_CERTIFICATE value. @@ -340,66 +342,53 @@ def test_data_transfer_service_client_mtls_env_auto( ): with mock.patch.object(transport_class, "__init__") as patched: with mock.patch( - "google.auth.transport.grpc.SslCredentials.__init__", return_value=None + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, ): with mock.patch( - "google.auth.transport.grpc.SslCredentials.is_mtls", - new_callable=mock.PropertyMock, - ) as is_mtls_mock: - with mock.patch( - "google.auth.transport.grpc.SslCredentials.ssl_credentials", - new_callable=mock.PropertyMock, - ) as ssl_credentials_mock: - if use_client_cert_env == "false": - is_mtls_mock.return_value = False - ssl_credentials_mock.return_value = None - expected_host = client.DEFAULT_ENDPOINT - expected_ssl_channel_creds = None - else: - is_mtls_mock.return_value = True - ssl_credentials_mock.return_value = mock.Mock() - expected_host = client.DEFAULT_MTLS_ENDPOINT - expected_ssl_channel_creds = ( - ssl_credentials_mock.return_value - ) - - patched.return_value = None - client = client_class() - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=expected_host, - scopes=None, - ssl_channel_credentials=expected_ssl_channel_creds, - quota_project_id=None, - client_info=transports.base.DEFAULT_CLIENT_INFO, - ) + "google.auth.transport.mtls.default_client_cert_source", + return_value=client_cert_source_callback, + ): + if use_client_cert_env == "false": + expected_host = client.DEFAULT_ENDPOINT + expected_client_cert_source = None + else: + expected_host = client.DEFAULT_MTLS_ENDPOINT + expected_client_cert_source = client_cert_source_callback - # Check the case client_cert_source and ADC client cert are not provided. - with mock.patch.dict( - os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} - ): - with mock.patch.object(transport_class, "__init__") as patched: - with mock.patch( - "google.auth.transport.grpc.SslCredentials.__init__", return_value=None - ): - with mock.patch( - "google.auth.transport.grpc.SslCredentials.is_mtls", - new_callable=mock.PropertyMock, - ) as is_mtls_mock: - is_mtls_mock.return_value = False patched.return_value = None client = client_class() patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_ENDPOINT, + host=expected_host, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=expected_client_cert_source, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) + # Check the case client_cert_source and ADC client cert are not provided. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + patched.return_value = None + client = client_class() + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + @pytest.mark.parametrize( "client_class,transport_class,transport_name", @@ -429,7 +418,7 @@ def test_data_transfer_service_client_client_options_scopes( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=["1", "2"], - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -463,7 +452,7 @@ def test_data_transfer_service_client_client_options_credentials_file( credentials_file="credentials.json", host=client.DEFAULT_ENDPOINT, scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -482,7 +471,7 @@ def test_data_transfer_service_client_client_options_from_dict(): credentials_file=None, host="squid.clam.whelk", scopes=None, - ssl_channel_credentials=None, + client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -576,6 +565,22 @@ def test_get_data_source_from_dict(): test_get_data_source(request_type=dict) +def test_get_data_source_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DataTransferServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_data_source), "__call__") as call: + client.get_data_source() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == datatransfer.GetDataSourceRequest() + + @pytest.mark.asyncio async def test_get_data_source_async( transport: str = "grpc_asyncio", request_type=datatransfer.GetDataSourceRequest @@ -830,6 +835,24 @@ def test_list_data_sources_from_dict(): test_list_data_sources(request_type=dict) +def test_list_data_sources_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DataTransferServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_data_sources), "__call__" + ) as call: + client.list_data_sources() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == datatransfer.ListDataSourcesRequest() + + @pytest.mark.asyncio async def test_list_data_sources_async( transport: str = "grpc_asyncio", request_type=datatransfer.ListDataSourcesRequest @@ -1229,6 +1252,24 @@ def test_create_transfer_config_from_dict(): test_create_transfer_config(request_type=dict) +def test_create_transfer_config_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DataTransferServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_transfer_config), "__call__" + ) as call: + client.create_transfer_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == datatransfer.CreateTransferConfigRequest() + + @pytest.mark.asyncio async def test_create_transfer_config_async( transport: str = "grpc_asyncio", @@ -1512,6 +1553,24 @@ def test_update_transfer_config_from_dict(): test_update_transfer_config(request_type=dict) +def test_update_transfer_config_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DataTransferServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_transfer_config), "__call__" + ) as call: + client.update_transfer_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == datatransfer.UpdateTransferConfigRequest() + + @pytest.mark.asyncio async def test_update_transfer_config_async( transport: str = "grpc_asyncio", @@ -1768,6 +1827,24 @@ def test_delete_transfer_config_from_dict(): test_delete_transfer_config(request_type=dict) +def test_delete_transfer_config_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DataTransferServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_transfer_config), "__call__" + ) as call: + client.delete_transfer_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == datatransfer.DeleteTransferConfigRequest() + + @pytest.mark.asyncio async def test_delete_transfer_config_async( transport: str = "grpc_asyncio", @@ -2000,6 +2077,24 @@ def test_get_transfer_config_from_dict(): test_get_transfer_config(request_type=dict) +def test_get_transfer_config_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DataTransferServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_transfer_config), "__call__" + ) as call: + client.get_transfer_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == datatransfer.GetTransferConfigRequest() + + @pytest.mark.asyncio async def test_get_transfer_config_async( transport: str = "grpc_asyncio", request_type=datatransfer.GetTransferConfigRequest @@ -2240,6 +2335,24 @@ def test_list_transfer_configs_from_dict(): test_list_transfer_configs(request_type=dict) +def test_list_transfer_configs_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DataTransferServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_transfer_configs), "__call__" + ) as call: + client.list_transfer_configs() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == datatransfer.ListTransferConfigsRequest() + + @pytest.mark.asyncio async def test_list_transfer_configs_async( transport: str = "grpc_asyncio", @@ -2620,6 +2733,24 @@ def test_schedule_transfer_runs_from_dict(): test_schedule_transfer_runs(request_type=dict) +def test_schedule_transfer_runs_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DataTransferServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.schedule_transfer_runs), "__call__" + ) as call: + client.schedule_transfer_runs() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == datatransfer.ScheduleTransferRunsRequest() + + @pytest.mark.asyncio async def test_schedule_transfer_runs_async( transport: str = "grpc_asyncio", @@ -2856,6 +2987,24 @@ def test_start_manual_transfer_runs_from_dict(): test_start_manual_transfer_runs(request_type=dict) +def test_start_manual_transfer_runs_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DataTransferServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.start_manual_transfer_runs), "__call__" + ) as call: + client.start_manual_transfer_runs() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == datatransfer.StartManualTransferRunsRequest() + + @pytest.mark.asyncio async def test_start_manual_transfer_runs_async( transport: str = "grpc_asyncio", @@ -3005,6 +3154,22 @@ def test_get_transfer_run_from_dict(): test_get_transfer_run(request_type=dict) +def test_get_transfer_run_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DataTransferServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_transfer_run), "__call__") as call: + client.get_transfer_run() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == datatransfer.GetTransferRunRequest() + + @pytest.mark.asyncio async def test_get_transfer_run_async( transport: str = "grpc_asyncio", request_type=datatransfer.GetTransferRunRequest @@ -3218,6 +3383,24 @@ def test_delete_transfer_run_from_dict(): test_delete_transfer_run(request_type=dict) +def test_delete_transfer_run_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DataTransferServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_transfer_run), "__call__" + ) as call: + client.delete_transfer_run() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == datatransfer.DeleteTransferRunRequest() + + @pytest.mark.asyncio async def test_delete_transfer_run_async( transport: str = "grpc_asyncio", request_type=datatransfer.DeleteTransferRunRequest @@ -3421,6 +3604,24 @@ def test_list_transfer_runs_from_dict(): test_list_transfer_runs(request_type=dict) +def test_list_transfer_runs_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DataTransferServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_transfer_runs), "__call__" + ) as call: + client.list_transfer_runs() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == datatransfer.ListTransferRunsRequest() + + @pytest.mark.asyncio async def test_list_transfer_runs_async( transport: str = "grpc_asyncio", request_type=datatransfer.ListTransferRunsRequest @@ -3792,6 +3993,24 @@ def test_list_transfer_logs_from_dict(): test_list_transfer_logs(request_type=dict) +def test_list_transfer_logs_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DataTransferServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_transfer_logs), "__call__" + ) as call: + client.list_transfer_logs() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == datatransfer.ListTransferLogsRequest() + + @pytest.mark.asyncio async def test_list_transfer_logs_async( transport: str = "grpc_asyncio", request_type=datatransfer.ListTransferLogsRequest @@ -4173,6 +4392,24 @@ def test_check_valid_creds_from_dict(): test_check_valid_creds(request_type=dict) +def test_check_valid_creds_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DataTransferServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.check_valid_creds), "__call__" + ) as call: + client.check_valid_creds() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == datatransfer.CheckValidCredsRequest() + + @pytest.mark.asyncio async def test_check_valid_creds_async( transport: str = "grpc_asyncio", request_type=datatransfer.CheckValidCredsRequest @@ -4517,6 +4754,53 @@ def test_data_transfer_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class", + [ + transports.DataTransferServiceGrpcTransport, + transports.DataTransferServiceGrpcAsyncIOTransport, + ], +) +def test_data_transfer_service_grpc_transport_client_cert_source_for_mtls( + transport_class, +): + cred = credentials.AnonymousCredentials() + + # Check ssl_channel_credentials is used if provided. + with mock.patch.object(transport_class, "create_channel") as mock_create_channel: + mock_ssl_channel_creds = mock.Mock() + transport_class( + host="squid.clam.whelk", + credentials=cred, + ssl_channel_credentials=mock_ssl_channel_creds, + ) + mock_create_channel.assert_called_once_with( + "squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_channel_creds, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Check if ssl_channel_credentials is not provided, then client_cert_source_for_mtls + # is used. + with mock.patch.object(transport_class, "create_channel", return_value=mock.Mock()): + with mock.patch("grpc.ssl_channel_credentials") as mock_ssl_cred: + transport_class( + credentials=cred, + client_cert_source_for_mtls=client_cert_source_callback, + ) + expected_cert, expected_key = client_cert_source_callback() + mock_ssl_cred.assert_called_once_with( + certificate_chain=expected_cert, private_key=expected_key + ) + + def test_data_transfer_service_host_no_port(): client = DataTransferServiceClient( credentials=credentials.AnonymousCredentials(), @@ -4561,6 +4845,8 @@ def test_data_transfer_service_grpc_asyncio_transport_channel(): assert transport._ssl_channel_credentials == None +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. @pytest.mark.parametrize( "transport_class", [ @@ -4613,6 +4899,8 @@ def test_data_transfer_service_transport_channel_mtls_with_client_cert_source( assert transport._ssl_channel_credentials == mock_ssl_cred +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. @pytest.mark.parametrize( "transport_class", [