diff --git a/.gitignore b/.gitignore index b9daa52..b4243ce 100644 --- a/.gitignore +++ b/.gitignore @@ -50,8 +50,10 @@ docs.metadata # Virtual environment env/ + +# Test logs coverage.xml -sponge_log.xml +*sponge_log.xml # System test environment variables. system_tests/local_test_setup diff --git a/.kokoro/build.sh b/.kokoro/build.sh index 62f45a2..04608a7 100755 --- a/.kokoro/build.sh +++ b/.kokoro/build.sh @@ -40,6 +40,16 @@ python3 -m pip uninstall --yes --quiet nox-automation python3 -m pip install --upgrade --quiet nox python3 -m nox --version +# If this is a continuous build, send the test log to the FlakyBot. +# See https://github.com/googleapis/repo-automation-bots/tree/master/packages/flakybot. +if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]]; then + cleanup() { + chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot + $KOKORO_GFILE_DIR/linux_amd64/flakybot + } + trap cleanup EXIT HUP +fi + # If NOX_SESSION is set, it only runs the specified session, # otherwise run all the sessions. if [[ -n "${NOX_SESSION:-}" ]]; then diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 083fd0e..0328ffb 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -70,9 +70,14 @@ We use `nox `__ to instrument our tests. - To test your changes, run unit tests with ``nox``:: $ nox -s unit-2.7 - $ nox -s unit-3.7 + $ nox -s unit-3.8 $ ... +- Args to pytest can be passed through the nox command separated by a `--`. For + example, to run a single test:: + + $ nox -s unit-3.8 -- -k + .. note:: The unit tests and system tests are described in the @@ -93,8 +98,12 @@ On Debian/Ubuntu:: ************ Coding Style ************ +- We use the automatic code formatter ``black``. You can run it using + the nox session ``blacken``. This will eliminate many lint errors. Run via:: + + $ nox -s blacken -- PEP8 compliance, with exceptions defined in the linter configuration. +- PEP8 compliance is required, with exceptions defined in the linter configuration. If you have ``nox`` installed, you can test that you have not introduced any non-compliant code via:: @@ -133,13 +142,18 @@ Running System Tests - To run system tests, you can execute:: - $ nox -s system-3.7 + # Run all system tests + $ nox -s system-3.8 $ nox -s system-2.7 + # Run a single system test + $ nox -s system-3.8 -- -k + + .. note:: System tests are only configured to run under Python 2.7 and - Python 3.7. For expediency, we do not run them in older versions + Python 3.8. For expediency, we do not run them in older versions of Python 3. This alone will not run the tests. You'll need to change some local diff --git a/MANIFEST.in b/MANIFEST.in index e9e29d1..e783f4c 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -16,10 +16,10 @@ # Generated by synthtool. DO NOT EDIT! include README.rst LICENSE -recursive-include google *.json *.proto +recursive-include google *.json *.proto py.typed recursive-include tests * global-exclude *.py[co] global-exclude __pycache__ # Exclude scripts for samples readmegen -prune scripts/readme-gen \ No newline at end of file +prune scripts/readme-gen diff --git a/google/cloud/networkconnectivity/__init__.py b/google/cloud/networkconnectivity/__init__.py index 427593f..880b58d 100644 --- a/google/cloud/networkconnectivity/__init__.py +++ b/google/cloud/networkconnectivity/__init__.py @@ -35,6 +35,7 @@ from google.cloud.networkconnectivity_v1alpha1.types.hub import ListSpokesResponse from google.cloud.networkconnectivity_v1alpha1.types.hub import RouterApplianceInstance from google.cloud.networkconnectivity_v1alpha1.types.hub import Spoke +from google.cloud.networkconnectivity_v1alpha1.types.hub import State from google.cloud.networkconnectivity_v1alpha1.types.hub import UpdateHubRequest from google.cloud.networkconnectivity_v1alpha1.types.hub import UpdateSpokeRequest @@ -55,6 +56,7 @@ "OperationMetadata", "RouterApplianceInstance", "Spoke", + "State", "UpdateHubRequest", "UpdateSpokeRequest", ) diff --git a/google/cloud/networkconnectivity_v1alpha1/__init__.py b/google/cloud/networkconnectivity_v1alpha1/__init__.py index 9aefd79..6bcd64d 100644 --- a/google/cloud/networkconnectivity_v1alpha1/__init__.py +++ b/google/cloud/networkconnectivity_v1alpha1/__init__.py @@ -30,6 +30,7 @@ from .types.hub import ListSpokesResponse from .types.hub import RouterApplianceInstance from .types.hub import Spoke +from .types.hub import State from .types.hub import UpdateHubRequest from .types.hub import UpdateSpokeRequest @@ -49,6 +50,7 @@ "OperationMetadata", "RouterApplianceInstance", "Spoke", + "State", "UpdateHubRequest", "UpdateSpokeRequest", "HubServiceClient", diff --git a/google/cloud/networkconnectivity_v1alpha1/services/hub_service/async_client.py b/google/cloud/networkconnectivity_v1alpha1/services/hub_service/async_client.py index e05915a..995fa86 100644 --- a/google/cloud/networkconnectivity_v1alpha1/services/hub_service/async_client.py +++ b/google/cloud/networkconnectivity_v1alpha1/services/hub_service/async_client.py @@ -44,8 +44,8 @@ class HubServiceAsyncClient: - """Connectivity Hub is a hub-and-spoke abstraction for network - connectivity management in Google Cloud. The Hub aims to reduce + """Network Connectivity Center is a hub-and-spoke abstraction + for network connectivity management in Google Cloud. It reduces operational complexity through a simple, centralized connectivity management model. """ @@ -272,13 +272,13 @@ async def get_hub( Returns: google.cloud.networkconnectivity_v1alpha1.types.Hub: - The Connectivity Hub is a hub-and- - poke abstraction for network + Network Connectivity Center is a hub- + nd-spoke abstraction for network connectivity management in Google Cloud. - It aims to reduce operational complexity + It reduces operational complexity through a simple, centralized - connectivity management model. Here is - the resource message of a Hub. + connectivity management model. Following + is the resource message of a hub. """ # Create or coerce a protobuf request object. @@ -369,11 +369,11 @@ async def create_hub( google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. - The result type for the operation will be :class:`google.cloud.networkconnectivity_v1alpha1.types.Hub` The Connectivity Hub is a hub-and-spoke abstraction for network connectivity - management in Google Cloud. It aims to reduce - operational complexity through a simple, centralized - connectivity management model. Here is the resource - message of a Hub. + The result type for the operation will be :class:`google.cloud.networkconnectivity_v1alpha1.types.Hub` Network Connectivity Center is a hub-and-spoke abstraction for + network connectivity management in Google Cloud. It + reduces operational complexity through a simple, + centralized connectivity management model. Following + is the resource message of a hub. """ # Create or coerce a protobuf request object. @@ -472,11 +472,11 @@ async def update_hub( google.api_core.operation_async.AsyncOperation: An object representing a long-running operation. - The result type for the operation will be :class:`google.cloud.networkconnectivity_v1alpha1.types.Hub` The Connectivity Hub is a hub-and-spoke abstraction for network connectivity - management in Google Cloud. It aims to reduce - operational complexity through a simple, centralized - connectivity management model. Here is the resource - message of a Hub. + The result type for the operation will be :class:`google.cloud.networkconnectivity_v1alpha1.types.Hub` Network Connectivity Center is a hub-and-spoke abstraction for + network connectivity management in Google Cloud. It + reduces operational complexity through a simple, + centralized connectivity management model. Following + is the resource message of a hub. """ # Create or coerce a protobuf request object. diff --git a/google/cloud/networkconnectivity_v1alpha1/services/hub_service/client.py b/google/cloud/networkconnectivity_v1alpha1/services/hub_service/client.py index 5849377..9233ee5 100644 --- a/google/cloud/networkconnectivity_v1alpha1/services/hub_service/client.py +++ b/google/cloud/networkconnectivity_v1alpha1/services/hub_service/client.py @@ -79,8 +79,8 @@ def get_transport_class(cls, label: str = None,) -> Type[HubServiceTransport]: class HubServiceClient(metaclass=HubServiceClientMeta): - """Connectivity Hub is a hub-and-spoke abstraction for network - connectivity management in Google Cloud. The Hub aims to reduce + """Network Connectivity Center is a hub-and-spoke abstraction + for network connectivity management in Google Cloud. It reduces operational complexity through a simple, centralized connectivity management model. """ @@ -359,21 +359,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: @@ -416,7 +412,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, ) @@ -536,13 +532,13 @@ def get_hub( Returns: google.cloud.networkconnectivity_v1alpha1.types.Hub: - The Connectivity Hub is a hub-and- - poke abstraction for network + Network Connectivity Center is a hub- + nd-spoke abstraction for network connectivity management in Google Cloud. - It aims to reduce operational complexity + It reduces operational complexity through a simple, centralized - connectivity management model. Here is - the resource message of a Hub. + connectivity management model. Following + is the resource message of a hub. """ # Create or coerce a protobuf request object. @@ -634,11 +630,11 @@ def create_hub( google.api_core.operation.Operation: An object representing a long-running operation. - The result type for the operation will be :class:`google.cloud.networkconnectivity_v1alpha1.types.Hub` The Connectivity Hub is a hub-and-spoke abstraction for network connectivity - management in Google Cloud. It aims to reduce - operational complexity through a simple, centralized - connectivity management model. Here is the resource - message of a Hub. + The result type for the operation will be :class:`google.cloud.networkconnectivity_v1alpha1.types.Hub` Network Connectivity Center is a hub-and-spoke abstraction for + network connectivity management in Google Cloud. It + reduces operational complexity through a simple, + centralized connectivity management model. Following + is the resource message of a hub. """ # Create or coerce a protobuf request object. @@ -738,11 +734,11 @@ def update_hub( google.api_core.operation.Operation: An object representing a long-running operation. - The result type for the operation will be :class:`google.cloud.networkconnectivity_v1alpha1.types.Hub` The Connectivity Hub is a hub-and-spoke abstraction for network connectivity - management in Google Cloud. It aims to reduce - operational complexity through a simple, centralized - connectivity management model. Here is the resource - message of a Hub. + The result type for the operation will be :class:`google.cloud.networkconnectivity_v1alpha1.types.Hub` Network Connectivity Center is a hub-and-spoke abstraction for + network connectivity management in Google Cloud. It + reduces operational complexity through a simple, + centralized connectivity management model. Following + is the resource message of a hub. """ # Create or coerce a protobuf request object. diff --git a/google/cloud/networkconnectivity_v1alpha1/services/hub_service/pagers.py b/google/cloud/networkconnectivity_v1alpha1/services/hub_service/pagers.py index 1bf66c4..1e1f1ae 100644 --- a/google/cloud/networkconnectivity_v1alpha1/services/hub_service/pagers.py +++ b/google/cloud/networkconnectivity_v1alpha1/services/hub_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.networkconnectivity_v1alpha1.types import hub diff --git a/google/cloud/networkconnectivity_v1alpha1/services/hub_service/transports/grpc.py b/google/cloud/networkconnectivity_v1alpha1/services/hub_service/transports/grpc.py index ba6e4c6..5f4a8e1 100644 --- a/google/cloud/networkconnectivity_v1alpha1/services/hub_service/transports/grpc.py +++ b/google/cloud/networkconnectivity_v1alpha1/services/hub_service/transports/grpc.py @@ -37,8 +37,8 @@ class HubServiceGrpcTransport(HubServiceTransport): """gRPC backend transport for HubService. - Connectivity Hub is a hub-and-spoke abstraction for network - connectivity management in Google Cloud. The Hub aims to reduce + Network Connectivity Center is a hub-and-spoke abstraction + for network connectivity management in Google Cloud. It reduces operational complexity through a simple, centralized connectivity management model. @@ -63,6 +63,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: @@ -93,6 +94,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): @@ -109,6 +114,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. @@ -118,11 +128,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 @@ -166,12 +171,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/networkconnectivity_v1alpha1/services/hub_service/transports/grpc_asyncio.py b/google/cloud/networkconnectivity_v1alpha1/services/hub_service/transports/grpc_asyncio.py index cd95c6c..cc5cf85 100644 --- a/google/cloud/networkconnectivity_v1alpha1/services/hub_service/transports/grpc_asyncio.py +++ b/google/cloud/networkconnectivity_v1alpha1/services/hub_service/transports/grpc_asyncio.py @@ -39,8 +39,8 @@ class HubServiceGrpcAsyncIOTransport(HubServiceTransport): """gRPC AsyncIO backend transport for HubService. - Connectivity Hub is a hub-and-spoke abstraction for network - connectivity management in Google Cloud. The Hub aims to reduce + Network Connectivity Center is a hub-and-spoke abstraction + for network connectivity management in Google Cloud. It reduces operational complexity through a simple, centralized connectivity management model. @@ -107,6 +107,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: @@ -138,6 +139,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): @@ -154,6 +159,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. @@ -163,11 +173,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 @@ -211,12 +216,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/networkconnectivity_v1alpha1/types/__init__.py b/google/cloud/networkconnectivity_v1alpha1/types/__init__.py index ec4d53c..d7436bd 100644 --- a/google/cloud/networkconnectivity_v1alpha1/types/__init__.py +++ b/google/cloud/networkconnectivity_v1alpha1/types/__init__.py @@ -32,6 +32,7 @@ UpdateSpokeRequest, DeleteSpokeRequest, RouterApplianceInstance, + State, ) __all__ = ( @@ -51,4 +52,5 @@ "UpdateSpokeRequest", "DeleteSpokeRequest", "RouterApplianceInstance", + "State", ) diff --git a/google/cloud/networkconnectivity_v1alpha1/types/hub.py b/google/cloud/networkconnectivity_v1alpha1/types/hub.py index 79b525a..f82d977 100644 --- a/google/cloud/networkconnectivity_v1alpha1/types/hub.py +++ b/google/cloud/networkconnectivity_v1alpha1/types/hub.py @@ -25,6 +25,7 @@ __protobuf__ = proto.module( package="google.cloud.networkconnectivity.v1alpha1", manifest={ + "State", "Hub", "Spoke", "ListHubsRequest", @@ -44,12 +45,22 @@ ) +class State(proto.Enum): + r"""The State enum represents the lifecycle of a Network + Connectivity Center resource. + """ + STATE_UNSPECIFIED = 0 + CREATING = 1 + ACTIVE = 2 + DELETING = 3 + + class Hub(proto.Message): - r"""The Connectivity Hub is a hub-and-spoke abstraction for - network connectivity management in Google Cloud. It aims to - reduce operational complexity through a simple, centralized - connectivity management model. Here is the resource message of a - Hub. + r"""Network Connectivity Center is a hub-and-spoke abstraction + for network connectivity management in Google Cloud. It reduces + operational complexity through a simple, centralized + connectivity management model. Following is the resource message + of a hub. Attributes: name (str): @@ -70,6 +81,9 @@ class Hub(proto.Message): is unique across all Hub resources. If a Hub resource is deleted and another with the same name is created, it gets a different unique_id. + state (google.cloud.networkconnectivity_v1alpha1.types.State): + Output only. The current lifecycle state of + this Hub. """ name = proto.Field(proto.STRING, number=1) @@ -86,6 +100,8 @@ class Hub(proto.Message): unique_id = proto.Field(proto.STRING, number=8) + state = proto.Field(proto.ENUM, number=9, enum="State",) + class Spoke(proto.Message): r"""A Spoke is an abstraction of a network attachment being @@ -118,6 +134,9 @@ class Spoke(proto.Message): is unique across all Spoke resources. If a Spoke resource is deleted and another with the same name is created, it gets a different unique_id. + state (google.cloud.networkconnectivity_v1alpha1.types.State): + Output only. The current lifecycle state of + this Hub. """ name = proto.Field(proto.STRING, number=1) @@ -142,6 +161,8 @@ class Spoke(proto.Message): unique_id = proto.Field(proto.STRING, number=11) + state = proto.Field(proto.ENUM, number=15, enum="State",) + class ListHubsRequest(proto.Message): r"""Request for diff --git a/noxfile.py b/noxfile.py index 9e90799..87c33ae 100644 --- a/noxfile.py +++ b/noxfile.py @@ -93,6 +93,7 @@ def default(session): session.run( "py.test", "--quiet", + f"--junitxml=unit_{session.python}_sponge_log.xml", "--cov=google/cloud", "--cov=tests/unit", "--cov-append", @@ -141,9 +142,21 @@ def system(session): # Run py.test against the system tests. if system_test_exists: - session.run("py.test", "--quiet", system_test_path, *session.posargs) + session.run( + "py.test", + "--quiet", + f"--junitxml=system_{session.python}_sponge_log.xml", + system_test_path, + *session.posargs, + ) if system_test_folder_exists: - session.run("py.test", "--quiet", system_test_folder_path, *session.posargs) + session.run( + "py.test", + "--quiet", + f"--junitxml=system_{session.python}_sponge_log.xml", + system_test_folder_path, + *session.posargs, + ) @nox.session(python=DEFAULT_PYTHON_VERSION) diff --git a/synth.metadata b/synth.metadata index db4117b..877c46f 100644 --- a/synth.metadata +++ b/synth.metadata @@ -4,29 +4,29 @@ "git": { "name": ".", "remote": "https://github.com/googleapis/python-network-connectivity.git", - "sha": "7c5e2683ff1774acf4a16bc928706709c0c70f91" + "sha": "47311e98c3a67fd67a711e9ea9b5cecfd7b06bc2" } }, { "git": { "name": "googleapis", "remote": "https://github.com/googleapis/googleapis.git", - "sha": "d99d5d592f3d1d5526511c90120b1e9ab3ce6e17", - "internalRef": "354148500" + "sha": "e53f05caf2fcc77c92be82bc2654e5d6000c5148", + "internalRef": "358007902" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "778d8beae28d6d87eb01fdc839a4b4d966ed2ebe" + "sha": "d17674372e27fb8f23013935e794aa37502071aa" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "778d8beae28d6d87eb01fdc839a4b4d966ed2ebe" + "sha": "d17674372e27fb8f23013935e794aa37502071aa" } } ], diff --git a/tests/unit/gapic/networkconnectivity_v1alpha1/test_hub_service.py b/tests/unit/gapic/networkconnectivity_v1alpha1/test_hub_service.py index ba2d517..7fe7cf0 100644 --- a/tests/unit/gapic/networkconnectivity_v1alpha1/test_hub_service.py +++ b/tests/unit/gapic/networkconnectivity_v1alpha1/test_hub_service.py @@ -176,7 +176,7 @@ def test_hub_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, ) @@ -192,7 +192,7 @@ def test_hub_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, ) @@ -208,7 +208,7 @@ def test_hub_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, ) @@ -236,7 +236,7 @@ def test_hub_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, ) @@ -285,29 +285,25 @@ def test_hub_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. @@ -316,66 +312,53 @@ def test_hub_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", @@ -401,7 +384,7 @@ def test_hub_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, ) @@ -431,7 +414,7 @@ def test_hub_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, ) @@ -448,7 +431,7 @@ def test_hub_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, ) @@ -771,6 +754,7 @@ def test_get_hub(transport: str = "grpc", request_type=hub.GetHubRequest): description="description_value", spokes=["spokes_value"], unique_id="unique_id_value", + state=hub.State.CREATING, ) response = client.get_hub(request) @@ -793,6 +777,8 @@ def test_get_hub(transport: str = "grpc", request_type=hub.GetHubRequest): assert response.unique_id == "unique_id_value" + assert response.state == hub.State.CREATING + def test_get_hub_from_dict(): test_get_hub(request_type=dict) @@ -819,6 +805,7 @@ async def test_get_hub_async( description="description_value", spokes=["spokes_value"], unique_id="unique_id_value", + state=hub.State.CREATING, ) ) @@ -841,6 +828,8 @@ async def test_get_hub_async( assert response.unique_id == "unique_id_value" + assert response.state == hub.State.CREATING + @pytest.mark.asyncio async def test_get_hub_async_from_dict(): @@ -1868,6 +1857,7 @@ def test_get_spoke(transport: str = "grpc", request_type=hub.GetSpokeRequest): linked_vpn_tunnels=["linked_vpn_tunnels_value"], linked_interconnect_attachments=["linked_interconnect_attachments_value"], unique_id="unique_id_value", + state=hub.State.CREATING, ) response = client.get_spoke(request) @@ -1896,6 +1886,8 @@ def test_get_spoke(transport: str = "grpc", request_type=hub.GetSpokeRequest): assert response.unique_id == "unique_id_value" + assert response.state == hub.State.CREATING + def test_get_spoke_from_dict(): test_get_spoke(request_type=dict) @@ -1926,6 +1918,7 @@ async def test_get_spoke_async( "linked_interconnect_attachments_value" ], unique_id="unique_id_value", + state=hub.State.CREATING, ) ) @@ -1954,6 +1947,8 @@ async def test_get_spoke_async( assert response.unique_id == "unique_id_value" + assert response.state == hub.State.CREATING + @pytest.mark.asyncio async def test_get_spoke_async_from_dict(): @@ -2832,6 +2827,48 @@ def test_hub_service_transport_auth_adc(): ) +@pytest.mark.parametrize( + "transport_class", + [transports.HubServiceGrpcTransport, transports.HubServiceGrpcAsyncIOTransport], +) +def test_hub_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_hub_service_host_no_port(): client = HubServiceClient( credentials=credentials.AnonymousCredentials(), @@ -2876,6 +2913,8 @@ def test_hub_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", [transports.HubServiceGrpcTransport, transports.HubServiceGrpcAsyncIOTransport], @@ -2923,6 +2962,8 @@ def test_hub_service_transport_channel_mtls_with_client_cert_source(transport_cl 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", [transports.HubServiceGrpcTransport, transports.HubServiceGrpcAsyncIOTransport],