diff --git a/.github/snippet-bot.yml b/.github/snippet-bot.yml new file mode 100644 index 00000000..e69de29b diff --git a/.kokoro/docs/common.cfg b/.kokoro/docs/common.cfg index d766113d..6aa886d6 100644 --- a/.kokoro/docs/common.cfg +++ b/.kokoro/docs/common.cfg @@ -30,7 +30,7 @@ env_vars: { env_vars: { key: "V2_STAGING_BUCKET" - value: "docs-staging-v2-staging" + value: "docs-staging-v2" } # It will upload the docker image after successful builds. diff --git a/.kokoro/populate-secrets.sh b/.kokoro/populate-secrets.sh new file mode 100755 index 00000000..f5251425 --- /dev/null +++ b/.kokoro/populate-secrets.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# 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. + +set -eo pipefail + +function now { date +"%Y-%m-%d %H:%M:%S" | tr -d '\n' ;} +function msg { println "$*" >&2 ;} +function println { printf '%s\n' "$(now) $*" ;} + + +# Populates requested secrets set in SECRET_MANAGER_KEYS from service account: +# kokoro-trampoline@cloud-devrel-kokoro-resources.iam.gserviceaccount.com +SECRET_LOCATION="${KOKORO_GFILE_DIR}/secret_manager" +msg "Creating folder on disk for secrets: ${SECRET_LOCATION}" +mkdir -p ${SECRET_LOCATION} +for key in $(echo ${SECRET_MANAGER_KEYS} | sed "s/,/ /g") +do + msg "Retrieving secret ${key}" + docker run --entrypoint=gcloud \ + --volume=${KOKORO_GFILE_DIR}:${KOKORO_GFILE_DIR} \ + gcr.io/google.com/cloudsdktool/cloud-sdk \ + secrets versions access latest \ + --project cloud-devrel-kokoro-resources \ + --secret ${key} > \ + "${SECRET_LOCATION}/${key}" + if [[ $? == 0 ]]; then + msg "Secret written to ${SECRET_LOCATION}/${key}" + else + msg "Error retrieving secret ${key}" + fi +done diff --git a/.kokoro/release/common.cfg b/.kokoro/release/common.cfg index 7b7697ca..420fb631 100644 --- a/.kokoro/release/common.cfg +++ b/.kokoro/release/common.cfg @@ -23,42 +23,18 @@ env_vars: { value: "github/python-game-servers/.kokoro/release.sh" } -# Fetch the token needed for reporting release status to GitHub -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "yoshi-automation-github-key" - } - } -} - -# Fetch PyPI password -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "google_cloud_pypi_password" - } - } -} - -# Fetch magictoken to use with Magic Github Proxy -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "releasetool-magictoken" - } - } +# Fetch PyPI password +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73713 + keyname: "google_cloud_pypi_password" + } + } } -# Fetch api key to use with Magic Github Proxy -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "magic-github-proxy-api-key" - } - } -} +# Tokens needed to report release status back to GitHub +env_vars: { + key: "SECRET_MANAGER_KEYS" + value: "releasetool-publish-reporter-app,releasetool-publish-reporter-googleapis-installation,releasetool-publish-reporter-pem" +} \ No newline at end of file diff --git a/.kokoro/samples/python3.6/common.cfg b/.kokoro/samples/python3.6/common.cfg index 2bcbe6e9..0322d83b 100644 --- a/.kokoro/samples/python3.6/common.cfg +++ b/.kokoro/samples/python3.6/common.cfg @@ -13,6 +13,12 @@ env_vars: { value: "py-3.6" } +# Declare build specific Cloud project. +env_vars: { + key: "BUILD_SPECIFIC_GCLOUD_PROJECT" + value: "python-docs-samples-tests-py36" +} + env_vars: { key: "TRAMPOLINE_BUILD_FILE" value: "github/python-game-servers/.kokoro/test-samples.sh" diff --git a/.kokoro/samples/python3.7/common.cfg b/.kokoro/samples/python3.7/common.cfg index fd5fcd69..4d47c263 100644 --- a/.kokoro/samples/python3.7/common.cfg +++ b/.kokoro/samples/python3.7/common.cfg @@ -13,6 +13,12 @@ env_vars: { value: "py-3.7" } +# Declare build specific Cloud project. +env_vars: { + key: "BUILD_SPECIFIC_GCLOUD_PROJECT" + value: "python-docs-samples-tests-py37" +} + env_vars: { key: "TRAMPOLINE_BUILD_FILE" value: "github/python-game-servers/.kokoro/test-samples.sh" diff --git a/.kokoro/samples/python3.8/common.cfg b/.kokoro/samples/python3.8/common.cfg index 31cd062b..317abb26 100644 --- a/.kokoro/samples/python3.8/common.cfg +++ b/.kokoro/samples/python3.8/common.cfg @@ -13,6 +13,12 @@ env_vars: { value: "py-3.8" } +# Declare build specific Cloud project. +env_vars: { + key: "BUILD_SPECIFIC_GCLOUD_PROJECT" + value: "python-docs-samples-tests-py38" +} + env_vars: { key: "TRAMPOLINE_BUILD_FILE" value: "github/python-game-servers/.kokoro/test-samples.sh" diff --git a/.kokoro/test-samples.sh b/.kokoro/test-samples.sh index 4be76015..042b950e 100755 --- a/.kokoro/test-samples.sh +++ b/.kokoro/test-samples.sh @@ -28,6 +28,12 @@ if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then git checkout $LATEST_RELEASE fi +# Exit early if samples directory doesn't exist +if [ ! -d "./samples" ]; then + echo "No tests run. `./samples` not found" + exit 0 +fi + # Disable buffering, so that the logs stream through. export PYTHONUNBUFFERED=1 @@ -101,4 +107,4 @@ cd "$ROOT" # Workaround for Kokoro permissions issue: delete secrets rm testing/{test-env.sh,client-secrets.json,service-account.json} -exit "$RTN" \ No newline at end of file +exit "$RTN" diff --git a/.kokoro/trampoline.sh b/.kokoro/trampoline.sh index e8c4251f..f39236e9 100755 --- a/.kokoro/trampoline.sh +++ b/.kokoro/trampoline.sh @@ -15,9 +15,14 @@ set -eo pipefail -python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py" || ret_code=$? +# Always run the cleanup script, regardless of the success of bouncing into +# the container. +function cleanup() { + chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh + ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh + echo "cleanup"; +} +trap cleanup EXIT -chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh -${KOKORO_GFILE_DIR}/trampoline_cleanup.sh || true - -exit ${ret_code} +$(dirname $0)/populate-secrets.sh # Secret Manager secrets. +python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py" \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index b3d1f602..039f4368 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,44 +1,95 @@ -# Contributor Code of Conduct +# Code of Conduct -As contributors and maintainers of this project, -and in the interest of fostering an open and welcoming community, -we pledge to respect all people who contribute through reporting issues, -posting feature requests, updating documentation, -submitting pull requests or patches, and other activities. +## Our Pledge -We are committed to making participation in this project -a harassment-free experience for everyone, -regardless of level of experience, gender, gender identity and expression, -sexual orientation, disability, personal appearance, -body size, race, ethnicity, age, religion, or nationality. +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of +experience, education, socio-economic status, nationality, personal appearance, +race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members Examples of unacceptable behavior by participants include: -* The use of sexualized language or imagery -* Personal attacks -* Trolling or insulting/derogatory comments -* Public or private harassment -* Publishing other's private information, -such as physical or electronic -addresses, without explicit permission -* Other unethical or unprofessional conduct. +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct. -By adopting this Code of Conduct, -project maintainers commit themselves to fairly and consistently -applying these principles to every aspect of managing this project. -Project maintainers who do not follow or enforce the Code of Conduct -may be permanently removed from the project team. - -This code of conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. - -Instances of abusive, harassing, or otherwise unacceptable behavior -may be reported by opening an issue -or contacting one or more of the project maintainers. - -This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, -available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, or to ban temporarily or permanently any +contributor for other behaviors that they deem inappropriate, threatening, +offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +This Code of Conduct also applies outside the project spaces when the Project +Steward has a reasonable belief that an individual's behavior may have a +negative impact on the project or its community. + +## Conflict Resolution + +We do not believe that all conflict is bad; healthy debate and disagreement +often yield positive results. However, it is never okay to be disrespectful or +to engage in behavior that violates the project’s code of conduct. + +If you see someone violating the code of conduct, you are encouraged to address +the behavior directly with those involved. Many issues can be resolved quickly +and easily, and this gives people more control over the outcome of their +dispute. If you are unable to resolve the matter for any reason, or if the +behavior is threatening or harassing, report it. We are dedicated to providing +an environment where participants feel welcome and safe. + + +Reports should be directed to *googleapis-stewards@google.com*, the +Project Steward(s) for *Google Cloud Client Libraries*. It is the Project Steward’s duty to +receive and address reported violations of the code of conduct. They will then +work with a committee consisting of representatives from the Open Source +Programs Office and the Google Open Source Strategy team. If for any reason you +are uncomfortable reaching out to the Project Steward, please email +opensource@google.com. + +We will investigate every complaint, but you may not receive a direct response. +We will use our discretion in determining when and how to follow up on reported +incidents, which may range from not taking action to permanent expulsion from +the project and project-sponsored spaces. We will notify the accused of the +report and provide them an opportunity to discuss it before any action is taken. +The identity of the reporter will be omitted from the details of the report +supplied to the accused. In potentially harmful situations, such as ongoing +harassment or threats to anyone's safety, we may take action without notice. + +## Attribution + +This Code of Conduct is adapted from the Contributor Covenant, version 1.4, +available at +https://www.contributor-covenant.org/version/1/4/code-of-conduct.html \ No newline at end of file diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index b4d21d6b..98391e75 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -80,25 +80,6 @@ We use `nox `__ to instrument our tests. .. nox: https://pypi.org/project/nox/ -Note on Editable Installs / Develop Mode -======================================== - -- As mentioned previously, using ``setuptools`` in `develop mode`_ - or a ``pip`` `editable install`_ is not possible with this - library. This is because this library uses `namespace packages`_. - For context see `Issue #2316`_ and the relevant `PyPA issue`_. - - Since ``editable`` / ``develop`` mode can't be used, packages - need to be installed directly. Hence your changes to the source - tree don't get incorporated into the **already installed** - package. - -.. _namespace packages: https://www.python.org/dev/peps/pep-0420/ -.. _Issue #2316: https://github.com/GoogleCloudPlatform/google-cloud-python/issues/2316 -.. _PyPA issue: https://github.com/pypa/packaging-problems/issues/12 -.. _develop mode: https://setuptools.readthedocs.io/en/latest/setuptools.html#development-mode -.. _editable install: https://pip.pypa.io/en/stable/reference/pip_install/#editable-installs - ***************************************** I'm getting weird errors... Can you help? ***************************************** diff --git a/docs/conf.py b/docs/conf.py index 83681ccb..9a955c89 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -29,7 +29,7 @@ # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = "1.6.3" +needs_sphinx = "1.5.5" # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom @@ -39,6 +39,7 @@ "sphinx.ext.autosummary", "sphinx.ext.intersphinx", "sphinx.ext.coverage", + "sphinx.ext.doctest", "sphinx.ext.napoleon", "sphinx.ext.todo", "sphinx.ext.viewcode", @@ -348,6 +349,7 @@ "google-auth": ("https://google-auth.readthedocs.io/en/stable", None), "google.api_core": ("https://googleapis.dev/python/google-api-core/latest/", None,), "grpc": ("https://grpc.io/grpc/python/", None), + "proto-plus": ("https://proto-plus-python.readthedocs.io/en/latest/", None), } diff --git a/docs/gaming_v1/types.rst b/docs/gaming_v1/types.rst index 0396ea47..dfd145a1 100644 --- a/docs/gaming_v1/types.rst +++ b/docs/gaming_v1/types.rst @@ -3,3 +3,4 @@ Types for Google Cloud Gaming v1 API .. automodule:: google.cloud.gaming_v1.types :members: + :show-inheritance: diff --git a/docs/gaming_v1beta/types.rst b/docs/gaming_v1beta/types.rst index da332a14..0d4debed 100644 --- a/docs/gaming_v1beta/types.rst +++ b/docs/gaming_v1beta/types.rst @@ -3,3 +3,4 @@ Types for Google Cloud Gaming v1beta API .. automodule:: google.cloud.gaming_v1beta.types :members: + :show-inheritance: diff --git a/google/cloud/gaming_v1/__init__.py b/google/cloud/gaming_v1/__init__.py index ad0f876b..cddeaeec 100644 --- a/google/cloud/gaming_v1/__init__.py +++ b/google/cloud/gaming_v1/__init__.py @@ -95,6 +95,7 @@ "GameServerClustersServiceClient", "GameServerConfig", "GameServerConfigOverride", + "GameServerConfigsServiceClient", "GameServerDeployment", "GameServerDeploymentRollout", "GameServerDeploymentsServiceClient", @@ -127,7 +128,6 @@ "PreviewUpdateGameServerClusterResponse", "Realm", "RealmSelector", - "RealmsServiceClient", "ScalingConfig", "Schedule", "SpecSource", @@ -137,5 +137,5 @@ "UpdateGameServerDeploymentRequest", "UpdateGameServerDeploymentRolloutRequest", "UpdateRealmRequest", - "GameServerConfigsServiceClient", + "RealmsServiceClient", ) diff --git a/google/cloud/gaming_v1/services/game_server_clusters_service/async_client.py b/google/cloud/gaming_v1/services/game_server_clusters_service/async_client.py index 124176f2..9e6f157c 100644 --- a/google/cloud/gaming_v1/services/game_server_clusters_service/async_client.py +++ b/google/cloud/gaming_v1/services/game_server_clusters_service/async_client.py @@ -28,8 +28,8 @@ from google.auth import credentials # type: ignore from google.oauth2 import service_account # type: ignore -from google.api_core import operation -from google.api_core import operation_async +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore from google.cloud.gaming_v1.services.game_server_clusters_service import pagers from google.cloud.gaming_v1.types import common from google.cloud.gaming_v1.types import game_server_clusters @@ -37,7 +37,7 @@ from google.protobuf import field_mask_pb2 as field_mask # type: ignore from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from .transports.base import GameServerClustersServiceTransport +from .transports.base import GameServerClustersServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc_asyncio import GameServerClustersServiceGrpcAsyncIOTransport from .client import GameServerClustersServiceClient @@ -55,12 +55,59 @@ class GameServerClustersServiceAsyncClient: game_server_cluster_path = staticmethod( GameServerClustersServiceClient.game_server_cluster_path ) + parse_game_server_cluster_path = staticmethod( + GameServerClustersServiceClient.parse_game_server_cluster_path + ) + + common_billing_account_path = staticmethod( + GameServerClustersServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + GameServerClustersServiceClient.parse_common_billing_account_path + ) + + common_folder_path = staticmethod( + GameServerClustersServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + GameServerClustersServiceClient.parse_common_folder_path + ) + + common_organization_path = staticmethod( + GameServerClustersServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + GameServerClustersServiceClient.parse_common_organization_path + ) + + common_project_path = staticmethod( + GameServerClustersServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + GameServerClustersServiceClient.parse_common_project_path + ) + + common_location_path = staticmethod( + GameServerClustersServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + GameServerClustersServiceClient.parse_common_location_path + ) from_service_account_file = ( GameServerClustersServiceClient.from_service_account_file ) from_service_account_json = from_service_account_file + @property + def transport(self) -> GameServerClustersServiceTransport: + """Return the transport used by the client instance. + + Returns: + GameServerClustersServiceTransport: The transport used by the client instance. + """ + return self._client.transport + get_transport_class = functools.partial( type(GameServerClustersServiceClient).get_transport_class, type(GameServerClustersServiceClient), @@ -72,6 +119,7 @@ def __init__( credentials: credentials.Credentials = None, transport: Union[str, GameServerClustersServiceTransport] = "grpc_asyncio", client_options: ClientOptions = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the game server clusters service client. @@ -87,16 +135,19 @@ def __init__( client_options (ClientOptions): Custom options for the client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT environment variable can also be used to override the endpoint: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint, this is the default value for - the environment variable) and "auto" (auto switch to the default - mTLS endpoint if client SSL credentials is present). However, - the ``api_endpoint`` property takes precedence if provided. - (2) The ``client_cert_source`` property is used to provide client - SSL credentials for mutual TLS transport. If not provided, the - default SSL credentials will be used if present. + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -104,7 +155,10 @@ def __init__( """ self._client = GameServerClustersServiceClient( - credentials=credentials, transport=transport, client_options=client_options, + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, ) async def list_game_server_clusters( @@ -149,7 +203,8 @@ async def list_game_server_clusters( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([parent]): + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -174,7 +229,7 @@ async def list_game_server_clusters( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -232,7 +287,8 @@ async def get_game_server_cluster( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -257,7 +313,7 @@ async def get_game_server_cluster( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -327,9 +383,10 @@ async def create_game_server_cluster( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any( + has_flattened_params = any( [parent, game_server_cluster, game_server_cluster_id] - ): + ) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -352,7 +409,7 @@ async def create_game_server_cluster( rpc = gapic_v1.method_async.wrap_method( self._client._transport.create_game_server_cluster, default_timeout=120.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -418,7 +475,7 @@ async def preview_create_game_server_cluster( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -486,7 +543,8 @@ async def delete_game_server_cluster( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -505,7 +563,7 @@ async def delete_game_server_cluster( rpc = gapic_v1.method_async.wrap_method( self._client._transport.delete_game_server_cluster, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -570,7 +628,7 @@ async def preview_delete_game_server_cluster( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -636,7 +694,8 @@ async def update_game_server_cluster( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([game_server_cluster, update_mask]): + has_flattened_params = any([game_server_cluster, update_mask]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -657,7 +716,7 @@ async def update_game_server_cluster( rpc = gapic_v1.method_async.wrap_method( self._client._transport.update_game_server_cluster, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -724,7 +783,7 @@ async def preview_update_game_server_cluster( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -743,13 +802,13 @@ async def preview_update_game_server_cluster( try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ("GameServerClustersServiceAsyncClient",) diff --git a/google/cloud/gaming_v1/services/game_server_clusters_service/client.py b/google/cloud/gaming_v1/services/game_server_clusters_service/client.py index 608f482e..356ad140 100644 --- a/google/cloud/gaming_v1/services/game_server_clusters_service/client.py +++ b/google/cloud/gaming_v1/services/game_server_clusters_service/client.py @@ -16,22 +16,24 @@ # from collections import OrderedDict +from distutils import util import os import re -from typing import Callable, Dict, Sequence, Tuple, Type, Union +from typing import Callable, Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore +from google.api_core import client_options as client_options_lib # type: ignore from google.api_core import exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore from google.auth import credentials # type: ignore from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore -from google.api_core import operation -from google.api_core import operation_async +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore from google.cloud.gaming_v1.services.game_server_clusters_service import pagers from google.cloud.gaming_v1.types import common from google.cloud.gaming_v1.types import game_server_clusters @@ -39,7 +41,7 @@ from google.protobuf import field_mask_pb2 as field_mask # type: ignore from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from .transports.base import GameServerClustersServiceTransport +from .transports.base import GameServerClustersServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc import GameServerClustersServiceGrpcTransport from .transports.grpc_asyncio import GameServerClustersServiceGrpcAsyncIOTransport @@ -138,6 +140,15 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): from_service_account_json = from_service_account_file + @property + def transport(self) -> GameServerClustersServiceTransport: + """Return the transport used by the client instance. + + Returns: + GameServerClustersServiceTransport: The transport used by the client instance. + """ + return self._transport + @staticmethod def game_server_cluster_path( project: str, location: str, realm: str, cluster: str, @@ -156,12 +167,72 @@ def parse_game_server_cluster_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def common_billing_account_path(billing_account: str,) -> str: + """Return a fully-qualified billing_account string.""" + return "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + + @staticmethod + def parse_common_billing_account_path(path: str) -> Dict[str, str]: + """Parse a billing_account path into its component segments.""" + m = re.match(r"^billingAccounts/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_folder_path(folder: str,) -> str: + """Return a fully-qualified folder string.""" + return "folders/{folder}".format(folder=folder,) + + @staticmethod + def parse_common_folder_path(path: str) -> Dict[str, str]: + """Parse a folder path into its component segments.""" + m = re.match(r"^folders/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_organization_path(organization: str,) -> str: + """Return a fully-qualified organization string.""" + return "organizations/{organization}".format(organization=organization,) + + @staticmethod + def parse_common_organization_path(path: str) -> Dict[str, str]: + """Parse a organization path into its component segments.""" + m = re.match(r"^organizations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_project_path(project: str,) -> str: + """Return a fully-qualified project string.""" + return "projects/{project}".format(project=project,) + + @staticmethod + def parse_common_project_path(path: str) -> Dict[str, str]: + """Parse a project path into its component segments.""" + m = re.match(r"^projects/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_location_path(project: str, location: str,) -> str: + """Return a fully-qualified location string.""" + return "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + + @staticmethod + def parse_common_location_path(path: str) -> Dict[str, str]: + """Parse a location path into its component segments.""" + m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path) + return m.groupdict() if m else {} + def __init__( self, *, - credentials: credentials.Credentials = None, - transport: Union[str, GameServerClustersServiceTransport] = None, - client_options: ClientOptions = None, + credentials: Optional[credentials.Credentials] = None, + transport: Union[str, GameServerClustersServiceTransport, None] = None, + client_options: Optional[client_options_lib.ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the game server clusters service client. @@ -174,48 +245,74 @@ def __init__( transport (Union[str, ~.GameServerClustersServiceTransport]): The transport to use. If set to None, a transport is chosen automatically. - client_options (ClientOptions): Custom options for the client. It - won't take effect if a ``transport`` instance is provided. + client_options (client_options_lib.ClientOptions): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT environment variable can also be used to override the endpoint: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint, this is the default value for - the environment variable) and "auto" (auto switch to the default - mTLS endpoint if client SSL credentials is present). However, - the ``api_endpoint`` property takes precedence if provided. - (2) The ``client_cert_source`` property is used to provide client - SSL credentials for mutual TLS transport. If not provided, the - default SSL credentials will be used if present. + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport creation failed for any reason. """ if isinstance(client_options, dict): - client_options = ClientOptions.from_dict(client_options) + client_options = client_options_lib.from_dict(client_options) if client_options is None: - client_options = ClientOptions.ClientOptions() + client_options = client_options_lib.ClientOptions() + + # Create SSL credentials for mutual TLS if needed. + use_client_cert = bool( + util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + ) - if client_options.api_endpoint is None: - use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS", "never") + ssl_credentials = 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 + else: + creds = SslCredentials() + is_mtls = creds.is_mtls + ssl_credentials = creds.ssl_credentials if is_mtls else None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") if use_mtls_env == "never": - client_options.api_endpoint = self.DEFAULT_ENDPOINT + api_endpoint = self.DEFAULT_ENDPOINT elif use_mtls_env == "always": - client_options.api_endpoint = self.DEFAULT_MTLS_ENDPOINT + api_endpoint = self.DEFAULT_MTLS_ENDPOINT elif use_mtls_env == "auto": - has_client_cert_source = ( - client_options.client_cert_source is not None - or mtls.has_default_client_cert_source() - ) - client_options.api_endpoint = ( - self.DEFAULT_MTLS_ENDPOINT - if has_client_cert_source - else self.DEFAULT_ENDPOINT + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT if is_mtls else self.DEFAULT_ENDPOINT ) else: raise MutualTLSChannelError( - "Unsupported GOOGLE_API_USE_MTLS value. Accepted values: never, auto, always" + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always" ) # Save or instantiate the transport. @@ -239,11 +336,11 @@ def __init__( self._transport = Transport( credentials=credentials, credentials_file=client_options.credentials_file, - host=client_options.api_endpoint, + host=api_endpoint, scopes=client_options.scopes, - api_mtls_endpoint=client_options.api_endpoint, - client_cert_source=client_options.client_cert_source, + ssl_channel_credentials=ssl_credentials, quota_project_id=client_options.quota_project_id, + client_info=client_info, ) def list_game_server_clusters( @@ -891,13 +988,13 @@ def preview_update_game_server_cluster( try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ("GameServerClustersServiceClient",) diff --git a/google/cloud/gaming_v1/services/game_server_clusters_service/transports/base.py b/google/cloud/gaming_v1/services/game_server_clusters_service/transports/base.py index c8716436..ea91f479 100644 --- a/google/cloud/gaming_v1/services/game_server_clusters_service/transports/base.py +++ b/google/cloud/gaming_v1/services/game_server_clusters_service/transports/base.py @@ -19,7 +19,7 @@ import typing import pkg_resources -from google import auth +from google import auth # type: ignore from google.api_core import exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore @@ -31,13 +31,13 @@ try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() class GameServerClustersServiceTransport(abc.ABC): @@ -53,6 +53,7 @@ def __init__( credentials_file: typing.Optional[str] = None, scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES, quota_project_id: typing.Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, **kwargs, ) -> None: """Instantiate the transport. @@ -70,6 +71,11 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -97,9 +103,9 @@ def __init__( self._credentials = credentials # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages() + self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self): + def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { self.list_game_server_clusters: gapic_v1.method.wrap_method( @@ -111,7 +117,7 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.get_game_server_cluster: gapic_v1.method.wrap_method( self.get_game_server_cluster, @@ -122,12 +128,12 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.create_game_server_cluster: gapic_v1.method.wrap_method( self.create_game_server_cluster, default_timeout=120.0, - client_info=_client_info, + client_info=client_info, ), self.preview_create_game_server_cluster: gapic_v1.method.wrap_method( self.preview_create_game_server_cluster, @@ -138,12 +144,12 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.delete_game_server_cluster: gapic_v1.method.wrap_method( self.delete_game_server_cluster, default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.preview_delete_game_server_cluster: gapic_v1.method.wrap_method( self.preview_delete_game_server_cluster, @@ -154,12 +160,12 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.update_game_server_cluster: gapic_v1.method.wrap_method( self.update_game_server_cluster, default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.preview_update_game_server_cluster: gapic_v1.method.wrap_method( self.preview_update_game_server_cluster, @@ -170,7 +176,7 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), } diff --git a/google/cloud/gaming_v1/services/game_server_clusters_service/transports/grpc.py b/google/cloud/gaming_v1/services/game_server_clusters_service/transports/grpc.py index b3130ac2..39efb978 100644 --- a/google/cloud/gaming_v1/services/game_server_clusters_service/transports/grpc.py +++ b/google/cloud/gaming_v1/services/game_server_clusters_service/transports/grpc.py @@ -15,21 +15,22 @@ # limitations under the License. # +import warnings from typing import Callable, Dict, Optional, Sequence, Tuple from google.api_core import grpc_helpers # type: ignore from google.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 # type: ignore from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore - import grpc # type: ignore from google.cloud.gaming_v1.types import game_server_clusters from google.longrunning import operations_pb2 as operations # type: ignore -from .base import GameServerClustersServiceTransport +from .base import GameServerClustersServiceTransport, DEFAULT_CLIENT_INFO class GameServerClustersServiceGrpcTransport(GameServerClustersServiceTransport): @@ -58,7 +59,9 @@ def __init__( channel: grpc.Channel = None, api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, - quota_project_id: Optional[str] = None + ssl_channel_credentials: grpc.ChannelCredentials = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -77,16 +80,23 @@ def __init__( ignored if ``channel`` is provided. channel (Optional[grpc.Channel]): A ``Channel`` instance through which to make calls. - api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If - provided, it overrides the ``host`` argument and tries to create + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from ``client_cert_source`` or applicatin default SSL credentials. - client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A - callback to provide client SSL certificate bytes and private key - bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` - is None. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for grpc channel. It is ignored if ``channel`` 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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -94,6 +104,8 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._ssl_channel_credentials = ssl_channel_credentials + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -101,7 +113,13 @@ def __init__( # If a channel was explicitly provided, set it. 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 @@ -132,6 +150,24 @@ def __init__( scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, ) + self._ssl_channel_credentials = ssl_credentials + else: + host = host if ":" in host else host + ":443" + + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + + # 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, + scopes=scopes or self.AUTH_SCOPES, + quota_project_id=quota_project_id, + ) self._stubs = {} # type: Dict[str, Callable] @@ -142,6 +178,7 @@ def __init__( credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) @classmethod @@ -152,7 +189,7 @@ def create_channel( credentials_file: str = None, scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, - **kwargs + **kwargs, ) -> grpc.Channel: """Create and return a gRPC channel object. Args: @@ -186,24 +223,13 @@ def create_channel( credentials_file=credentials_file, scopes=scopes, quota_project_id=quota_project_id, - **kwargs + **kwargs, ) @property def grpc_channel(self) -> grpc.Channel: - """Create the channel designed to connect to this service. - - This property caches on the instance; repeated calls return - the same channel. + """Return the channel designed to connect to this service. """ - # Sanity check: Only create a new channel if we do not already - # have one. - if not hasattr(self, "_grpc_channel"): - self._grpc_channel = self.create_channel( - self._host, credentials=self._credentials, - ) - - # Return the channel from cache. return self._grpc_channel @property diff --git a/google/cloud/gaming_v1/services/game_server_clusters_service/transports/grpc_asyncio.py b/google/cloud/gaming_v1/services/game_server_clusters_service/transports/grpc_asyncio.py index 4b8e913f..7813f611 100644 --- a/google/cloud/gaming_v1/services/game_server_clusters_service/transports/grpc_asyncio.py +++ b/google/cloud/gaming_v1/services/game_server_clusters_service/transports/grpc_asyncio.py @@ -15,10 +15,13 @@ # limitations under the License. # +import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple +from google.api_core import gapic_v1 # type: ignore from google.api_core import grpc_helpers_async # type: ignore from google.api_core import operations_v1 # type: ignore +from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -28,7 +31,7 @@ from google.cloud.gaming_v1.types import game_server_clusters from google.longrunning import operations_pb2 as operations # type: ignore -from .base import GameServerClustersServiceTransport +from .base import GameServerClustersServiceTransport, DEFAULT_CLIENT_INFO from .grpc import GameServerClustersServiceGrpcTransport @@ -100,7 +103,9 @@ def __init__( channel: aio.Channel = None, api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, + ssl_channel_credentials: grpc.ChannelCredentials = None, quota_project_id=None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -120,16 +125,23 @@ def __init__( are passed to :func:`google.auth.default`. channel (Optional[aio.Channel]): A ``Channel`` instance through which to make calls. - api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If - provided, it overrides the ``host`` argument and tries to create + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from ``client_cert_source`` or applicatin default SSL credentials. - client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A - callback to provide client SSL certificate bytes and private key - bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` - is None. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for grpc channel. It is ignored if ``channel`` 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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -137,6 +149,8 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._ssl_channel_credentials = ssl_channel_credentials + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -144,13 +158,24 @@ def __init__( # If a channel was explicitly provided, set it. 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 else api_mtls_endpoint + ":443" ) + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + # Create SSL credentials with client_cert_source or application # default SSL credentials. if client_cert_source: @@ -170,6 +195,24 @@ def __init__( scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, ) + self._ssl_channel_credentials = ssl_credentials + else: + host = host if ":" in host else host + ":443" + + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + + # 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, + scopes=scopes or self.AUTH_SCOPES, + quota_project_id=quota_project_id, + ) # Run the base constructor. super().__init__( @@ -178,6 +221,7 @@ def __init__( credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) self._stubs = {} @@ -189,13 +233,6 @@ def grpc_channel(self) -> aio.Channel: This property caches on the instance; repeated calls return the same channel. """ - # Sanity check: Only create a new channel if we do not already - # have one. - if not hasattr(self, "_grpc_channel"): - self._grpc_channel = self.create_channel( - self._host, credentials=self._credentials, - ) - # Return the channel from cache. return self._grpc_channel diff --git a/google/cloud/gaming_v1/services/game_server_configs_service/async_client.py b/google/cloud/gaming_v1/services/game_server_configs_service/async_client.py index 888999da..57b7d0c1 100644 --- a/google/cloud/gaming_v1/services/game_server_configs_service/async_client.py +++ b/google/cloud/gaming_v1/services/game_server_configs_service/async_client.py @@ -28,15 +28,15 @@ from google.auth import credentials # type: ignore from google.oauth2 import service_account # type: ignore -from google.api_core import operation -from google.api_core import operation_async +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore from google.cloud.gaming_v1.services.game_server_configs_service import pagers from google.cloud.gaming_v1.types import common from google.cloud.gaming_v1.types import game_server_configs from google.protobuf import empty_pb2 as empty # type: ignore from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from .transports.base import GameServerConfigsServiceTransport +from .transports.base import GameServerConfigsServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc_asyncio import GameServerConfigsServiceGrpcAsyncIOTransport from .client import GameServerConfigsServiceClient @@ -54,10 +54,55 @@ class GameServerConfigsServiceAsyncClient: game_server_config_path = staticmethod( GameServerConfigsServiceClient.game_server_config_path ) + parse_game_server_config_path = staticmethod( + GameServerConfigsServiceClient.parse_game_server_config_path + ) + + common_billing_account_path = staticmethod( + GameServerConfigsServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + GameServerConfigsServiceClient.parse_common_billing_account_path + ) + + common_folder_path = staticmethod(GameServerConfigsServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + GameServerConfigsServiceClient.parse_common_folder_path + ) + + common_organization_path = staticmethod( + GameServerConfigsServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + GameServerConfigsServiceClient.parse_common_organization_path + ) + + common_project_path = staticmethod( + GameServerConfigsServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + GameServerConfigsServiceClient.parse_common_project_path + ) + + common_location_path = staticmethod( + GameServerConfigsServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + GameServerConfigsServiceClient.parse_common_location_path + ) from_service_account_file = GameServerConfigsServiceClient.from_service_account_file from_service_account_json = from_service_account_file + @property + def transport(self) -> GameServerConfigsServiceTransport: + """Return the transport used by the client instance. + + Returns: + GameServerConfigsServiceTransport: The transport used by the client instance. + """ + return self._client.transport + get_transport_class = functools.partial( type(GameServerConfigsServiceClient).get_transport_class, type(GameServerConfigsServiceClient), @@ -69,6 +114,7 @@ def __init__( credentials: credentials.Credentials = None, transport: Union[str, GameServerConfigsServiceTransport] = "grpc_asyncio", client_options: ClientOptions = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the game server configs service client. @@ -84,16 +130,19 @@ def __init__( client_options (ClientOptions): Custom options for the client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT environment variable can also be used to override the endpoint: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint, this is the default value for - the environment variable) and "auto" (auto switch to the default - mTLS endpoint if client SSL credentials is present). However, - the ``api_endpoint`` property takes precedence if provided. - (2) The ``client_cert_source`` property is used to provide client - SSL credentials for mutual TLS transport. If not provided, the - default SSL credentials will be used if present. + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -101,7 +150,10 @@ def __init__( """ self._client = GameServerConfigsServiceClient( - credentials=credentials, transport=transport, client_options=client_options, + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, ) async def list_game_server_configs( @@ -146,7 +198,8 @@ async def list_game_server_configs( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([parent]): + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -171,7 +224,7 @@ async def list_game_server_configs( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -229,7 +282,8 @@ async def get_game_server_config( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -254,7 +308,7 @@ async def get_game_server_config( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -321,7 +375,8 @@ async def create_game_server_config( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([parent, game_server_config]): + has_flattened_params = any([parent, game_server_config]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -342,7 +397,7 @@ async def create_game_server_config( rpc = gapic_v1.method_async.wrap_method( self._client._transport.create_game_server_config, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -421,7 +476,8 @@ async def delete_game_server_config( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -440,7 +496,7 @@ async def delete_game_server_config( rpc = gapic_v1.method_async.wrap_method( self._client._transport.delete_game_server_config, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -465,13 +521,13 @@ async def delete_game_server_config( try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ("GameServerConfigsServiceAsyncClient",) diff --git a/google/cloud/gaming_v1/services/game_server_configs_service/client.py b/google/cloud/gaming_v1/services/game_server_configs_service/client.py index acef129e..fcb5a880 100644 --- a/google/cloud/gaming_v1/services/game_server_configs_service/client.py +++ b/google/cloud/gaming_v1/services/game_server_configs_service/client.py @@ -16,29 +16,31 @@ # from collections import OrderedDict +from distutils import util import os import re -from typing import Callable, Dict, Sequence, Tuple, Type, Union +from typing import Callable, Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore +from google.api_core import client_options as client_options_lib # type: ignore from google.api_core import exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore from google.auth import credentials # type: ignore from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore -from google.api_core import operation -from google.api_core import operation_async +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore from google.cloud.gaming_v1.services.game_server_configs_service import pagers from google.cloud.gaming_v1.types import common from google.cloud.gaming_v1.types import game_server_configs from google.protobuf import empty_pb2 as empty # type: ignore from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from .transports.base import GameServerConfigsServiceTransport +from .transports.base import GameServerConfigsServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc import GameServerConfigsServiceGrpcTransport from .transports.grpc_asyncio import GameServerConfigsServiceGrpcAsyncIOTransport @@ -137,6 +139,15 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): from_service_account_json = from_service_account_file + @property + def transport(self) -> GameServerConfigsServiceTransport: + """Return the transport used by the client instance. + + Returns: + GameServerConfigsServiceTransport: The transport used by the client instance. + """ + return self._transport + @staticmethod def game_server_config_path( project: str, location: str, deployment: str, config: str, @@ -155,12 +166,72 @@ def parse_game_server_config_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def common_billing_account_path(billing_account: str,) -> str: + """Return a fully-qualified billing_account string.""" + return "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + + @staticmethod + def parse_common_billing_account_path(path: str) -> Dict[str, str]: + """Parse a billing_account path into its component segments.""" + m = re.match(r"^billingAccounts/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_folder_path(folder: str,) -> str: + """Return a fully-qualified folder string.""" + return "folders/{folder}".format(folder=folder,) + + @staticmethod + def parse_common_folder_path(path: str) -> Dict[str, str]: + """Parse a folder path into its component segments.""" + m = re.match(r"^folders/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_organization_path(organization: str,) -> str: + """Return a fully-qualified organization string.""" + return "organizations/{organization}".format(organization=organization,) + + @staticmethod + def parse_common_organization_path(path: str) -> Dict[str, str]: + """Parse a organization path into its component segments.""" + m = re.match(r"^organizations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_project_path(project: str,) -> str: + """Return a fully-qualified project string.""" + return "projects/{project}".format(project=project,) + + @staticmethod + def parse_common_project_path(path: str) -> Dict[str, str]: + """Parse a project path into its component segments.""" + m = re.match(r"^projects/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_location_path(project: str, location: str,) -> str: + """Return a fully-qualified location string.""" + return "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + + @staticmethod + def parse_common_location_path(path: str) -> Dict[str, str]: + """Parse a location path into its component segments.""" + m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path) + return m.groupdict() if m else {} + def __init__( self, *, - credentials: credentials.Credentials = None, - transport: Union[str, GameServerConfigsServiceTransport] = None, - client_options: ClientOptions = None, + credentials: Optional[credentials.Credentials] = None, + transport: Union[str, GameServerConfigsServiceTransport, None] = None, + client_options: Optional[client_options_lib.ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the game server configs service client. @@ -173,48 +244,74 @@ def __init__( transport (Union[str, ~.GameServerConfigsServiceTransport]): The transport to use. If set to None, a transport is chosen automatically. - client_options (ClientOptions): Custom options for the client. It - won't take effect if a ``transport`` instance is provided. + client_options (client_options_lib.ClientOptions): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT environment variable can also be used to override the endpoint: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint, this is the default value for - the environment variable) and "auto" (auto switch to the default - mTLS endpoint if client SSL credentials is present). However, - the ``api_endpoint`` property takes precedence if provided. - (2) The ``client_cert_source`` property is used to provide client - SSL credentials for mutual TLS transport. If not provided, the - default SSL credentials will be used if present. + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport creation failed for any reason. """ if isinstance(client_options, dict): - client_options = ClientOptions.from_dict(client_options) + client_options = client_options_lib.from_dict(client_options) if client_options is None: - client_options = ClientOptions.ClientOptions() + client_options = client_options_lib.ClientOptions() + + # Create SSL credentials for mutual TLS if needed. + use_client_cert = bool( + util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + ) - if client_options.api_endpoint is None: - use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS", "never") + ssl_credentials = 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 + else: + creds = SslCredentials() + is_mtls = creds.is_mtls + ssl_credentials = creds.ssl_credentials if is_mtls else None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") if use_mtls_env == "never": - client_options.api_endpoint = self.DEFAULT_ENDPOINT + api_endpoint = self.DEFAULT_ENDPOINT elif use_mtls_env == "always": - client_options.api_endpoint = self.DEFAULT_MTLS_ENDPOINT + api_endpoint = self.DEFAULT_MTLS_ENDPOINT elif use_mtls_env == "auto": - has_client_cert_source = ( - client_options.client_cert_source is not None - or mtls.has_default_client_cert_source() - ) - client_options.api_endpoint = ( - self.DEFAULT_MTLS_ENDPOINT - if has_client_cert_source - else self.DEFAULT_ENDPOINT + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT if is_mtls else self.DEFAULT_ENDPOINT ) else: raise MutualTLSChannelError( - "Unsupported GOOGLE_API_USE_MTLS value. Accepted values: never, auto, always" + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always" ) # Save or instantiate the transport. @@ -238,11 +335,11 @@ def __init__( self._transport = Transport( credentials=credentials, credentials_file=client_options.credentials_file, - host=client_options.api_endpoint, + host=api_endpoint, scopes=client_options.scopes, - api_mtls_endpoint=client_options.api_endpoint, - client_cert_source=client_options.client_cert_source, + ssl_channel_credentials=ssl_credentials, quota_project_id=client_options.quota_project_id, + client_info=client_info, ) def list_game_server_configs( @@ -606,13 +703,13 @@ def delete_game_server_config( try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ("GameServerConfigsServiceClient",) diff --git a/google/cloud/gaming_v1/services/game_server_configs_service/transports/base.py b/google/cloud/gaming_v1/services/game_server_configs_service/transports/base.py index dcf1277a..f814a1a3 100644 --- a/google/cloud/gaming_v1/services/game_server_configs_service/transports/base.py +++ b/google/cloud/gaming_v1/services/game_server_configs_service/transports/base.py @@ -19,7 +19,7 @@ import typing import pkg_resources -from google import auth +from google import auth # type: ignore from google.api_core import exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore @@ -31,13 +31,13 @@ try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() class GameServerConfigsServiceTransport(abc.ABC): @@ -53,6 +53,7 @@ def __init__( credentials_file: typing.Optional[str] = None, scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES, quota_project_id: typing.Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, **kwargs, ) -> None: """Instantiate the transport. @@ -70,6 +71,11 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -97,9 +103,9 @@ def __init__( self._credentials = credentials # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages() + self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self): + def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { self.list_game_server_configs: gapic_v1.method.wrap_method( @@ -111,7 +117,7 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.get_game_server_config: gapic_v1.method.wrap_method( self.get_game_server_config, @@ -122,17 +128,17 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.create_game_server_config: gapic_v1.method.wrap_method( self.create_game_server_config, default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.delete_game_server_config: gapic_v1.method.wrap_method( self.delete_game_server_config, default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), } diff --git a/google/cloud/gaming_v1/services/game_server_configs_service/transports/grpc.py b/google/cloud/gaming_v1/services/game_server_configs_service/transports/grpc.py index 9f93e147..36b52cc0 100644 --- a/google/cloud/gaming_v1/services/game_server_configs_service/transports/grpc.py +++ b/google/cloud/gaming_v1/services/game_server_configs_service/transports/grpc.py @@ -15,21 +15,22 @@ # limitations under the License. # +import warnings from typing import Callable, Dict, Optional, Sequence, Tuple from google.api_core import grpc_helpers # type: ignore from google.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 # type: ignore from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore - import grpc # type: ignore from google.cloud.gaming_v1.types import game_server_configs from google.longrunning import operations_pb2 as operations # type: ignore -from .base import GameServerConfigsServiceTransport +from .base import GameServerConfigsServiceTransport, DEFAULT_CLIENT_INFO class GameServerConfigsServiceGrpcTransport(GameServerConfigsServiceTransport): @@ -58,7 +59,9 @@ def __init__( channel: grpc.Channel = None, api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, - quota_project_id: Optional[str] = None + ssl_channel_credentials: grpc.ChannelCredentials = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -77,16 +80,23 @@ def __init__( ignored if ``channel`` is provided. channel (Optional[grpc.Channel]): A ``Channel`` instance through which to make calls. - api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If - provided, it overrides the ``host`` argument and tries to create + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from ``client_cert_source`` or applicatin default SSL credentials. - client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A - callback to provide client SSL certificate bytes and private key - bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` - is None. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for grpc channel. It is ignored if ``channel`` 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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -94,6 +104,8 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._ssl_channel_credentials = ssl_channel_credentials + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -101,7 +113,13 @@ def __init__( # If a channel was explicitly provided, set it. 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 @@ -132,6 +150,24 @@ def __init__( scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, ) + self._ssl_channel_credentials = ssl_credentials + else: + host = host if ":" in host else host + ":443" + + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + + # 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, + scopes=scopes or self.AUTH_SCOPES, + quota_project_id=quota_project_id, + ) self._stubs = {} # type: Dict[str, Callable] @@ -142,6 +178,7 @@ def __init__( credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) @classmethod @@ -152,7 +189,7 @@ def create_channel( credentials_file: str = None, scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, - **kwargs + **kwargs, ) -> grpc.Channel: """Create and return a gRPC channel object. Args: @@ -186,24 +223,13 @@ def create_channel( credentials_file=credentials_file, scopes=scopes, quota_project_id=quota_project_id, - **kwargs + **kwargs, ) @property def grpc_channel(self) -> grpc.Channel: - """Create the channel designed to connect to this service. - - This property caches on the instance; repeated calls return - the same channel. + """Return the channel designed to connect to this service. """ - # Sanity check: Only create a new channel if we do not already - # have one. - if not hasattr(self, "_grpc_channel"): - self._grpc_channel = self.create_channel( - self._host, credentials=self._credentials, - ) - - # Return the channel from cache. return self._grpc_channel @property diff --git a/google/cloud/gaming_v1/services/game_server_configs_service/transports/grpc_asyncio.py b/google/cloud/gaming_v1/services/game_server_configs_service/transports/grpc_asyncio.py index b0043929..aefa96d1 100644 --- a/google/cloud/gaming_v1/services/game_server_configs_service/transports/grpc_asyncio.py +++ b/google/cloud/gaming_v1/services/game_server_configs_service/transports/grpc_asyncio.py @@ -15,10 +15,13 @@ # limitations under the License. # +import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple +from google.api_core import gapic_v1 # type: ignore from google.api_core import grpc_helpers_async # type: ignore from google.api_core import operations_v1 # type: ignore +from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -28,7 +31,7 @@ from google.cloud.gaming_v1.types import game_server_configs from google.longrunning import operations_pb2 as operations # type: ignore -from .base import GameServerConfigsServiceTransport +from .base import GameServerConfigsServiceTransport, DEFAULT_CLIENT_INFO from .grpc import GameServerConfigsServiceGrpcTransport @@ -100,7 +103,9 @@ def __init__( channel: aio.Channel = None, api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, + ssl_channel_credentials: grpc.ChannelCredentials = None, quota_project_id=None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -120,16 +125,23 @@ def __init__( are passed to :func:`google.auth.default`. channel (Optional[aio.Channel]): A ``Channel`` instance through which to make calls. - api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If - provided, it overrides the ``host`` argument and tries to create + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from ``client_cert_source`` or applicatin default SSL credentials. - client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A - callback to provide client SSL certificate bytes and private key - bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` - is None. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for grpc channel. It is ignored if ``channel`` 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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -137,6 +149,8 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._ssl_channel_credentials = ssl_channel_credentials + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -144,13 +158,24 @@ def __init__( # If a channel was explicitly provided, set it. 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 else api_mtls_endpoint + ":443" ) + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + # Create SSL credentials with client_cert_source or application # default SSL credentials. if client_cert_source: @@ -170,6 +195,24 @@ def __init__( scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, ) + self._ssl_channel_credentials = ssl_credentials + else: + host = host if ":" in host else host + ":443" + + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + + # 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, + scopes=scopes or self.AUTH_SCOPES, + quota_project_id=quota_project_id, + ) # Run the base constructor. super().__init__( @@ -178,6 +221,7 @@ def __init__( credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) self._stubs = {} @@ -189,13 +233,6 @@ def grpc_channel(self) -> aio.Channel: This property caches on the instance; repeated calls return the same channel. """ - # Sanity check: Only create a new channel if we do not already - # have one. - if not hasattr(self, "_grpc_channel"): - self._grpc_channel = self.create_channel( - self._host, credentials=self._credentials, - ) - # Return the channel from cache. return self._grpc_channel diff --git a/google/cloud/gaming_v1/services/game_server_deployments_service/async_client.py b/google/cloud/gaming_v1/services/game_server_deployments_service/async_client.py index 13a2470d..fb8217c8 100644 --- a/google/cloud/gaming_v1/services/game_server_deployments_service/async_client.py +++ b/google/cloud/gaming_v1/services/game_server_deployments_service/async_client.py @@ -28,8 +28,8 @@ from google.auth import credentials # type: ignore from google.oauth2 import service_account # type: ignore -from google.api_core import operation -from google.api_core import operation_async +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore from google.cloud.gaming_v1.services.game_server_deployments_service import pagers from google.cloud.gaming_v1.types import common from google.cloud.gaming_v1.types import game_server_deployments @@ -37,7 +37,7 @@ from google.protobuf import field_mask_pb2 as field_mask # type: ignore from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from .transports.base import GameServerDeploymentsServiceTransport +from .transports.base import GameServerDeploymentsServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc_asyncio import GameServerDeploymentsServiceGrpcAsyncIOTransport from .client import GameServerDeploymentsServiceClient @@ -52,12 +52,52 @@ class GameServerDeploymentsServiceAsyncClient: DEFAULT_ENDPOINT = GameServerDeploymentsServiceClient.DEFAULT_ENDPOINT DEFAULT_MTLS_ENDPOINT = GameServerDeploymentsServiceClient.DEFAULT_MTLS_ENDPOINT + game_server_deployment_path = staticmethod( + GameServerDeploymentsServiceClient.game_server_deployment_path + ) + parse_game_server_deployment_path = staticmethod( + GameServerDeploymentsServiceClient.parse_game_server_deployment_path + ) game_server_deployment_rollout_path = staticmethod( GameServerDeploymentsServiceClient.game_server_deployment_rollout_path ) + parse_game_server_deployment_rollout_path = staticmethod( + GameServerDeploymentsServiceClient.parse_game_server_deployment_rollout_path + ) - game_server_deployment_path = staticmethod( - GameServerDeploymentsServiceClient.game_server_deployment_path + common_billing_account_path = staticmethod( + GameServerDeploymentsServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + GameServerDeploymentsServiceClient.parse_common_billing_account_path + ) + + common_folder_path = staticmethod( + GameServerDeploymentsServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + GameServerDeploymentsServiceClient.parse_common_folder_path + ) + + common_organization_path = staticmethod( + GameServerDeploymentsServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + GameServerDeploymentsServiceClient.parse_common_organization_path + ) + + common_project_path = staticmethod( + GameServerDeploymentsServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + GameServerDeploymentsServiceClient.parse_common_project_path + ) + + common_location_path = staticmethod( + GameServerDeploymentsServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + GameServerDeploymentsServiceClient.parse_common_location_path ) from_service_account_file = ( @@ -65,6 +105,15 @@ class GameServerDeploymentsServiceAsyncClient: ) from_service_account_json = from_service_account_file + @property + def transport(self) -> GameServerDeploymentsServiceTransport: + """Return the transport used by the client instance. + + Returns: + GameServerDeploymentsServiceTransport: The transport used by the client instance. + """ + return self._client.transport + get_transport_class = functools.partial( type(GameServerDeploymentsServiceClient).get_transport_class, type(GameServerDeploymentsServiceClient), @@ -76,6 +125,7 @@ def __init__( credentials: credentials.Credentials = None, transport: Union[str, GameServerDeploymentsServiceTransport] = "grpc_asyncio", client_options: ClientOptions = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the game server deployments service client. @@ -91,16 +141,19 @@ def __init__( client_options (ClientOptions): Custom options for the client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT environment variable can also be used to override the endpoint: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint, this is the default value for - the environment variable) and "auto" (auto switch to the default - mTLS endpoint if client SSL credentials is present). However, - the ``api_endpoint`` property takes precedence if provided. - (2) The ``client_cert_source`` property is used to provide client - SSL credentials for mutual TLS transport. If not provided, the - default SSL credentials will be used if present. + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -108,7 +161,10 @@ def __init__( """ self._client = GameServerDeploymentsServiceClient( - credentials=credentials, transport=transport, client_options=client_options, + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, ) async def list_game_server_deployments( @@ -152,7 +208,8 @@ async def list_game_server_deployments( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([parent]): + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -177,7 +234,7 @@ async def list_game_server_deployments( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -235,7 +292,8 @@ async def get_game_server_deployment( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -260,7 +318,7 @@ async def get_game_server_deployment( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -323,7 +381,8 @@ async def create_game_server_deployment( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([parent, game_server_deployment]): + has_flattened_params = any([parent, game_server_deployment]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -344,7 +403,7 @@ async def create_game_server_deployment( rpc = gapic_v1.method_async.wrap_method( self._client._transport.create_game_server_deployment, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -421,7 +480,8 @@ async def delete_game_server_deployment( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -440,7 +500,7 @@ async def delete_game_server_deployment( rpc = gapic_v1.method_async.wrap_method( self._client._transport.delete_game_server_deployment, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -515,7 +575,8 @@ async def update_game_server_deployment( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([game_server_deployment, update_mask]): + has_flattened_params = any([game_server_deployment, update_mask]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -536,7 +597,7 @@ async def update_game_server_deployment( rpc = gapic_v1.method_async.wrap_method( self._client._transport.update_game_server_deployment, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -601,7 +662,8 @@ async def get_game_server_deployment_rollout( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -626,7 +688,7 @@ async def get_game_server_deployment_rollout( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -699,7 +761,8 @@ async def update_game_server_deployment_rollout( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([rollout, update_mask]): + has_flattened_params = any([rollout, update_mask]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -722,7 +785,7 @@ async def update_game_server_deployment_rollout( rpc = gapic_v1.method_async.wrap_method( self._client._transport.update_game_server_deployment_rollout, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -794,7 +857,7 @@ async def preview_game_server_deployment_rollout( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -856,7 +919,7 @@ async def fetch_deployment_state( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=120.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -873,13 +936,13 @@ async def fetch_deployment_state( try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ("GameServerDeploymentsServiceAsyncClient",) diff --git a/google/cloud/gaming_v1/services/game_server_deployments_service/client.py b/google/cloud/gaming_v1/services/game_server_deployments_service/client.py index 20221142..efc3bff5 100644 --- a/google/cloud/gaming_v1/services/game_server_deployments_service/client.py +++ b/google/cloud/gaming_v1/services/game_server_deployments_service/client.py @@ -16,22 +16,24 @@ # from collections import OrderedDict +from distutils import util import os import re -from typing import Callable, Dict, Sequence, Tuple, Type, Union +from typing import Callable, Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore +from google.api_core import client_options as client_options_lib # type: ignore from google.api_core import exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore from google.auth import credentials # type: ignore from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore -from google.api_core import operation -from google.api_core import operation_async +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore from google.cloud.gaming_v1.services.game_server_deployments_service import pagers from google.cloud.gaming_v1.types import common from google.cloud.gaming_v1.types import game_server_deployments @@ -39,7 +41,7 @@ from google.protobuf import field_mask_pb2 as field_mask # type: ignore from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from .transports.base import GameServerDeploymentsServiceTransport +from .transports.base import GameServerDeploymentsServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc import GameServerDeploymentsServiceGrpcTransport from .transports.grpc_asyncio import GameServerDeploymentsServiceGrpcAsyncIOTransport @@ -142,6 +144,15 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): from_service_account_json = from_service_account_file + @property + def transport(self) -> GameServerDeploymentsServiceTransport: + """Return the transport used by the client instance. + + Returns: + GameServerDeploymentsServiceTransport: The transport used by the client instance. + """ + return self._transport + @staticmethod def game_server_deployment_path( project: str, location: str, deployment: str, @@ -178,12 +189,72 @@ def parse_game_server_deployment_rollout_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def common_billing_account_path(billing_account: str,) -> str: + """Return a fully-qualified billing_account string.""" + return "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + + @staticmethod + def parse_common_billing_account_path(path: str) -> Dict[str, str]: + """Parse a billing_account path into its component segments.""" + m = re.match(r"^billingAccounts/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_folder_path(folder: str,) -> str: + """Return a fully-qualified folder string.""" + return "folders/{folder}".format(folder=folder,) + + @staticmethod + def parse_common_folder_path(path: str) -> Dict[str, str]: + """Parse a folder path into its component segments.""" + m = re.match(r"^folders/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_organization_path(organization: str,) -> str: + """Return a fully-qualified organization string.""" + return "organizations/{organization}".format(organization=organization,) + + @staticmethod + def parse_common_organization_path(path: str) -> Dict[str, str]: + """Parse a organization path into its component segments.""" + m = re.match(r"^organizations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_project_path(project: str,) -> str: + """Return a fully-qualified project string.""" + return "projects/{project}".format(project=project,) + + @staticmethod + def parse_common_project_path(path: str) -> Dict[str, str]: + """Parse a project path into its component segments.""" + m = re.match(r"^projects/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_location_path(project: str, location: str,) -> str: + """Return a fully-qualified location string.""" + return "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + + @staticmethod + def parse_common_location_path(path: str) -> Dict[str, str]: + """Parse a location path into its component segments.""" + m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path) + return m.groupdict() if m else {} + def __init__( self, *, - credentials: credentials.Credentials = None, - transport: Union[str, GameServerDeploymentsServiceTransport] = None, - client_options: ClientOptions = None, + credentials: Optional[credentials.Credentials] = None, + transport: Union[str, GameServerDeploymentsServiceTransport, None] = None, + client_options: Optional[client_options_lib.ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the game server deployments service client. @@ -196,48 +267,74 @@ def __init__( transport (Union[str, ~.GameServerDeploymentsServiceTransport]): The transport to use. If set to None, a transport is chosen automatically. - client_options (ClientOptions): Custom options for the client. It - won't take effect if a ``transport`` instance is provided. + client_options (client_options_lib.ClientOptions): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT environment variable can also be used to override the endpoint: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint, this is the default value for - the environment variable) and "auto" (auto switch to the default - mTLS endpoint if client SSL credentials is present). However, - the ``api_endpoint`` property takes precedence if provided. - (2) The ``client_cert_source`` property is used to provide client - SSL credentials for mutual TLS transport. If not provided, the - default SSL credentials will be used if present. + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport creation failed for any reason. """ if isinstance(client_options, dict): - client_options = ClientOptions.from_dict(client_options) + client_options = client_options_lib.from_dict(client_options) if client_options is None: - client_options = ClientOptions.ClientOptions() + client_options = client_options_lib.ClientOptions() + + # Create SSL credentials for mutual TLS if needed. + use_client_cert = bool( + util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + ) - if client_options.api_endpoint is None: - use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS", "never") + ssl_credentials = 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 + else: + creds = SslCredentials() + is_mtls = creds.is_mtls + ssl_credentials = creds.ssl_credentials if is_mtls else None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") if use_mtls_env == "never": - client_options.api_endpoint = self.DEFAULT_ENDPOINT + api_endpoint = self.DEFAULT_ENDPOINT elif use_mtls_env == "always": - client_options.api_endpoint = self.DEFAULT_MTLS_ENDPOINT + api_endpoint = self.DEFAULT_MTLS_ENDPOINT elif use_mtls_env == "auto": - has_client_cert_source = ( - client_options.client_cert_source is not None - or mtls.has_default_client_cert_source() - ) - client_options.api_endpoint = ( - self.DEFAULT_MTLS_ENDPOINT - if has_client_cert_source - else self.DEFAULT_ENDPOINT + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT if is_mtls else self.DEFAULT_ENDPOINT ) else: raise MutualTLSChannelError( - "Unsupported GOOGLE_API_USE_MTLS value. Accepted values: never, auto, always" + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always" ) # Save or instantiate the transport. @@ -261,11 +358,11 @@ def __init__( self._transport = Transport( credentials=credentials, credentials_file=client_options.credentials_file, - host=client_options.api_endpoint, + host=api_endpoint, scopes=client_options.scopes, - api_mtls_endpoint=client_options.api_endpoint, - client_cert_source=client_options.client_cert_source, + ssl_channel_credentials=ssl_credentials, quota_project_id=client_options.quota_project_id, + client_info=client_info, ) def list_game_server_deployments( @@ -1050,13 +1147,13 @@ def fetch_deployment_state( try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ("GameServerDeploymentsServiceClient",) diff --git a/google/cloud/gaming_v1/services/game_server_deployments_service/transports/base.py b/google/cloud/gaming_v1/services/game_server_deployments_service/transports/base.py index adfdac58..6596afea 100644 --- a/google/cloud/gaming_v1/services/game_server_deployments_service/transports/base.py +++ b/google/cloud/gaming_v1/services/game_server_deployments_service/transports/base.py @@ -19,7 +19,7 @@ import typing import pkg_resources -from google import auth +from google import auth # type: ignore from google.api_core import exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore @@ -31,13 +31,13 @@ try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() class GameServerDeploymentsServiceTransport(abc.ABC): @@ -53,6 +53,7 @@ def __init__( credentials_file: typing.Optional[str] = None, scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES, quota_project_id: typing.Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, **kwargs, ) -> None: """Instantiate the transport. @@ -70,6 +71,11 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -97,9 +103,9 @@ def __init__( self._credentials = credentials # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages() + self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self): + def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { self.list_game_server_deployments: gapic_v1.method.wrap_method( @@ -111,7 +117,7 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.get_game_server_deployment: gapic_v1.method.wrap_method( self.get_game_server_deployment, @@ -122,22 +128,22 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.create_game_server_deployment: gapic_v1.method.wrap_method( self.create_game_server_deployment, default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.delete_game_server_deployment: gapic_v1.method.wrap_method( self.delete_game_server_deployment, default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.update_game_server_deployment: gapic_v1.method.wrap_method( self.update_game_server_deployment, default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.get_game_server_deployment_rollout: gapic_v1.method.wrap_method( self.get_game_server_deployment_rollout, @@ -148,12 +154,12 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.update_game_server_deployment_rollout: gapic_v1.method.wrap_method( self.update_game_server_deployment_rollout, default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.preview_game_server_deployment_rollout: gapic_v1.method.wrap_method( self.preview_game_server_deployment_rollout, @@ -164,7 +170,7 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.fetch_deployment_state: gapic_v1.method.wrap_method( self.fetch_deployment_state, @@ -175,7 +181,7 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=120.0, - client_info=_client_info, + client_info=client_info, ), } diff --git a/google/cloud/gaming_v1/services/game_server_deployments_service/transports/grpc.py b/google/cloud/gaming_v1/services/game_server_deployments_service/transports/grpc.py index 80f479de..6be91b48 100644 --- a/google/cloud/gaming_v1/services/game_server_deployments_service/transports/grpc.py +++ b/google/cloud/gaming_v1/services/game_server_deployments_service/transports/grpc.py @@ -15,21 +15,22 @@ # limitations under the License. # +import warnings from typing import Callable, Dict, Optional, Sequence, Tuple from google.api_core import grpc_helpers # type: ignore from google.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 # type: ignore from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore - import grpc # type: ignore from google.cloud.gaming_v1.types import game_server_deployments from google.longrunning import operations_pb2 as operations # type: ignore -from .base import GameServerDeploymentsServiceTransport +from .base import GameServerDeploymentsServiceTransport, DEFAULT_CLIENT_INFO class GameServerDeploymentsServiceGrpcTransport(GameServerDeploymentsServiceTransport): @@ -58,7 +59,9 @@ def __init__( channel: grpc.Channel = None, api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, - quota_project_id: Optional[str] = None + ssl_channel_credentials: grpc.ChannelCredentials = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -77,16 +80,23 @@ def __init__( ignored if ``channel`` is provided. channel (Optional[grpc.Channel]): A ``Channel`` instance through which to make calls. - api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If - provided, it overrides the ``host`` argument and tries to create + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from ``client_cert_source`` or applicatin default SSL credentials. - client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A - callback to provide client SSL certificate bytes and private key - bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` - is None. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for grpc channel. It is ignored if ``channel`` 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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -94,6 +104,8 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._ssl_channel_credentials = ssl_channel_credentials + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -101,7 +113,13 @@ def __init__( # If a channel was explicitly provided, set it. 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 @@ -132,6 +150,24 @@ def __init__( scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, ) + self._ssl_channel_credentials = ssl_credentials + else: + host = host if ":" in host else host + ":443" + + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + + # 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, + scopes=scopes or self.AUTH_SCOPES, + quota_project_id=quota_project_id, + ) self._stubs = {} # type: Dict[str, Callable] @@ -142,6 +178,7 @@ def __init__( credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) @classmethod @@ -152,7 +189,7 @@ def create_channel( credentials_file: str = None, scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, - **kwargs + **kwargs, ) -> grpc.Channel: """Create and return a gRPC channel object. Args: @@ -186,24 +223,13 @@ def create_channel( credentials_file=credentials_file, scopes=scopes, quota_project_id=quota_project_id, - **kwargs + **kwargs, ) @property def grpc_channel(self) -> grpc.Channel: - """Create the channel designed to connect to this service. - - This property caches on the instance; repeated calls return - the same channel. + """Return the channel designed to connect to this service. """ - # Sanity check: Only create a new channel if we do not already - # have one. - if not hasattr(self, "_grpc_channel"): - self._grpc_channel = self.create_channel( - self._host, credentials=self._credentials, - ) - - # Return the channel from cache. return self._grpc_channel @property diff --git a/google/cloud/gaming_v1/services/game_server_deployments_service/transports/grpc_asyncio.py b/google/cloud/gaming_v1/services/game_server_deployments_service/transports/grpc_asyncio.py index 108e6391..e8eadd37 100644 --- a/google/cloud/gaming_v1/services/game_server_deployments_service/transports/grpc_asyncio.py +++ b/google/cloud/gaming_v1/services/game_server_deployments_service/transports/grpc_asyncio.py @@ -15,10 +15,13 @@ # limitations under the License. # +import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple +from google.api_core import gapic_v1 # type: ignore from google.api_core import grpc_helpers_async # type: ignore from google.api_core import operations_v1 # type: ignore +from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -28,7 +31,7 @@ from google.cloud.gaming_v1.types import game_server_deployments from google.longrunning import operations_pb2 as operations # type: ignore -from .base import GameServerDeploymentsServiceTransport +from .base import GameServerDeploymentsServiceTransport, DEFAULT_CLIENT_INFO from .grpc import GameServerDeploymentsServiceGrpcTransport @@ -102,7 +105,9 @@ def __init__( channel: aio.Channel = None, api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, + ssl_channel_credentials: grpc.ChannelCredentials = None, quota_project_id=None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -122,16 +127,23 @@ def __init__( are passed to :func:`google.auth.default`. channel (Optional[aio.Channel]): A ``Channel`` instance through which to make calls. - api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If - provided, it overrides the ``host`` argument and tries to create + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from ``client_cert_source`` or applicatin default SSL credentials. - client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A - callback to provide client SSL certificate bytes and private key - bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` - is None. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for grpc channel. It is ignored if ``channel`` 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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -139,6 +151,8 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._ssl_channel_credentials = ssl_channel_credentials + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -146,13 +160,24 @@ def __init__( # If a channel was explicitly provided, set it. 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 else api_mtls_endpoint + ":443" ) + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + # Create SSL credentials with client_cert_source or application # default SSL credentials. if client_cert_source: @@ -172,6 +197,24 @@ def __init__( scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, ) + self._ssl_channel_credentials = ssl_credentials + else: + host = host if ":" in host else host + ":443" + + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + + # 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, + scopes=scopes or self.AUTH_SCOPES, + quota_project_id=quota_project_id, + ) # Run the base constructor. super().__init__( @@ -180,6 +223,7 @@ def __init__( credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) self._stubs = {} @@ -191,13 +235,6 @@ def grpc_channel(self) -> aio.Channel: This property caches on the instance; repeated calls return the same channel. """ - # Sanity check: Only create a new channel if we do not already - # have one. - if not hasattr(self, "_grpc_channel"): - self._grpc_channel = self.create_channel( - self._host, credentials=self._credentials, - ) - # Return the channel from cache. return self._grpc_channel diff --git a/google/cloud/gaming_v1/services/realms_service/async_client.py b/google/cloud/gaming_v1/services/realms_service/async_client.py index 84a8ebdf..63abe9f5 100644 --- a/google/cloud/gaming_v1/services/realms_service/async_client.py +++ b/google/cloud/gaming_v1/services/realms_service/async_client.py @@ -28,8 +28,8 @@ from google.auth import credentials # type: ignore from google.oauth2 import service_account # type: ignore -from google.api_core import operation -from google.api_core import operation_async +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore from google.cloud.gaming_v1.services.realms_service import pagers from google.cloud.gaming_v1.types import common from google.cloud.gaming_v1.types import realms @@ -37,7 +37,7 @@ from google.protobuf import field_mask_pb2 as field_mask # type: ignore from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from .transports.base import RealmsServiceTransport +from .transports.base import RealmsServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc_asyncio import RealmsServiceGrpcAsyncIOTransport from .client import RealmsServiceClient @@ -53,10 +53,49 @@ class RealmsServiceAsyncClient: DEFAULT_MTLS_ENDPOINT = RealmsServiceClient.DEFAULT_MTLS_ENDPOINT realm_path = staticmethod(RealmsServiceClient.realm_path) + parse_realm_path = staticmethod(RealmsServiceClient.parse_realm_path) + + common_billing_account_path = staticmethod( + RealmsServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + RealmsServiceClient.parse_common_billing_account_path + ) + + common_folder_path = staticmethod(RealmsServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + RealmsServiceClient.parse_common_folder_path + ) + + common_organization_path = staticmethod( + RealmsServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + RealmsServiceClient.parse_common_organization_path + ) + + common_project_path = staticmethod(RealmsServiceClient.common_project_path) + parse_common_project_path = staticmethod( + RealmsServiceClient.parse_common_project_path + ) + + common_location_path = staticmethod(RealmsServiceClient.common_location_path) + parse_common_location_path = staticmethod( + RealmsServiceClient.parse_common_location_path + ) from_service_account_file = RealmsServiceClient.from_service_account_file from_service_account_json = from_service_account_file + @property + def transport(self) -> RealmsServiceTransport: + """Return the transport used by the client instance. + + Returns: + RealmsServiceTransport: The transport used by the client instance. + """ + return self._client.transport + get_transport_class = functools.partial( type(RealmsServiceClient).get_transport_class, type(RealmsServiceClient) ) @@ -67,6 +106,7 @@ def __init__( credentials: credentials.Credentials = None, transport: Union[str, RealmsServiceTransport] = "grpc_asyncio", client_options: ClientOptions = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the realms service client. @@ -82,16 +122,19 @@ def __init__( client_options (ClientOptions): Custom options for the client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT environment variable can also be used to override the endpoint: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint, this is the default value for - the environment variable) and "auto" (auto switch to the default - mTLS endpoint if client SSL credentials is present). However, - the ``api_endpoint`` property takes precedence if provided. - (2) The ``client_cert_source`` property is used to provide client - SSL credentials for mutual TLS transport. If not provided, the - default SSL credentials will be used if present. + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -99,7 +142,10 @@ def __init__( """ self._client = RealmsServiceClient( - credentials=credentials, transport=transport, client_options=client_options, + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, ) async def list_realms( @@ -142,7 +188,8 @@ async def list_realms( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([parent]): + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -167,7 +214,7 @@ async def list_realms( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -224,7 +271,8 @@ async def get_realm( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -249,7 +297,7 @@ async def get_realm( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -317,7 +365,8 @@ async def create_realm( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([parent, realm, realm_id]): + has_flattened_params = any([parent, realm, realm_id]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -340,7 +389,7 @@ async def create_realm( rpc = gapic_v1.method_async.wrap_method( self._client._transport.create_realm, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -416,7 +465,8 @@ async def delete_realm( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -435,7 +485,7 @@ async def delete_realm( rpc = gapic_v1.method_async.wrap_method( self._client._transport.delete_realm, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -507,7 +557,8 @@ async def update_realm( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([realm, update_mask]): + has_flattened_params = any([realm, update_mask]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -528,7 +579,7 @@ async def update_realm( rpc = gapic_v1.method_async.wrap_method( self._client._transport.update_realm, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -595,7 +646,7 @@ async def preview_realm_update( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -614,13 +665,13 @@ async def preview_realm_update( try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ("RealmsServiceAsyncClient",) diff --git a/google/cloud/gaming_v1/services/realms_service/client.py b/google/cloud/gaming_v1/services/realms_service/client.py index c83108ca..dc55bf61 100644 --- a/google/cloud/gaming_v1/services/realms_service/client.py +++ b/google/cloud/gaming_v1/services/realms_service/client.py @@ -16,22 +16,24 @@ # from collections import OrderedDict +from distutils import util import os import re -from typing import Callable, Dict, Sequence, Tuple, Type, Union +from typing import Callable, Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore +from google.api_core import client_options as client_options_lib # type: ignore from google.api_core import exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore from google.auth import credentials # type: ignore from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore -from google.api_core import operation -from google.api_core import operation_async +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore from google.cloud.gaming_v1.services.realms_service import pagers from google.cloud.gaming_v1.types import common from google.cloud.gaming_v1.types import realms @@ -39,7 +41,7 @@ from google.protobuf import field_mask_pb2 as field_mask # type: ignore from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from .transports.base import RealmsServiceTransport +from .transports.base import RealmsServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc import RealmsServiceGrpcTransport from .transports.grpc_asyncio import RealmsServiceGrpcAsyncIOTransport @@ -134,6 +136,15 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): from_service_account_json = from_service_account_file + @property + def transport(self) -> RealmsServiceTransport: + """Return the transport used by the client instance. + + Returns: + RealmsServiceTransport: The transport used by the client instance. + """ + return self._transport + @staticmethod def realm_path(project: str, location: str, realm: str,) -> str: """Return a fully-qualified realm string.""" @@ -150,12 +161,72 @@ def parse_realm_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def common_billing_account_path(billing_account: str,) -> str: + """Return a fully-qualified billing_account string.""" + return "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + + @staticmethod + def parse_common_billing_account_path(path: str) -> Dict[str, str]: + """Parse a billing_account path into its component segments.""" + m = re.match(r"^billingAccounts/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_folder_path(folder: str,) -> str: + """Return a fully-qualified folder string.""" + return "folders/{folder}".format(folder=folder,) + + @staticmethod + def parse_common_folder_path(path: str) -> Dict[str, str]: + """Parse a folder path into its component segments.""" + m = re.match(r"^folders/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_organization_path(organization: str,) -> str: + """Return a fully-qualified organization string.""" + return "organizations/{organization}".format(organization=organization,) + + @staticmethod + def parse_common_organization_path(path: str) -> Dict[str, str]: + """Parse a organization path into its component segments.""" + m = re.match(r"^organizations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_project_path(project: str,) -> str: + """Return a fully-qualified project string.""" + return "projects/{project}".format(project=project,) + + @staticmethod + def parse_common_project_path(path: str) -> Dict[str, str]: + """Parse a project path into its component segments.""" + m = re.match(r"^projects/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_location_path(project: str, location: str,) -> str: + """Return a fully-qualified location string.""" + return "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + + @staticmethod + def parse_common_location_path(path: str) -> Dict[str, str]: + """Parse a location path into its component segments.""" + m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path) + return m.groupdict() if m else {} + def __init__( self, *, - credentials: credentials.Credentials = None, - transport: Union[str, RealmsServiceTransport] = None, - client_options: ClientOptions = None, + credentials: Optional[credentials.Credentials] = None, + transport: Union[str, RealmsServiceTransport, None] = None, + client_options: Optional[client_options_lib.ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the realms service client. @@ -168,48 +239,74 @@ def __init__( transport (Union[str, ~.RealmsServiceTransport]): The transport to use. If set to None, a transport is chosen automatically. - client_options (ClientOptions): Custom options for the client. It - won't take effect if a ``transport`` instance is provided. + client_options (client_options_lib.ClientOptions): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT environment variable can also be used to override the endpoint: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint, this is the default value for - the environment variable) and "auto" (auto switch to the default - mTLS endpoint if client SSL credentials is present). However, - the ``api_endpoint`` property takes precedence if provided. - (2) The ``client_cert_source`` property is used to provide client - SSL credentials for mutual TLS transport. If not provided, the - default SSL credentials will be used if present. + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport creation failed for any reason. """ if isinstance(client_options, dict): - client_options = ClientOptions.from_dict(client_options) + client_options = client_options_lib.from_dict(client_options) if client_options is None: - client_options = ClientOptions.ClientOptions() + client_options = client_options_lib.ClientOptions() + + # Create SSL credentials for mutual TLS if needed. + use_client_cert = bool( + util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + ) - if client_options.api_endpoint is None: - use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS", "never") + ssl_credentials = 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 + else: + creds = SslCredentials() + is_mtls = creds.is_mtls + ssl_credentials = creds.ssl_credentials if is_mtls else None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") if use_mtls_env == "never": - client_options.api_endpoint = self.DEFAULT_ENDPOINT + api_endpoint = self.DEFAULT_ENDPOINT elif use_mtls_env == "always": - client_options.api_endpoint = self.DEFAULT_MTLS_ENDPOINT + api_endpoint = self.DEFAULT_MTLS_ENDPOINT elif use_mtls_env == "auto": - has_client_cert_source = ( - client_options.client_cert_source is not None - or mtls.has_default_client_cert_source() - ) - client_options.api_endpoint = ( - self.DEFAULT_MTLS_ENDPOINT - if has_client_cert_source - else self.DEFAULT_ENDPOINT + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT if is_mtls else self.DEFAULT_ENDPOINT ) else: raise MutualTLSChannelError( - "Unsupported GOOGLE_API_USE_MTLS value. Accepted values: never, auto, always" + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always" ) # Save or instantiate the transport. @@ -233,11 +330,11 @@ def __init__( self._transport = Transport( credentials=credentials, credentials_file=client_options.credentials_file, - host=client_options.api_endpoint, + host=api_endpoint, scopes=client_options.scopes, - api_mtls_endpoint=client_options.api_endpoint, - client_cert_source=client_options.client_cert_source, + ssl_channel_credentials=ssl_credentials, quota_project_id=client_options.quota_project_id, + client_info=client_info, ) def list_realms( @@ -745,13 +842,13 @@ def preview_realm_update( try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ("RealmsServiceClient",) diff --git a/google/cloud/gaming_v1/services/realms_service/transports/base.py b/google/cloud/gaming_v1/services/realms_service/transports/base.py index 22f3a166..7bea019d 100644 --- a/google/cloud/gaming_v1/services/realms_service/transports/base.py +++ b/google/cloud/gaming_v1/services/realms_service/transports/base.py @@ -19,7 +19,7 @@ import typing import pkg_resources -from google import auth +from google import auth # type: ignore from google.api_core import exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore @@ -31,13 +31,13 @@ try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() class RealmsServiceTransport(abc.ABC): @@ -53,6 +53,7 @@ def __init__( credentials_file: typing.Optional[str] = None, scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES, quota_project_id: typing.Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, **kwargs, ) -> None: """Instantiate the transport. @@ -70,6 +71,11 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -97,9 +103,9 @@ def __init__( self._credentials = credentials # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages() + self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self): + def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { self.list_realms: gapic_v1.method.wrap_method( @@ -111,7 +117,7 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.get_realm: gapic_v1.method.wrap_method( self.get_realm, @@ -122,16 +128,16 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.create_realm: gapic_v1.method.wrap_method( - self.create_realm, default_timeout=60.0, client_info=_client_info, + self.create_realm, default_timeout=60.0, client_info=client_info, ), self.delete_realm: gapic_v1.method.wrap_method( - self.delete_realm, default_timeout=60.0, client_info=_client_info, + self.delete_realm, default_timeout=60.0, client_info=client_info, ), self.update_realm: gapic_v1.method.wrap_method( - self.update_realm, default_timeout=60.0, client_info=_client_info, + self.update_realm, default_timeout=60.0, client_info=client_info, ), self.preview_realm_update: gapic_v1.method.wrap_method( self.preview_realm_update, @@ -142,7 +148,7 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), } diff --git a/google/cloud/gaming_v1/services/realms_service/transports/grpc.py b/google/cloud/gaming_v1/services/realms_service/transports/grpc.py index 7f6bfee0..65f00a0c 100644 --- a/google/cloud/gaming_v1/services/realms_service/transports/grpc.py +++ b/google/cloud/gaming_v1/services/realms_service/transports/grpc.py @@ -15,21 +15,22 @@ # limitations under the License. # +import warnings from typing import Callable, Dict, Optional, Sequence, Tuple from google.api_core import grpc_helpers # type: ignore from google.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 # type: ignore from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore - import grpc # type: ignore from google.cloud.gaming_v1.types import realms from google.longrunning import operations_pb2 as operations # type: ignore -from .base import RealmsServiceTransport +from .base import RealmsServiceTransport, DEFAULT_CLIENT_INFO class RealmsServiceGrpcTransport(RealmsServiceTransport): @@ -58,7 +59,9 @@ def __init__( channel: grpc.Channel = None, api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, - quota_project_id: Optional[str] = None + ssl_channel_credentials: grpc.ChannelCredentials = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -77,16 +80,23 @@ def __init__( ignored if ``channel`` is provided. channel (Optional[grpc.Channel]): A ``Channel`` instance through which to make calls. - api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If - provided, it overrides the ``host`` argument and tries to create + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from ``client_cert_source`` or applicatin default SSL credentials. - client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A - callback to provide client SSL certificate bytes and private key - bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` - is None. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for grpc channel. It is ignored if ``channel`` 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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -94,6 +104,8 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._ssl_channel_credentials = ssl_channel_credentials + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -101,7 +113,13 @@ def __init__( # If a channel was explicitly provided, set it. 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 @@ -132,6 +150,24 @@ def __init__( scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, ) + self._ssl_channel_credentials = ssl_credentials + else: + host = host if ":" in host else host + ":443" + + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + + # 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, + scopes=scopes or self.AUTH_SCOPES, + quota_project_id=quota_project_id, + ) self._stubs = {} # type: Dict[str, Callable] @@ -142,6 +178,7 @@ def __init__( credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) @classmethod @@ -152,7 +189,7 @@ def create_channel( credentials_file: str = None, scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, - **kwargs + **kwargs, ) -> grpc.Channel: """Create and return a gRPC channel object. Args: @@ -186,24 +223,13 @@ def create_channel( credentials_file=credentials_file, scopes=scopes, quota_project_id=quota_project_id, - **kwargs + **kwargs, ) @property def grpc_channel(self) -> grpc.Channel: - """Create the channel designed to connect to this service. - - This property caches on the instance; repeated calls return - the same channel. + """Return the channel designed to connect to this service. """ - # Sanity check: Only create a new channel if we do not already - # have one. - if not hasattr(self, "_grpc_channel"): - self._grpc_channel = self.create_channel( - self._host, credentials=self._credentials, - ) - - # Return the channel from cache. return self._grpc_channel @property diff --git a/google/cloud/gaming_v1/services/realms_service/transports/grpc_asyncio.py b/google/cloud/gaming_v1/services/realms_service/transports/grpc_asyncio.py index 6ab59c59..ede57a5c 100644 --- a/google/cloud/gaming_v1/services/realms_service/transports/grpc_asyncio.py +++ b/google/cloud/gaming_v1/services/realms_service/transports/grpc_asyncio.py @@ -15,10 +15,13 @@ # limitations under the License. # +import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple +from google.api_core import gapic_v1 # type: ignore from google.api_core import grpc_helpers_async # type: ignore from google.api_core import operations_v1 # type: ignore +from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -28,7 +31,7 @@ from google.cloud.gaming_v1.types import realms from google.longrunning import operations_pb2 as operations # type: ignore -from .base import RealmsServiceTransport +from .base import RealmsServiceTransport, DEFAULT_CLIENT_INFO from .grpc import RealmsServiceGrpcTransport @@ -100,7 +103,9 @@ def __init__( channel: aio.Channel = None, api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, + ssl_channel_credentials: grpc.ChannelCredentials = None, quota_project_id=None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -120,16 +125,23 @@ def __init__( are passed to :func:`google.auth.default`. channel (Optional[aio.Channel]): A ``Channel`` instance through which to make calls. - api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If - provided, it overrides the ``host`` argument and tries to create + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from ``client_cert_source`` or applicatin default SSL credentials. - client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A - callback to provide client SSL certificate bytes and private key - bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` - is None. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for grpc channel. It is ignored if ``channel`` 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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -137,6 +149,8 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._ssl_channel_credentials = ssl_channel_credentials + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -144,13 +158,24 @@ def __init__( # If a channel was explicitly provided, set it. 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 else api_mtls_endpoint + ":443" ) + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + # Create SSL credentials with client_cert_source or application # default SSL credentials. if client_cert_source: @@ -170,6 +195,24 @@ def __init__( scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, ) + self._ssl_channel_credentials = ssl_credentials + else: + host = host if ":" in host else host + ":443" + + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + + # 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, + scopes=scopes or self.AUTH_SCOPES, + quota_project_id=quota_project_id, + ) # Run the base constructor. super().__init__( @@ -178,6 +221,7 @@ def __init__( credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) self._stubs = {} @@ -189,13 +233,6 @@ def grpc_channel(self) -> aio.Channel: This property caches on the instance; repeated calls return the same channel. """ - # Sanity check: Only create a new channel if we do not already - # have one. - if not hasattr(self, "_grpc_channel"): - self._grpc_channel = self.create_channel( - self._host, credentials=self._credentials, - ) - # Return the channel from cache. return self._grpc_channel diff --git a/google/cloud/gaming_v1/types/common.py b/google/cloud/gaming_v1/types/common.py index 29634e71..43422427 100644 --- a/google/cloud/gaming_v1/types/common.py +++ b/google/cloud/gaming_v1/types/common.py @@ -248,7 +248,7 @@ class TargetFleet(proto.Message): name = proto.Field(proto.STRING, number=1) - spec_source = proto.Field(proto.MESSAGE, number=2, message=SpecSource,) + spec_source = proto.Field(proto.MESSAGE, number=2, message="SpecSource",) class TargetFleetAutoscaler(proto.Message): r"""Target Agones autoscaler policy reference. @@ -263,7 +263,7 @@ class TargetFleetAutoscaler(proto.Message): name = proto.Field(proto.STRING, number=1) - spec_source = proto.Field(proto.MESSAGE, number=2, message=SpecSource,) + spec_source = proto.Field(proto.MESSAGE, number=2, message="SpecSource",) fleet = proto.Field( proto.MESSAGE, @@ -294,7 +294,7 @@ class TargetState(proto.Message): Details about Agones fleets. """ - details = proto.RepeatedField(proto.MESSAGE, number=1, message=TargetDetails,) + details = proto.RepeatedField(proto.MESSAGE, number=1, message="TargetDetails",) class DeployedFleetDetails(proto.Message): @@ -360,7 +360,7 @@ class DeployedFleetStatus(proto.Message): fleet_spec = proto.Field(proto.STRING, number=2) - spec_source = proto.Field(proto.MESSAGE, number=3, message=SpecSource,) + spec_source = proto.Field(proto.MESSAGE, number=3, message="SpecSource",) status = proto.Field( proto.MESSAGE, @@ -384,7 +384,7 @@ class DeployedFleetAutoscaler(proto.Message): autoscaler = proto.Field(proto.STRING, number=1) - spec_source = proto.Field(proto.MESSAGE, number=4, message=SpecSource,) + spec_source = proto.Field(proto.MESSAGE, number=4, message="SpecSource",) fleet_autoscaler_spec = proto.Field(proto.STRING, number=3) diff --git a/google/cloud/gaming_v1/types/game_server_clusters.py b/google/cloud/gaming_v1/types/game_server_clusters.py index e4413e14..27e4b963 100644 --- a/google/cloud/gaming_v1/types/game_server_clusters.py +++ b/google/cloud/gaming_v1/types/game_server_clusters.py @@ -398,7 +398,7 @@ class GameServerCluster(proto.Message): labels = proto.MapField(proto.STRING, proto.STRING, number=4) connection_info = proto.Field( - proto.MESSAGE, number=5, message=GameServerClusterConnectionInfo, + proto.MESSAGE, number=5, message="GameServerClusterConnectionInfo", ) etag = proto.Field(proto.STRING, number=6) diff --git a/google/cloud/gaming_v1/types/game_server_configs.py b/google/cloud/gaming_v1/types/game_server_configs.py index 36eb4d4a..226bff5b 100644 --- a/google/cloud/gaming_v1/types/game_server_configs.py +++ b/google/cloud/gaming_v1/types/game_server_configs.py @@ -244,10 +244,10 @@ class GameServerConfig(proto.Message): labels = proto.MapField(proto.STRING, proto.STRING, number=4) - fleet_configs = proto.RepeatedField(proto.MESSAGE, number=5, message=FleetConfig,) + fleet_configs = proto.RepeatedField(proto.MESSAGE, number=5, message="FleetConfig",) scaling_configs = proto.RepeatedField( - proto.MESSAGE, number=6, message=ScalingConfig, + proto.MESSAGE, number=6, message="ScalingConfig", ) description = proto.Field(proto.STRING, number=7) diff --git a/google/cloud/gaming_v1/types/game_server_deployments.py b/google/cloud/gaming_v1/types/game_server_deployments.py index ea03de7e..31174596 100644 --- a/google/cloud/gaming_v1/types/game_server_deployments.py +++ b/google/cloud/gaming_v1/types/game_server_deployments.py @@ -378,7 +378,7 @@ class GameServerDeploymentRollout(proto.Message): default_game_server_config = proto.Field(proto.STRING, number=4) game_server_config_overrides = proto.RepeatedField( - proto.MESSAGE, number=5, message=GameServerConfigOverride, + proto.MESSAGE, number=5, message="GameServerConfigOverride", ) etag = proto.Field(proto.STRING, number=6) @@ -404,7 +404,9 @@ class PreviewGameServerDeploymentRolloutRequest(proto.Message): proposed rollout completes. """ - rollout = proto.Field(proto.MESSAGE, number=1, message=GameServerDeploymentRollout,) + rollout = proto.Field( + proto.MESSAGE, number=1, message="GameServerDeploymentRollout", + ) update_mask = proto.Field(proto.MESSAGE, number=2, message=field_mask.FieldMask,) diff --git a/google/cloud/gaming_v1beta/__init__.py b/google/cloud/gaming_v1beta/__init__.py index ad0f876b..cddeaeec 100644 --- a/google/cloud/gaming_v1beta/__init__.py +++ b/google/cloud/gaming_v1beta/__init__.py @@ -95,6 +95,7 @@ "GameServerClustersServiceClient", "GameServerConfig", "GameServerConfigOverride", + "GameServerConfigsServiceClient", "GameServerDeployment", "GameServerDeploymentRollout", "GameServerDeploymentsServiceClient", @@ -127,7 +128,6 @@ "PreviewUpdateGameServerClusterResponse", "Realm", "RealmSelector", - "RealmsServiceClient", "ScalingConfig", "Schedule", "SpecSource", @@ -137,5 +137,5 @@ "UpdateGameServerDeploymentRequest", "UpdateGameServerDeploymentRolloutRequest", "UpdateRealmRequest", - "GameServerConfigsServiceClient", + "RealmsServiceClient", ) diff --git a/google/cloud/gaming_v1beta/services/game_server_clusters_service/async_client.py b/google/cloud/gaming_v1beta/services/game_server_clusters_service/async_client.py index 71dc21d9..9a48f628 100644 --- a/google/cloud/gaming_v1beta/services/game_server_clusters_service/async_client.py +++ b/google/cloud/gaming_v1beta/services/game_server_clusters_service/async_client.py @@ -28,8 +28,8 @@ from google.auth import credentials # type: ignore from google.oauth2 import service_account # type: ignore -from google.api_core import operation -from google.api_core import operation_async +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore from google.cloud.gaming_v1beta.services.game_server_clusters_service import pagers from google.cloud.gaming_v1beta.types import common from google.cloud.gaming_v1beta.types import game_server_clusters @@ -37,7 +37,7 @@ from google.protobuf import field_mask_pb2 as field_mask # type: ignore from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from .transports.base import GameServerClustersServiceTransport +from .transports.base import GameServerClustersServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc_asyncio import GameServerClustersServiceGrpcAsyncIOTransport from .client import GameServerClustersServiceClient @@ -55,12 +55,59 @@ class GameServerClustersServiceAsyncClient: game_server_cluster_path = staticmethod( GameServerClustersServiceClient.game_server_cluster_path ) + parse_game_server_cluster_path = staticmethod( + GameServerClustersServiceClient.parse_game_server_cluster_path + ) + + common_billing_account_path = staticmethod( + GameServerClustersServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + GameServerClustersServiceClient.parse_common_billing_account_path + ) + + common_folder_path = staticmethod( + GameServerClustersServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + GameServerClustersServiceClient.parse_common_folder_path + ) + + common_organization_path = staticmethod( + GameServerClustersServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + GameServerClustersServiceClient.parse_common_organization_path + ) + + common_project_path = staticmethod( + GameServerClustersServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + GameServerClustersServiceClient.parse_common_project_path + ) + + common_location_path = staticmethod( + GameServerClustersServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + GameServerClustersServiceClient.parse_common_location_path + ) from_service_account_file = ( GameServerClustersServiceClient.from_service_account_file ) from_service_account_json = from_service_account_file + @property + def transport(self) -> GameServerClustersServiceTransport: + """Return the transport used by the client instance. + + Returns: + GameServerClustersServiceTransport: The transport used by the client instance. + """ + return self._client.transport + get_transport_class = functools.partial( type(GameServerClustersServiceClient).get_transport_class, type(GameServerClustersServiceClient), @@ -72,6 +119,7 @@ def __init__( credentials: credentials.Credentials = None, transport: Union[str, GameServerClustersServiceTransport] = "grpc_asyncio", client_options: ClientOptions = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the game server clusters service client. @@ -87,16 +135,19 @@ def __init__( client_options (ClientOptions): Custom options for the client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT environment variable can also be used to override the endpoint: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint, this is the default value for - the environment variable) and "auto" (auto switch to the default - mTLS endpoint if client SSL credentials is present). However, - the ``api_endpoint`` property takes precedence if provided. - (2) The ``client_cert_source`` property is used to provide client - SSL credentials for mutual TLS transport. If not provided, the - default SSL credentials will be used if present. + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -104,7 +155,10 @@ def __init__( """ self._client = GameServerClustersServiceClient( - credentials=credentials, transport=transport, client_options=client_options, + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, ) async def list_game_server_clusters( @@ -149,7 +203,8 @@ async def list_game_server_clusters( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([parent]): + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -174,7 +229,7 @@ async def list_game_server_clusters( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -232,7 +287,8 @@ async def get_game_server_cluster( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -257,7 +313,7 @@ async def get_game_server_cluster( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -327,9 +383,10 @@ async def create_game_server_cluster( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any( + has_flattened_params = any( [parent, game_server_cluster, game_server_cluster_id] - ): + ) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -352,7 +409,7 @@ async def create_game_server_cluster( rpc = gapic_v1.method_async.wrap_method( self._client._transport.create_game_server_cluster, default_timeout=120.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -418,7 +475,7 @@ async def preview_create_game_server_cluster( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -486,7 +543,8 @@ async def delete_game_server_cluster( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -505,7 +563,7 @@ async def delete_game_server_cluster( rpc = gapic_v1.method_async.wrap_method( self._client._transport.delete_game_server_cluster, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -570,7 +628,7 @@ async def preview_delete_game_server_cluster( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -636,7 +694,8 @@ async def update_game_server_cluster( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([game_server_cluster, update_mask]): + has_flattened_params = any([game_server_cluster, update_mask]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -657,7 +716,7 @@ async def update_game_server_cluster( rpc = gapic_v1.method_async.wrap_method( self._client._transport.update_game_server_cluster, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -724,7 +783,7 @@ async def preview_update_game_server_cluster( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -743,13 +802,13 @@ async def preview_update_game_server_cluster( try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ("GameServerClustersServiceAsyncClient",) diff --git a/google/cloud/gaming_v1beta/services/game_server_clusters_service/client.py b/google/cloud/gaming_v1beta/services/game_server_clusters_service/client.py index ac123342..44ed94af 100644 --- a/google/cloud/gaming_v1beta/services/game_server_clusters_service/client.py +++ b/google/cloud/gaming_v1beta/services/game_server_clusters_service/client.py @@ -16,22 +16,24 @@ # from collections import OrderedDict +from distutils import util import os import re -from typing import Callable, Dict, Sequence, Tuple, Type, Union +from typing import Callable, Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore +from google.api_core import client_options as client_options_lib # type: ignore from google.api_core import exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore from google.auth import credentials # type: ignore from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore -from google.api_core import operation -from google.api_core import operation_async +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore from google.cloud.gaming_v1beta.services.game_server_clusters_service import pagers from google.cloud.gaming_v1beta.types import common from google.cloud.gaming_v1beta.types import game_server_clusters @@ -39,7 +41,7 @@ from google.protobuf import field_mask_pb2 as field_mask # type: ignore from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from .transports.base import GameServerClustersServiceTransport +from .transports.base import GameServerClustersServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc import GameServerClustersServiceGrpcTransport from .transports.grpc_asyncio import GameServerClustersServiceGrpcAsyncIOTransport @@ -138,6 +140,15 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): from_service_account_json = from_service_account_file + @property + def transport(self) -> GameServerClustersServiceTransport: + """Return the transport used by the client instance. + + Returns: + GameServerClustersServiceTransport: The transport used by the client instance. + """ + return self._transport + @staticmethod def game_server_cluster_path( project: str, location: str, realm: str, cluster: str, @@ -156,12 +167,72 @@ def parse_game_server_cluster_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def common_billing_account_path(billing_account: str,) -> str: + """Return a fully-qualified billing_account string.""" + return "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + + @staticmethod + def parse_common_billing_account_path(path: str) -> Dict[str, str]: + """Parse a billing_account path into its component segments.""" + m = re.match(r"^billingAccounts/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_folder_path(folder: str,) -> str: + """Return a fully-qualified folder string.""" + return "folders/{folder}".format(folder=folder,) + + @staticmethod + def parse_common_folder_path(path: str) -> Dict[str, str]: + """Parse a folder path into its component segments.""" + m = re.match(r"^folders/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_organization_path(organization: str,) -> str: + """Return a fully-qualified organization string.""" + return "organizations/{organization}".format(organization=organization,) + + @staticmethod + def parse_common_organization_path(path: str) -> Dict[str, str]: + """Parse a organization path into its component segments.""" + m = re.match(r"^organizations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_project_path(project: str,) -> str: + """Return a fully-qualified project string.""" + return "projects/{project}".format(project=project,) + + @staticmethod + def parse_common_project_path(path: str) -> Dict[str, str]: + """Parse a project path into its component segments.""" + m = re.match(r"^projects/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_location_path(project: str, location: str,) -> str: + """Return a fully-qualified location string.""" + return "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + + @staticmethod + def parse_common_location_path(path: str) -> Dict[str, str]: + """Parse a location path into its component segments.""" + m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path) + return m.groupdict() if m else {} + def __init__( self, *, - credentials: credentials.Credentials = None, - transport: Union[str, GameServerClustersServiceTransport] = None, - client_options: ClientOptions = None, + credentials: Optional[credentials.Credentials] = None, + transport: Union[str, GameServerClustersServiceTransport, None] = None, + client_options: Optional[client_options_lib.ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the game server clusters service client. @@ -174,48 +245,74 @@ def __init__( transport (Union[str, ~.GameServerClustersServiceTransport]): The transport to use. If set to None, a transport is chosen automatically. - client_options (ClientOptions): Custom options for the client. It - won't take effect if a ``transport`` instance is provided. + client_options (client_options_lib.ClientOptions): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT environment variable can also be used to override the endpoint: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint, this is the default value for - the environment variable) and "auto" (auto switch to the default - mTLS endpoint if client SSL credentials is present). However, - the ``api_endpoint`` property takes precedence if provided. - (2) The ``client_cert_source`` property is used to provide client - SSL credentials for mutual TLS transport. If not provided, the - default SSL credentials will be used if present. + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport creation failed for any reason. """ if isinstance(client_options, dict): - client_options = ClientOptions.from_dict(client_options) + client_options = client_options_lib.from_dict(client_options) if client_options is None: - client_options = ClientOptions.ClientOptions() + client_options = client_options_lib.ClientOptions() + + # Create SSL credentials for mutual TLS if needed. + use_client_cert = bool( + util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + ) - if client_options.api_endpoint is None: - use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS", "never") + ssl_credentials = 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 + else: + creds = SslCredentials() + is_mtls = creds.is_mtls + ssl_credentials = creds.ssl_credentials if is_mtls else None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") if use_mtls_env == "never": - client_options.api_endpoint = self.DEFAULT_ENDPOINT + api_endpoint = self.DEFAULT_ENDPOINT elif use_mtls_env == "always": - client_options.api_endpoint = self.DEFAULT_MTLS_ENDPOINT + api_endpoint = self.DEFAULT_MTLS_ENDPOINT elif use_mtls_env == "auto": - has_client_cert_source = ( - client_options.client_cert_source is not None - or mtls.has_default_client_cert_source() - ) - client_options.api_endpoint = ( - self.DEFAULT_MTLS_ENDPOINT - if has_client_cert_source - else self.DEFAULT_ENDPOINT + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT if is_mtls else self.DEFAULT_ENDPOINT ) else: raise MutualTLSChannelError( - "Unsupported GOOGLE_API_USE_MTLS value. Accepted values: never, auto, always" + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always" ) # Save or instantiate the transport. @@ -239,11 +336,11 @@ def __init__( self._transport = Transport( credentials=credentials, credentials_file=client_options.credentials_file, - host=client_options.api_endpoint, + host=api_endpoint, scopes=client_options.scopes, - api_mtls_endpoint=client_options.api_endpoint, - client_cert_source=client_options.client_cert_source, + ssl_channel_credentials=ssl_credentials, quota_project_id=client_options.quota_project_id, + client_info=client_info, ) def list_game_server_clusters( @@ -891,13 +988,13 @@ def preview_update_game_server_cluster( try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ("GameServerClustersServiceClient",) diff --git a/google/cloud/gaming_v1beta/services/game_server_clusters_service/transports/base.py b/google/cloud/gaming_v1beta/services/game_server_clusters_service/transports/base.py index d26a8cf9..41a3a591 100644 --- a/google/cloud/gaming_v1beta/services/game_server_clusters_service/transports/base.py +++ b/google/cloud/gaming_v1beta/services/game_server_clusters_service/transports/base.py @@ -19,7 +19,7 @@ import typing import pkg_resources -from google import auth +from google import auth # type: ignore from google.api_core import exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore @@ -31,13 +31,13 @@ try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() class GameServerClustersServiceTransport(abc.ABC): @@ -53,6 +53,7 @@ def __init__( credentials_file: typing.Optional[str] = None, scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES, quota_project_id: typing.Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, **kwargs, ) -> None: """Instantiate the transport. @@ -70,6 +71,11 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -97,9 +103,9 @@ def __init__( self._credentials = credentials # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages() + self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self): + def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { self.list_game_server_clusters: gapic_v1.method.wrap_method( @@ -111,7 +117,7 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.get_game_server_cluster: gapic_v1.method.wrap_method( self.get_game_server_cluster, @@ -122,12 +128,12 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.create_game_server_cluster: gapic_v1.method.wrap_method( self.create_game_server_cluster, default_timeout=120.0, - client_info=_client_info, + client_info=client_info, ), self.preview_create_game_server_cluster: gapic_v1.method.wrap_method( self.preview_create_game_server_cluster, @@ -138,12 +144,12 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.delete_game_server_cluster: gapic_v1.method.wrap_method( self.delete_game_server_cluster, default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.preview_delete_game_server_cluster: gapic_v1.method.wrap_method( self.preview_delete_game_server_cluster, @@ -154,12 +160,12 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.update_game_server_cluster: gapic_v1.method.wrap_method( self.update_game_server_cluster, default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.preview_update_game_server_cluster: gapic_v1.method.wrap_method( self.preview_update_game_server_cluster, @@ -170,7 +176,7 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), } diff --git a/google/cloud/gaming_v1beta/services/game_server_clusters_service/transports/grpc.py b/google/cloud/gaming_v1beta/services/game_server_clusters_service/transports/grpc.py index 9de033f8..c62ac481 100644 --- a/google/cloud/gaming_v1beta/services/game_server_clusters_service/transports/grpc.py +++ b/google/cloud/gaming_v1beta/services/game_server_clusters_service/transports/grpc.py @@ -15,21 +15,22 @@ # limitations under the License. # +import warnings from typing import Callable, Dict, Optional, Sequence, Tuple from google.api_core import grpc_helpers # type: ignore from google.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 # type: ignore from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore - import grpc # type: ignore from google.cloud.gaming_v1beta.types import game_server_clusters from google.longrunning import operations_pb2 as operations # type: ignore -from .base import GameServerClustersServiceTransport +from .base import GameServerClustersServiceTransport, DEFAULT_CLIENT_INFO class GameServerClustersServiceGrpcTransport(GameServerClustersServiceTransport): @@ -58,7 +59,9 @@ def __init__( channel: grpc.Channel = None, api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, - quota_project_id: Optional[str] = None + ssl_channel_credentials: grpc.ChannelCredentials = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -77,16 +80,23 @@ def __init__( ignored if ``channel`` is provided. channel (Optional[grpc.Channel]): A ``Channel`` instance through which to make calls. - api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If - provided, it overrides the ``host`` argument and tries to create + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from ``client_cert_source`` or applicatin default SSL credentials. - client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A - callback to provide client SSL certificate bytes and private key - bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` - is None. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for grpc channel. It is ignored if ``channel`` 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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -94,6 +104,8 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._ssl_channel_credentials = ssl_channel_credentials + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -101,7 +113,13 @@ def __init__( # If a channel was explicitly provided, set it. 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 @@ -132,6 +150,24 @@ def __init__( scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, ) + self._ssl_channel_credentials = ssl_credentials + else: + host = host if ":" in host else host + ":443" + + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + + # 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, + scopes=scopes or self.AUTH_SCOPES, + quota_project_id=quota_project_id, + ) self._stubs = {} # type: Dict[str, Callable] @@ -142,6 +178,7 @@ def __init__( credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) @classmethod @@ -152,7 +189,7 @@ def create_channel( credentials_file: str = None, scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, - **kwargs + **kwargs, ) -> grpc.Channel: """Create and return a gRPC channel object. Args: @@ -186,24 +223,13 @@ def create_channel( credentials_file=credentials_file, scopes=scopes, quota_project_id=quota_project_id, - **kwargs + **kwargs, ) @property def grpc_channel(self) -> grpc.Channel: - """Create the channel designed to connect to this service. - - This property caches on the instance; repeated calls return - the same channel. + """Return the channel designed to connect to this service. """ - # Sanity check: Only create a new channel if we do not already - # have one. - if not hasattr(self, "_grpc_channel"): - self._grpc_channel = self.create_channel( - self._host, credentials=self._credentials, - ) - - # Return the channel from cache. return self._grpc_channel @property diff --git a/google/cloud/gaming_v1beta/services/game_server_clusters_service/transports/grpc_asyncio.py b/google/cloud/gaming_v1beta/services/game_server_clusters_service/transports/grpc_asyncio.py index 35c2600c..e1567647 100644 --- a/google/cloud/gaming_v1beta/services/game_server_clusters_service/transports/grpc_asyncio.py +++ b/google/cloud/gaming_v1beta/services/game_server_clusters_service/transports/grpc_asyncio.py @@ -15,10 +15,13 @@ # limitations under the License. # +import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple +from google.api_core import gapic_v1 # type: ignore from google.api_core import grpc_helpers_async # type: ignore from google.api_core import operations_v1 # type: ignore +from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -28,7 +31,7 @@ from google.cloud.gaming_v1beta.types import game_server_clusters from google.longrunning import operations_pb2 as operations # type: ignore -from .base import GameServerClustersServiceTransport +from .base import GameServerClustersServiceTransport, DEFAULT_CLIENT_INFO from .grpc import GameServerClustersServiceGrpcTransport @@ -100,7 +103,9 @@ def __init__( channel: aio.Channel = None, api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, + ssl_channel_credentials: grpc.ChannelCredentials = None, quota_project_id=None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -120,16 +125,23 @@ def __init__( are passed to :func:`google.auth.default`. channel (Optional[aio.Channel]): A ``Channel`` instance through which to make calls. - api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If - provided, it overrides the ``host`` argument and tries to create + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from ``client_cert_source`` or applicatin default SSL credentials. - client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A - callback to provide client SSL certificate bytes and private key - bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` - is None. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for grpc channel. It is ignored if ``channel`` 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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -137,6 +149,8 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._ssl_channel_credentials = ssl_channel_credentials + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -144,13 +158,24 @@ def __init__( # If a channel was explicitly provided, set it. 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 else api_mtls_endpoint + ":443" ) + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + # Create SSL credentials with client_cert_source or application # default SSL credentials. if client_cert_source: @@ -170,6 +195,24 @@ def __init__( scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, ) + self._ssl_channel_credentials = ssl_credentials + else: + host = host if ":" in host else host + ":443" + + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + + # 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, + scopes=scopes or self.AUTH_SCOPES, + quota_project_id=quota_project_id, + ) # Run the base constructor. super().__init__( @@ -178,6 +221,7 @@ def __init__( credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) self._stubs = {} @@ -189,13 +233,6 @@ def grpc_channel(self) -> aio.Channel: This property caches on the instance; repeated calls return the same channel. """ - # Sanity check: Only create a new channel if we do not already - # have one. - if not hasattr(self, "_grpc_channel"): - self._grpc_channel = self.create_channel( - self._host, credentials=self._credentials, - ) - # Return the channel from cache. return self._grpc_channel diff --git a/google/cloud/gaming_v1beta/services/game_server_configs_service/async_client.py b/google/cloud/gaming_v1beta/services/game_server_configs_service/async_client.py index 1aadee07..3da8992e 100644 --- a/google/cloud/gaming_v1beta/services/game_server_configs_service/async_client.py +++ b/google/cloud/gaming_v1beta/services/game_server_configs_service/async_client.py @@ -28,15 +28,15 @@ from google.auth import credentials # type: ignore from google.oauth2 import service_account # type: ignore -from google.api_core import operation -from google.api_core import operation_async +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore from google.cloud.gaming_v1beta.services.game_server_configs_service import pagers from google.cloud.gaming_v1beta.types import common from google.cloud.gaming_v1beta.types import game_server_configs from google.protobuf import empty_pb2 as empty # type: ignore from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from .transports.base import GameServerConfigsServiceTransport +from .transports.base import GameServerConfigsServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc_asyncio import GameServerConfigsServiceGrpcAsyncIOTransport from .client import GameServerConfigsServiceClient @@ -54,10 +54,55 @@ class GameServerConfigsServiceAsyncClient: game_server_config_path = staticmethod( GameServerConfigsServiceClient.game_server_config_path ) + parse_game_server_config_path = staticmethod( + GameServerConfigsServiceClient.parse_game_server_config_path + ) + + common_billing_account_path = staticmethod( + GameServerConfigsServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + GameServerConfigsServiceClient.parse_common_billing_account_path + ) + + common_folder_path = staticmethod(GameServerConfigsServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + GameServerConfigsServiceClient.parse_common_folder_path + ) + + common_organization_path = staticmethod( + GameServerConfigsServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + GameServerConfigsServiceClient.parse_common_organization_path + ) + + common_project_path = staticmethod( + GameServerConfigsServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + GameServerConfigsServiceClient.parse_common_project_path + ) + + common_location_path = staticmethod( + GameServerConfigsServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + GameServerConfigsServiceClient.parse_common_location_path + ) from_service_account_file = GameServerConfigsServiceClient.from_service_account_file from_service_account_json = from_service_account_file + @property + def transport(self) -> GameServerConfigsServiceTransport: + """Return the transport used by the client instance. + + Returns: + GameServerConfigsServiceTransport: The transport used by the client instance. + """ + return self._client.transport + get_transport_class = functools.partial( type(GameServerConfigsServiceClient).get_transport_class, type(GameServerConfigsServiceClient), @@ -69,6 +114,7 @@ def __init__( credentials: credentials.Credentials = None, transport: Union[str, GameServerConfigsServiceTransport] = "grpc_asyncio", client_options: ClientOptions = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the game server configs service client. @@ -84,16 +130,19 @@ def __init__( client_options (ClientOptions): Custom options for the client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT environment variable can also be used to override the endpoint: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint, this is the default value for - the environment variable) and "auto" (auto switch to the default - mTLS endpoint if client SSL credentials is present). However, - the ``api_endpoint`` property takes precedence if provided. - (2) The ``client_cert_source`` property is used to provide client - SSL credentials for mutual TLS transport. If not provided, the - default SSL credentials will be used if present. + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -101,7 +150,10 @@ def __init__( """ self._client = GameServerConfigsServiceClient( - credentials=credentials, transport=transport, client_options=client_options, + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, ) async def list_game_server_configs( @@ -146,7 +198,8 @@ async def list_game_server_configs( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([parent]): + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -171,7 +224,7 @@ async def list_game_server_configs( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -229,7 +282,8 @@ async def get_game_server_config( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -254,7 +308,7 @@ async def get_game_server_config( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -321,7 +375,8 @@ async def create_game_server_config( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([parent, game_server_config]): + has_flattened_params = any([parent, game_server_config]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -342,7 +397,7 @@ async def create_game_server_config( rpc = gapic_v1.method_async.wrap_method( self._client._transport.create_game_server_config, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -421,7 +476,8 @@ async def delete_game_server_config( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -440,7 +496,7 @@ async def delete_game_server_config( rpc = gapic_v1.method_async.wrap_method( self._client._transport.delete_game_server_config, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -465,13 +521,13 @@ async def delete_game_server_config( try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ("GameServerConfigsServiceAsyncClient",) diff --git a/google/cloud/gaming_v1beta/services/game_server_configs_service/client.py b/google/cloud/gaming_v1beta/services/game_server_configs_service/client.py index 19ae568d..aab3bfac 100644 --- a/google/cloud/gaming_v1beta/services/game_server_configs_service/client.py +++ b/google/cloud/gaming_v1beta/services/game_server_configs_service/client.py @@ -16,29 +16,31 @@ # from collections import OrderedDict +from distutils import util import os import re -from typing import Callable, Dict, Sequence, Tuple, Type, Union +from typing import Callable, Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore +from google.api_core import client_options as client_options_lib # type: ignore from google.api_core import exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore from google.auth import credentials # type: ignore from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore -from google.api_core import operation -from google.api_core import operation_async +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore from google.cloud.gaming_v1beta.services.game_server_configs_service import pagers from google.cloud.gaming_v1beta.types import common from google.cloud.gaming_v1beta.types import game_server_configs from google.protobuf import empty_pb2 as empty # type: ignore from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from .transports.base import GameServerConfigsServiceTransport +from .transports.base import GameServerConfigsServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc import GameServerConfigsServiceGrpcTransport from .transports.grpc_asyncio import GameServerConfigsServiceGrpcAsyncIOTransport @@ -137,6 +139,15 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): from_service_account_json = from_service_account_file + @property + def transport(self) -> GameServerConfigsServiceTransport: + """Return the transport used by the client instance. + + Returns: + GameServerConfigsServiceTransport: The transport used by the client instance. + """ + return self._transport + @staticmethod def game_server_config_path( project: str, location: str, deployment: str, config: str, @@ -155,12 +166,72 @@ def parse_game_server_config_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def common_billing_account_path(billing_account: str,) -> str: + """Return a fully-qualified billing_account string.""" + return "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + + @staticmethod + def parse_common_billing_account_path(path: str) -> Dict[str, str]: + """Parse a billing_account path into its component segments.""" + m = re.match(r"^billingAccounts/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_folder_path(folder: str,) -> str: + """Return a fully-qualified folder string.""" + return "folders/{folder}".format(folder=folder,) + + @staticmethod + def parse_common_folder_path(path: str) -> Dict[str, str]: + """Parse a folder path into its component segments.""" + m = re.match(r"^folders/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_organization_path(organization: str,) -> str: + """Return a fully-qualified organization string.""" + return "organizations/{organization}".format(organization=organization,) + + @staticmethod + def parse_common_organization_path(path: str) -> Dict[str, str]: + """Parse a organization path into its component segments.""" + m = re.match(r"^organizations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_project_path(project: str,) -> str: + """Return a fully-qualified project string.""" + return "projects/{project}".format(project=project,) + + @staticmethod + def parse_common_project_path(path: str) -> Dict[str, str]: + """Parse a project path into its component segments.""" + m = re.match(r"^projects/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_location_path(project: str, location: str,) -> str: + """Return a fully-qualified location string.""" + return "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + + @staticmethod + def parse_common_location_path(path: str) -> Dict[str, str]: + """Parse a location path into its component segments.""" + m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path) + return m.groupdict() if m else {} + def __init__( self, *, - credentials: credentials.Credentials = None, - transport: Union[str, GameServerConfigsServiceTransport] = None, - client_options: ClientOptions = None, + credentials: Optional[credentials.Credentials] = None, + transport: Union[str, GameServerConfigsServiceTransport, None] = None, + client_options: Optional[client_options_lib.ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the game server configs service client. @@ -173,48 +244,74 @@ def __init__( transport (Union[str, ~.GameServerConfigsServiceTransport]): The transport to use. If set to None, a transport is chosen automatically. - client_options (ClientOptions): Custom options for the client. It - won't take effect if a ``transport`` instance is provided. + client_options (client_options_lib.ClientOptions): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT environment variable can also be used to override the endpoint: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint, this is the default value for - the environment variable) and "auto" (auto switch to the default - mTLS endpoint if client SSL credentials is present). However, - the ``api_endpoint`` property takes precedence if provided. - (2) The ``client_cert_source`` property is used to provide client - SSL credentials for mutual TLS transport. If not provided, the - default SSL credentials will be used if present. + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport creation failed for any reason. """ if isinstance(client_options, dict): - client_options = ClientOptions.from_dict(client_options) + client_options = client_options_lib.from_dict(client_options) if client_options is None: - client_options = ClientOptions.ClientOptions() + client_options = client_options_lib.ClientOptions() + + # Create SSL credentials for mutual TLS if needed. + use_client_cert = bool( + util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + ) - if client_options.api_endpoint is None: - use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS", "never") + ssl_credentials = 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 + else: + creds = SslCredentials() + is_mtls = creds.is_mtls + ssl_credentials = creds.ssl_credentials if is_mtls else None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") if use_mtls_env == "never": - client_options.api_endpoint = self.DEFAULT_ENDPOINT + api_endpoint = self.DEFAULT_ENDPOINT elif use_mtls_env == "always": - client_options.api_endpoint = self.DEFAULT_MTLS_ENDPOINT + api_endpoint = self.DEFAULT_MTLS_ENDPOINT elif use_mtls_env == "auto": - has_client_cert_source = ( - client_options.client_cert_source is not None - or mtls.has_default_client_cert_source() - ) - client_options.api_endpoint = ( - self.DEFAULT_MTLS_ENDPOINT - if has_client_cert_source - else self.DEFAULT_ENDPOINT + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT if is_mtls else self.DEFAULT_ENDPOINT ) else: raise MutualTLSChannelError( - "Unsupported GOOGLE_API_USE_MTLS value. Accepted values: never, auto, always" + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always" ) # Save or instantiate the transport. @@ -238,11 +335,11 @@ def __init__( self._transport = Transport( credentials=credentials, credentials_file=client_options.credentials_file, - host=client_options.api_endpoint, + host=api_endpoint, scopes=client_options.scopes, - api_mtls_endpoint=client_options.api_endpoint, - client_cert_source=client_options.client_cert_source, + ssl_channel_credentials=ssl_credentials, quota_project_id=client_options.quota_project_id, + client_info=client_info, ) def list_game_server_configs( @@ -606,13 +703,13 @@ def delete_game_server_config( try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ("GameServerConfigsServiceClient",) diff --git a/google/cloud/gaming_v1beta/services/game_server_configs_service/transports/base.py b/google/cloud/gaming_v1beta/services/game_server_configs_service/transports/base.py index 0218abd2..1d658506 100644 --- a/google/cloud/gaming_v1beta/services/game_server_configs_service/transports/base.py +++ b/google/cloud/gaming_v1beta/services/game_server_configs_service/transports/base.py @@ -19,7 +19,7 @@ import typing import pkg_resources -from google import auth +from google import auth # type: ignore from google.api_core import exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore @@ -31,13 +31,13 @@ try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() class GameServerConfigsServiceTransport(abc.ABC): @@ -53,6 +53,7 @@ def __init__( credentials_file: typing.Optional[str] = None, scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES, quota_project_id: typing.Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, **kwargs, ) -> None: """Instantiate the transport. @@ -70,6 +71,11 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -97,9 +103,9 @@ def __init__( self._credentials = credentials # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages() + self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self): + def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { self.list_game_server_configs: gapic_v1.method.wrap_method( @@ -111,7 +117,7 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.get_game_server_config: gapic_v1.method.wrap_method( self.get_game_server_config, @@ -122,17 +128,17 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.create_game_server_config: gapic_v1.method.wrap_method( self.create_game_server_config, default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.delete_game_server_config: gapic_v1.method.wrap_method( self.delete_game_server_config, default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), } diff --git a/google/cloud/gaming_v1beta/services/game_server_configs_service/transports/grpc.py b/google/cloud/gaming_v1beta/services/game_server_configs_service/transports/grpc.py index 112c69cd..2d25773f 100644 --- a/google/cloud/gaming_v1beta/services/game_server_configs_service/transports/grpc.py +++ b/google/cloud/gaming_v1beta/services/game_server_configs_service/transports/grpc.py @@ -15,21 +15,22 @@ # limitations under the License. # +import warnings from typing import Callable, Dict, Optional, Sequence, Tuple from google.api_core import grpc_helpers # type: ignore from google.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 # type: ignore from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore - import grpc # type: ignore from google.cloud.gaming_v1beta.types import game_server_configs from google.longrunning import operations_pb2 as operations # type: ignore -from .base import GameServerConfigsServiceTransport +from .base import GameServerConfigsServiceTransport, DEFAULT_CLIENT_INFO class GameServerConfigsServiceGrpcTransport(GameServerConfigsServiceTransport): @@ -58,7 +59,9 @@ def __init__( channel: grpc.Channel = None, api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, - quota_project_id: Optional[str] = None + ssl_channel_credentials: grpc.ChannelCredentials = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -77,16 +80,23 @@ def __init__( ignored if ``channel`` is provided. channel (Optional[grpc.Channel]): A ``Channel`` instance through which to make calls. - api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If - provided, it overrides the ``host`` argument and tries to create + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from ``client_cert_source`` or applicatin default SSL credentials. - client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A - callback to provide client SSL certificate bytes and private key - bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` - is None. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for grpc channel. It is ignored if ``channel`` 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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -94,6 +104,8 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._ssl_channel_credentials = ssl_channel_credentials + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -101,7 +113,13 @@ def __init__( # If a channel was explicitly provided, set it. 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 @@ -132,6 +150,24 @@ def __init__( scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, ) + self._ssl_channel_credentials = ssl_credentials + else: + host = host if ":" in host else host + ":443" + + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + + # 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, + scopes=scopes or self.AUTH_SCOPES, + quota_project_id=quota_project_id, + ) self._stubs = {} # type: Dict[str, Callable] @@ -142,6 +178,7 @@ def __init__( credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) @classmethod @@ -152,7 +189,7 @@ def create_channel( credentials_file: str = None, scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, - **kwargs + **kwargs, ) -> grpc.Channel: """Create and return a gRPC channel object. Args: @@ -186,24 +223,13 @@ def create_channel( credentials_file=credentials_file, scopes=scopes, quota_project_id=quota_project_id, - **kwargs + **kwargs, ) @property def grpc_channel(self) -> grpc.Channel: - """Create the channel designed to connect to this service. - - This property caches on the instance; repeated calls return - the same channel. + """Return the channel designed to connect to this service. """ - # Sanity check: Only create a new channel if we do not already - # have one. - if not hasattr(self, "_grpc_channel"): - self._grpc_channel = self.create_channel( - self._host, credentials=self._credentials, - ) - - # Return the channel from cache. return self._grpc_channel @property diff --git a/google/cloud/gaming_v1beta/services/game_server_configs_service/transports/grpc_asyncio.py b/google/cloud/gaming_v1beta/services/game_server_configs_service/transports/grpc_asyncio.py index 2fb0f59a..caf61da8 100644 --- a/google/cloud/gaming_v1beta/services/game_server_configs_service/transports/grpc_asyncio.py +++ b/google/cloud/gaming_v1beta/services/game_server_configs_service/transports/grpc_asyncio.py @@ -15,10 +15,13 @@ # limitations under the License. # +import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple +from google.api_core import gapic_v1 # type: ignore from google.api_core import grpc_helpers_async # type: ignore from google.api_core import operations_v1 # type: ignore +from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -28,7 +31,7 @@ from google.cloud.gaming_v1beta.types import game_server_configs from google.longrunning import operations_pb2 as operations # type: ignore -from .base import GameServerConfigsServiceTransport +from .base import GameServerConfigsServiceTransport, DEFAULT_CLIENT_INFO from .grpc import GameServerConfigsServiceGrpcTransport @@ -100,7 +103,9 @@ def __init__( channel: aio.Channel = None, api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, + ssl_channel_credentials: grpc.ChannelCredentials = None, quota_project_id=None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -120,16 +125,23 @@ def __init__( are passed to :func:`google.auth.default`. channel (Optional[aio.Channel]): A ``Channel`` instance through which to make calls. - api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If - provided, it overrides the ``host`` argument and tries to create + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from ``client_cert_source`` or applicatin default SSL credentials. - client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A - callback to provide client SSL certificate bytes and private key - bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` - is None. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for grpc channel. It is ignored if ``channel`` 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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -137,6 +149,8 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._ssl_channel_credentials = ssl_channel_credentials + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -144,13 +158,24 @@ def __init__( # If a channel was explicitly provided, set it. 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 else api_mtls_endpoint + ":443" ) + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + # Create SSL credentials with client_cert_source or application # default SSL credentials. if client_cert_source: @@ -170,6 +195,24 @@ def __init__( scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, ) + self._ssl_channel_credentials = ssl_credentials + else: + host = host if ":" in host else host + ":443" + + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + + # 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, + scopes=scopes or self.AUTH_SCOPES, + quota_project_id=quota_project_id, + ) # Run the base constructor. super().__init__( @@ -178,6 +221,7 @@ def __init__( credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) self._stubs = {} @@ -189,13 +233,6 @@ def grpc_channel(self) -> aio.Channel: This property caches on the instance; repeated calls return the same channel. """ - # Sanity check: Only create a new channel if we do not already - # have one. - if not hasattr(self, "_grpc_channel"): - self._grpc_channel = self.create_channel( - self._host, credentials=self._credentials, - ) - # Return the channel from cache. return self._grpc_channel diff --git a/google/cloud/gaming_v1beta/services/game_server_deployments_service/async_client.py b/google/cloud/gaming_v1beta/services/game_server_deployments_service/async_client.py index ddb2dc01..7ebafb02 100644 --- a/google/cloud/gaming_v1beta/services/game_server_deployments_service/async_client.py +++ b/google/cloud/gaming_v1beta/services/game_server_deployments_service/async_client.py @@ -28,8 +28,8 @@ from google.auth import credentials # type: ignore from google.oauth2 import service_account # type: ignore -from google.api_core import operation -from google.api_core import operation_async +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore from google.cloud.gaming_v1beta.services.game_server_deployments_service import pagers from google.cloud.gaming_v1beta.types import common from google.cloud.gaming_v1beta.types import game_server_deployments @@ -37,7 +37,7 @@ from google.protobuf import field_mask_pb2 as field_mask # type: ignore from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from .transports.base import GameServerDeploymentsServiceTransport +from .transports.base import GameServerDeploymentsServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc_asyncio import GameServerDeploymentsServiceGrpcAsyncIOTransport from .client import GameServerDeploymentsServiceClient @@ -55,16 +55,65 @@ class GameServerDeploymentsServiceAsyncClient: game_server_deployment_path = staticmethod( GameServerDeploymentsServiceClient.game_server_deployment_path ) - + parse_game_server_deployment_path = staticmethod( + GameServerDeploymentsServiceClient.parse_game_server_deployment_path + ) game_server_deployment_rollout_path = staticmethod( GameServerDeploymentsServiceClient.game_server_deployment_rollout_path ) + parse_game_server_deployment_rollout_path = staticmethod( + GameServerDeploymentsServiceClient.parse_game_server_deployment_rollout_path + ) + + common_billing_account_path = staticmethod( + GameServerDeploymentsServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + GameServerDeploymentsServiceClient.parse_common_billing_account_path + ) + + common_folder_path = staticmethod( + GameServerDeploymentsServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + GameServerDeploymentsServiceClient.parse_common_folder_path + ) + + common_organization_path = staticmethod( + GameServerDeploymentsServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + GameServerDeploymentsServiceClient.parse_common_organization_path + ) + + common_project_path = staticmethod( + GameServerDeploymentsServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + GameServerDeploymentsServiceClient.parse_common_project_path + ) + + common_location_path = staticmethod( + GameServerDeploymentsServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + GameServerDeploymentsServiceClient.parse_common_location_path + ) from_service_account_file = ( GameServerDeploymentsServiceClient.from_service_account_file ) from_service_account_json = from_service_account_file + @property + def transport(self) -> GameServerDeploymentsServiceTransport: + """Return the transport used by the client instance. + + Returns: + GameServerDeploymentsServiceTransport: The transport used by the client instance. + """ + return self._client.transport + get_transport_class = functools.partial( type(GameServerDeploymentsServiceClient).get_transport_class, type(GameServerDeploymentsServiceClient), @@ -76,6 +125,7 @@ def __init__( credentials: credentials.Credentials = None, transport: Union[str, GameServerDeploymentsServiceTransport] = "grpc_asyncio", client_options: ClientOptions = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the game server deployments service client. @@ -91,16 +141,19 @@ def __init__( client_options (ClientOptions): Custom options for the client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT environment variable can also be used to override the endpoint: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint, this is the default value for - the environment variable) and "auto" (auto switch to the default - mTLS endpoint if client SSL credentials is present). However, - the ``api_endpoint`` property takes precedence if provided. - (2) The ``client_cert_source`` property is used to provide client - SSL credentials for mutual TLS transport. If not provided, the - default SSL credentials will be used if present. + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -108,7 +161,10 @@ def __init__( """ self._client = GameServerDeploymentsServiceClient( - credentials=credentials, transport=transport, client_options=client_options, + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, ) async def list_game_server_deployments( @@ -152,7 +208,8 @@ async def list_game_server_deployments( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([parent]): + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -177,7 +234,7 @@ async def list_game_server_deployments( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -235,7 +292,8 @@ async def get_game_server_deployment( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -260,7 +318,7 @@ async def get_game_server_deployment( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -323,7 +381,8 @@ async def create_game_server_deployment( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([parent, game_server_deployment]): + has_flattened_params = any([parent, game_server_deployment]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -344,7 +403,7 @@ async def create_game_server_deployment( rpc = gapic_v1.method_async.wrap_method( self._client._transport.create_game_server_deployment, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -421,7 +480,8 @@ async def delete_game_server_deployment( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -440,7 +500,7 @@ async def delete_game_server_deployment( rpc = gapic_v1.method_async.wrap_method( self._client._transport.delete_game_server_deployment, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -515,7 +575,8 @@ async def update_game_server_deployment( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([game_server_deployment, update_mask]): + has_flattened_params = any([game_server_deployment, update_mask]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -536,7 +597,7 @@ async def update_game_server_deployment( rpc = gapic_v1.method_async.wrap_method( self._client._transport.update_game_server_deployment, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -601,7 +662,8 @@ async def get_game_server_deployment_rollout( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -626,7 +688,7 @@ async def get_game_server_deployment_rollout( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -699,7 +761,8 @@ async def update_game_server_deployment_rollout( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([rollout, update_mask]): + has_flattened_params = any([rollout, update_mask]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -722,7 +785,7 @@ async def update_game_server_deployment_rollout( rpc = gapic_v1.method_async.wrap_method( self._client._transport.update_game_server_deployment_rollout, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -794,7 +857,7 @@ async def preview_game_server_deployment_rollout( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -856,7 +919,7 @@ async def fetch_deployment_state( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -873,13 +936,13 @@ async def fetch_deployment_state( try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ("GameServerDeploymentsServiceAsyncClient",) diff --git a/google/cloud/gaming_v1beta/services/game_server_deployments_service/client.py b/google/cloud/gaming_v1beta/services/game_server_deployments_service/client.py index 085b4f48..358055a4 100644 --- a/google/cloud/gaming_v1beta/services/game_server_deployments_service/client.py +++ b/google/cloud/gaming_v1beta/services/game_server_deployments_service/client.py @@ -16,22 +16,24 @@ # from collections import OrderedDict +from distutils import util import os import re -from typing import Callable, Dict, Sequence, Tuple, Type, Union +from typing import Callable, Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore +from google.api_core import client_options as client_options_lib # type: ignore from google.api_core import exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore from google.auth import credentials # type: ignore from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore -from google.api_core import operation -from google.api_core import operation_async +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore from google.cloud.gaming_v1beta.services.game_server_deployments_service import pagers from google.cloud.gaming_v1beta.types import common from google.cloud.gaming_v1beta.types import game_server_deployments @@ -39,7 +41,7 @@ from google.protobuf import field_mask_pb2 as field_mask # type: ignore from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from .transports.base import GameServerDeploymentsServiceTransport +from .transports.base import GameServerDeploymentsServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc import GameServerDeploymentsServiceGrpcTransport from .transports.grpc_asyncio import GameServerDeploymentsServiceGrpcAsyncIOTransport @@ -142,6 +144,15 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): from_service_account_json = from_service_account_file + @property + def transport(self) -> GameServerDeploymentsServiceTransport: + """Return the transport used by the client instance. + + Returns: + GameServerDeploymentsServiceTransport: The transport used by the client instance. + """ + return self._transport + @staticmethod def game_server_deployment_path( project: str, location: str, deployment: str, @@ -178,12 +189,72 @@ def parse_game_server_deployment_rollout_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def common_billing_account_path(billing_account: str,) -> str: + """Return a fully-qualified billing_account string.""" + return "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + + @staticmethod + def parse_common_billing_account_path(path: str) -> Dict[str, str]: + """Parse a billing_account path into its component segments.""" + m = re.match(r"^billingAccounts/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_folder_path(folder: str,) -> str: + """Return a fully-qualified folder string.""" + return "folders/{folder}".format(folder=folder,) + + @staticmethod + def parse_common_folder_path(path: str) -> Dict[str, str]: + """Parse a folder path into its component segments.""" + m = re.match(r"^folders/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_organization_path(organization: str,) -> str: + """Return a fully-qualified organization string.""" + return "organizations/{organization}".format(organization=organization,) + + @staticmethod + def parse_common_organization_path(path: str) -> Dict[str, str]: + """Parse a organization path into its component segments.""" + m = re.match(r"^organizations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_project_path(project: str,) -> str: + """Return a fully-qualified project string.""" + return "projects/{project}".format(project=project,) + + @staticmethod + def parse_common_project_path(path: str) -> Dict[str, str]: + """Parse a project path into its component segments.""" + m = re.match(r"^projects/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_location_path(project: str, location: str,) -> str: + """Return a fully-qualified location string.""" + return "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + + @staticmethod + def parse_common_location_path(path: str) -> Dict[str, str]: + """Parse a location path into its component segments.""" + m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path) + return m.groupdict() if m else {} + def __init__( self, *, - credentials: credentials.Credentials = None, - transport: Union[str, GameServerDeploymentsServiceTransport] = None, - client_options: ClientOptions = None, + credentials: Optional[credentials.Credentials] = None, + transport: Union[str, GameServerDeploymentsServiceTransport, None] = None, + client_options: Optional[client_options_lib.ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the game server deployments service client. @@ -196,48 +267,74 @@ def __init__( transport (Union[str, ~.GameServerDeploymentsServiceTransport]): The transport to use. If set to None, a transport is chosen automatically. - client_options (ClientOptions): Custom options for the client. It - won't take effect if a ``transport`` instance is provided. + client_options (client_options_lib.ClientOptions): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT environment variable can also be used to override the endpoint: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint, this is the default value for - the environment variable) and "auto" (auto switch to the default - mTLS endpoint if client SSL credentials is present). However, - the ``api_endpoint`` property takes precedence if provided. - (2) The ``client_cert_source`` property is used to provide client - SSL credentials for mutual TLS transport. If not provided, the - default SSL credentials will be used if present. + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport creation failed for any reason. """ if isinstance(client_options, dict): - client_options = ClientOptions.from_dict(client_options) + client_options = client_options_lib.from_dict(client_options) if client_options is None: - client_options = ClientOptions.ClientOptions() + client_options = client_options_lib.ClientOptions() + + # Create SSL credentials for mutual TLS if needed. + use_client_cert = bool( + util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + ) - if client_options.api_endpoint is None: - use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS", "never") + ssl_credentials = 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 + else: + creds = SslCredentials() + is_mtls = creds.is_mtls + ssl_credentials = creds.ssl_credentials if is_mtls else None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") if use_mtls_env == "never": - client_options.api_endpoint = self.DEFAULT_ENDPOINT + api_endpoint = self.DEFAULT_ENDPOINT elif use_mtls_env == "always": - client_options.api_endpoint = self.DEFAULT_MTLS_ENDPOINT + api_endpoint = self.DEFAULT_MTLS_ENDPOINT elif use_mtls_env == "auto": - has_client_cert_source = ( - client_options.client_cert_source is not None - or mtls.has_default_client_cert_source() - ) - client_options.api_endpoint = ( - self.DEFAULT_MTLS_ENDPOINT - if has_client_cert_source - else self.DEFAULT_ENDPOINT + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT if is_mtls else self.DEFAULT_ENDPOINT ) else: raise MutualTLSChannelError( - "Unsupported GOOGLE_API_USE_MTLS value. Accepted values: never, auto, always" + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always" ) # Save or instantiate the transport. @@ -261,11 +358,11 @@ def __init__( self._transport = Transport( credentials=credentials, credentials_file=client_options.credentials_file, - host=client_options.api_endpoint, + host=api_endpoint, scopes=client_options.scopes, - api_mtls_endpoint=client_options.api_endpoint, - client_cert_source=client_options.client_cert_source, + ssl_channel_credentials=ssl_credentials, quota_project_id=client_options.quota_project_id, + client_info=client_info, ) def list_game_server_deployments( @@ -1050,13 +1147,13 @@ def fetch_deployment_state( try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ("GameServerDeploymentsServiceClient",) diff --git a/google/cloud/gaming_v1beta/services/game_server_deployments_service/transports/base.py b/google/cloud/gaming_v1beta/services/game_server_deployments_service/transports/base.py index 382bb205..8a510155 100644 --- a/google/cloud/gaming_v1beta/services/game_server_deployments_service/transports/base.py +++ b/google/cloud/gaming_v1beta/services/game_server_deployments_service/transports/base.py @@ -19,7 +19,7 @@ import typing import pkg_resources -from google import auth +from google import auth # type: ignore from google.api_core import exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore @@ -31,13 +31,13 @@ try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() class GameServerDeploymentsServiceTransport(abc.ABC): @@ -53,6 +53,7 @@ def __init__( credentials_file: typing.Optional[str] = None, scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES, quota_project_id: typing.Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, **kwargs, ) -> None: """Instantiate the transport. @@ -70,6 +71,11 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -97,9 +103,9 @@ def __init__( self._credentials = credentials # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages() + self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self): + def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { self.list_game_server_deployments: gapic_v1.method.wrap_method( @@ -111,7 +117,7 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.get_game_server_deployment: gapic_v1.method.wrap_method( self.get_game_server_deployment, @@ -122,22 +128,22 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.create_game_server_deployment: gapic_v1.method.wrap_method( self.create_game_server_deployment, default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.delete_game_server_deployment: gapic_v1.method.wrap_method( self.delete_game_server_deployment, default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.update_game_server_deployment: gapic_v1.method.wrap_method( self.update_game_server_deployment, default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.get_game_server_deployment_rollout: gapic_v1.method.wrap_method( self.get_game_server_deployment_rollout, @@ -148,12 +154,12 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.update_game_server_deployment_rollout: gapic_v1.method.wrap_method( self.update_game_server_deployment_rollout, default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.preview_game_server_deployment_rollout: gapic_v1.method.wrap_method( self.preview_game_server_deployment_rollout, @@ -164,7 +170,7 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.fetch_deployment_state: gapic_v1.method.wrap_method( self.fetch_deployment_state, @@ -175,7 +181,7 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), } diff --git a/google/cloud/gaming_v1beta/services/game_server_deployments_service/transports/grpc.py b/google/cloud/gaming_v1beta/services/game_server_deployments_service/transports/grpc.py index 77a2c611..415d00f6 100644 --- a/google/cloud/gaming_v1beta/services/game_server_deployments_service/transports/grpc.py +++ b/google/cloud/gaming_v1beta/services/game_server_deployments_service/transports/grpc.py @@ -15,21 +15,22 @@ # limitations under the License. # +import warnings from typing import Callable, Dict, Optional, Sequence, Tuple from google.api_core import grpc_helpers # type: ignore from google.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 # type: ignore from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore - import grpc # type: ignore from google.cloud.gaming_v1beta.types import game_server_deployments from google.longrunning import operations_pb2 as operations # type: ignore -from .base import GameServerDeploymentsServiceTransport +from .base import GameServerDeploymentsServiceTransport, DEFAULT_CLIENT_INFO class GameServerDeploymentsServiceGrpcTransport(GameServerDeploymentsServiceTransport): @@ -58,7 +59,9 @@ def __init__( channel: grpc.Channel = None, api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, - quota_project_id: Optional[str] = None + ssl_channel_credentials: grpc.ChannelCredentials = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -77,16 +80,23 @@ def __init__( ignored if ``channel`` is provided. channel (Optional[grpc.Channel]): A ``Channel`` instance through which to make calls. - api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If - provided, it overrides the ``host`` argument and tries to create + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from ``client_cert_source`` or applicatin default SSL credentials. - client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A - callback to provide client SSL certificate bytes and private key - bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` - is None. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for grpc channel. It is ignored if ``channel`` 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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -94,6 +104,8 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._ssl_channel_credentials = ssl_channel_credentials + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -101,7 +113,13 @@ def __init__( # If a channel was explicitly provided, set it. 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 @@ -132,6 +150,24 @@ def __init__( scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, ) + self._ssl_channel_credentials = ssl_credentials + else: + host = host if ":" in host else host + ":443" + + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + + # 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, + scopes=scopes or self.AUTH_SCOPES, + quota_project_id=quota_project_id, + ) self._stubs = {} # type: Dict[str, Callable] @@ -142,6 +178,7 @@ def __init__( credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) @classmethod @@ -152,7 +189,7 @@ def create_channel( credentials_file: str = None, scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, - **kwargs + **kwargs, ) -> grpc.Channel: """Create and return a gRPC channel object. Args: @@ -186,24 +223,13 @@ def create_channel( credentials_file=credentials_file, scopes=scopes, quota_project_id=quota_project_id, - **kwargs + **kwargs, ) @property def grpc_channel(self) -> grpc.Channel: - """Create the channel designed to connect to this service. - - This property caches on the instance; repeated calls return - the same channel. + """Return the channel designed to connect to this service. """ - # Sanity check: Only create a new channel if we do not already - # have one. - if not hasattr(self, "_grpc_channel"): - self._grpc_channel = self.create_channel( - self._host, credentials=self._credentials, - ) - - # Return the channel from cache. return self._grpc_channel @property diff --git a/google/cloud/gaming_v1beta/services/game_server_deployments_service/transports/grpc_asyncio.py b/google/cloud/gaming_v1beta/services/game_server_deployments_service/transports/grpc_asyncio.py index afdcdc54..4c14f322 100644 --- a/google/cloud/gaming_v1beta/services/game_server_deployments_service/transports/grpc_asyncio.py +++ b/google/cloud/gaming_v1beta/services/game_server_deployments_service/transports/grpc_asyncio.py @@ -15,10 +15,13 @@ # limitations under the License. # +import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple +from google.api_core import gapic_v1 # type: ignore from google.api_core import grpc_helpers_async # type: ignore from google.api_core import operations_v1 # type: ignore +from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -28,7 +31,7 @@ from google.cloud.gaming_v1beta.types import game_server_deployments from google.longrunning import operations_pb2 as operations # type: ignore -from .base import GameServerDeploymentsServiceTransport +from .base import GameServerDeploymentsServiceTransport, DEFAULT_CLIENT_INFO from .grpc import GameServerDeploymentsServiceGrpcTransport @@ -102,7 +105,9 @@ def __init__( channel: aio.Channel = None, api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, + ssl_channel_credentials: grpc.ChannelCredentials = None, quota_project_id=None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -122,16 +127,23 @@ def __init__( are passed to :func:`google.auth.default`. channel (Optional[aio.Channel]): A ``Channel`` instance through which to make calls. - api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If - provided, it overrides the ``host`` argument and tries to create + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from ``client_cert_source`` or applicatin default SSL credentials. - client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A - callback to provide client SSL certificate bytes and private key - bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` - is None. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for grpc channel. It is ignored if ``channel`` 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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -139,6 +151,8 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._ssl_channel_credentials = ssl_channel_credentials + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -146,13 +160,24 @@ def __init__( # If a channel was explicitly provided, set it. 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 else api_mtls_endpoint + ":443" ) + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + # Create SSL credentials with client_cert_source or application # default SSL credentials. if client_cert_source: @@ -172,6 +197,24 @@ def __init__( scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, ) + self._ssl_channel_credentials = ssl_credentials + else: + host = host if ":" in host else host + ":443" + + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + + # 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, + scopes=scopes or self.AUTH_SCOPES, + quota_project_id=quota_project_id, + ) # Run the base constructor. super().__init__( @@ -180,6 +223,7 @@ def __init__( credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) self._stubs = {} @@ -191,13 +235,6 @@ def grpc_channel(self) -> aio.Channel: This property caches on the instance; repeated calls return the same channel. """ - # Sanity check: Only create a new channel if we do not already - # have one. - if not hasattr(self, "_grpc_channel"): - self._grpc_channel = self.create_channel( - self._host, credentials=self._credentials, - ) - # Return the channel from cache. return self._grpc_channel diff --git a/google/cloud/gaming_v1beta/services/realms_service/async_client.py b/google/cloud/gaming_v1beta/services/realms_service/async_client.py index 22639b9b..eb9ff3b0 100644 --- a/google/cloud/gaming_v1beta/services/realms_service/async_client.py +++ b/google/cloud/gaming_v1beta/services/realms_service/async_client.py @@ -28,8 +28,8 @@ from google.auth import credentials # type: ignore from google.oauth2 import service_account # type: ignore -from google.api_core import operation -from google.api_core import operation_async +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore from google.cloud.gaming_v1beta.services.realms_service import pagers from google.cloud.gaming_v1beta.types import common from google.cloud.gaming_v1beta.types import realms @@ -37,7 +37,7 @@ from google.protobuf import field_mask_pb2 as field_mask # type: ignore from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from .transports.base import RealmsServiceTransport +from .transports.base import RealmsServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc_asyncio import RealmsServiceGrpcAsyncIOTransport from .client import RealmsServiceClient @@ -53,10 +53,49 @@ class RealmsServiceAsyncClient: DEFAULT_MTLS_ENDPOINT = RealmsServiceClient.DEFAULT_MTLS_ENDPOINT realm_path = staticmethod(RealmsServiceClient.realm_path) + parse_realm_path = staticmethod(RealmsServiceClient.parse_realm_path) + + common_billing_account_path = staticmethod( + RealmsServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + RealmsServiceClient.parse_common_billing_account_path + ) + + common_folder_path = staticmethod(RealmsServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + RealmsServiceClient.parse_common_folder_path + ) + + common_organization_path = staticmethod( + RealmsServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + RealmsServiceClient.parse_common_organization_path + ) + + common_project_path = staticmethod(RealmsServiceClient.common_project_path) + parse_common_project_path = staticmethod( + RealmsServiceClient.parse_common_project_path + ) + + common_location_path = staticmethod(RealmsServiceClient.common_location_path) + parse_common_location_path = staticmethod( + RealmsServiceClient.parse_common_location_path + ) from_service_account_file = RealmsServiceClient.from_service_account_file from_service_account_json = from_service_account_file + @property + def transport(self) -> RealmsServiceTransport: + """Return the transport used by the client instance. + + Returns: + RealmsServiceTransport: The transport used by the client instance. + """ + return self._client.transport + get_transport_class = functools.partial( type(RealmsServiceClient).get_transport_class, type(RealmsServiceClient) ) @@ -67,6 +106,7 @@ def __init__( credentials: credentials.Credentials = None, transport: Union[str, RealmsServiceTransport] = "grpc_asyncio", client_options: ClientOptions = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the realms service client. @@ -82,16 +122,19 @@ def __init__( client_options (ClientOptions): Custom options for the client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT environment variable can also be used to override the endpoint: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint, this is the default value for - the environment variable) and "auto" (auto switch to the default - mTLS endpoint if client SSL credentials is present). However, - the ``api_endpoint`` property takes precedence if provided. - (2) The ``client_cert_source`` property is used to provide client - SSL credentials for mutual TLS transport. If not provided, the - default SSL credentials will be used if present. + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -99,7 +142,10 @@ def __init__( """ self._client = RealmsServiceClient( - credentials=credentials, transport=transport, client_options=client_options, + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, ) async def list_realms( @@ -142,7 +188,8 @@ async def list_realms( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([parent]): + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -167,7 +214,7 @@ async def list_realms( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -224,7 +271,8 @@ async def get_realm( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -249,7 +297,7 @@ async def get_realm( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -317,7 +365,8 @@ async def create_realm( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([parent, realm, realm_id]): + has_flattened_params = any([parent, realm, realm_id]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -340,7 +389,7 @@ async def create_realm( rpc = gapic_v1.method_async.wrap_method( self._client._transport.create_realm, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -416,7 +465,8 @@ async def delete_realm( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([name]): + has_flattened_params = any([name]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -435,7 +485,7 @@ async def delete_realm( rpc = gapic_v1.method_async.wrap_method( self._client._transport.delete_realm, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -507,7 +557,8 @@ async def update_realm( # Create or coerce a protobuf request object. # Sanity check: If we got a request object, we should *not* have # gotten any keyword arguments that map to the request. - if request is not None and any([realm, update_mask]): + has_flattened_params = any([realm, update_mask]) + if request is not None and has_flattened_params: raise ValueError( "If the `request` argument is set, then none of " "the individual field arguments should be set." @@ -528,7 +579,7 @@ async def update_realm( rpc = gapic_v1.method_async.wrap_method( self._client._transport.update_realm, default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -595,7 +646,7 @@ async def preview_realm_update( predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=DEFAULT_CLIENT_INFO, ) # Certain fields should be provided within the metadata header; @@ -614,13 +665,13 @@ async def preview_realm_update( try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ("RealmsServiceAsyncClient",) diff --git a/google/cloud/gaming_v1beta/services/realms_service/client.py b/google/cloud/gaming_v1beta/services/realms_service/client.py index 83cf35aa..aa4dc719 100644 --- a/google/cloud/gaming_v1beta/services/realms_service/client.py +++ b/google/cloud/gaming_v1beta/services/realms_service/client.py @@ -16,22 +16,24 @@ # from collections import OrderedDict +from distutils import util import os import re -from typing import Callable, Dict, Sequence, Tuple, Type, Union +from typing import Callable, Dict, Optional, Sequence, Tuple, Type, Union import pkg_resources -import google.api_core.client_options as ClientOptions # type: ignore +from google.api_core import client_options as client_options_lib # type: ignore from google.api_core import exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore from google.auth import credentials # type: ignore from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore from google.auth.exceptions import MutualTLSChannelError # type: ignore from google.oauth2 import service_account # type: ignore -from google.api_core import operation -from google.api_core import operation_async +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore from google.cloud.gaming_v1beta.services.realms_service import pagers from google.cloud.gaming_v1beta.types import common from google.cloud.gaming_v1beta.types import realms @@ -39,7 +41,7 @@ from google.protobuf import field_mask_pb2 as field_mask # type: ignore from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from .transports.base import RealmsServiceTransport +from .transports.base import RealmsServiceTransport, DEFAULT_CLIENT_INFO from .transports.grpc import RealmsServiceGrpcTransport from .transports.grpc_asyncio import RealmsServiceGrpcAsyncIOTransport @@ -134,6 +136,15 @@ def from_service_account_file(cls, filename: str, *args, **kwargs): from_service_account_json = from_service_account_file + @property + def transport(self) -> RealmsServiceTransport: + """Return the transport used by the client instance. + + Returns: + RealmsServiceTransport: The transport used by the client instance. + """ + return self._transport + @staticmethod def realm_path(project: str, location: str, realm: str,) -> str: """Return a fully-qualified realm string.""" @@ -150,12 +161,72 @@ def parse_realm_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def common_billing_account_path(billing_account: str,) -> str: + """Return a fully-qualified billing_account string.""" + return "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + + @staticmethod + def parse_common_billing_account_path(path: str) -> Dict[str, str]: + """Parse a billing_account path into its component segments.""" + m = re.match(r"^billingAccounts/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_folder_path(folder: str,) -> str: + """Return a fully-qualified folder string.""" + return "folders/{folder}".format(folder=folder,) + + @staticmethod + def parse_common_folder_path(path: str) -> Dict[str, str]: + """Parse a folder path into its component segments.""" + m = re.match(r"^folders/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_organization_path(organization: str,) -> str: + """Return a fully-qualified organization string.""" + return "organizations/{organization}".format(organization=organization,) + + @staticmethod + def parse_common_organization_path(path: str) -> Dict[str, str]: + """Parse a organization path into its component segments.""" + m = re.match(r"^organizations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_project_path(project: str,) -> str: + """Return a fully-qualified project string.""" + return "projects/{project}".format(project=project,) + + @staticmethod + def parse_common_project_path(path: str) -> Dict[str, str]: + """Parse a project path into its component segments.""" + m = re.match(r"^projects/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_location_path(project: str, location: str,) -> str: + """Return a fully-qualified location string.""" + return "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + + @staticmethod + def parse_common_location_path(path: str) -> Dict[str, str]: + """Parse a location path into its component segments.""" + m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path) + return m.groupdict() if m else {} + def __init__( self, *, - credentials: credentials.Credentials = None, - transport: Union[str, RealmsServiceTransport] = None, - client_options: ClientOptions = None, + credentials: Optional[credentials.Credentials] = None, + transport: Union[str, RealmsServiceTransport, None] = None, + client_options: Optional[client_options_lib.ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the realms service client. @@ -168,48 +239,74 @@ def __init__( transport (Union[str, ~.RealmsServiceTransport]): The transport to use. If set to None, a transport is chosen automatically. - client_options (ClientOptions): Custom options for the client. It - won't take effect if a ``transport`` instance is provided. + client_options (client_options_lib.ClientOptions): Custom options for the + client. It won't take effect if a ``transport`` instance is provided. (1) The ``api_endpoint`` property can be used to override the - default endpoint provided by the client. GOOGLE_API_USE_MTLS + default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT environment variable can also be used to override the endpoint: "always" (always use the default mTLS endpoint), "never" (always - use the default regular endpoint, this is the default value for - the environment variable) and "auto" (auto switch to the default - mTLS endpoint if client SSL credentials is present). However, - the ``api_endpoint`` property takes precedence if provided. - (2) The ``client_cert_source`` property is used to provide client - SSL credentials for mutual TLS transport. If not provided, the - default SSL credentials will be used if present. + use the default regular endpoint) and "auto" (auto switch to the + default mTLS endpoint if client certificate is present, this is + the default value). However, the ``api_endpoint`` property takes + precedence if provided. + (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide client certificate for mutual TLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport creation failed for any reason. """ if isinstance(client_options, dict): - client_options = ClientOptions.from_dict(client_options) + client_options = client_options_lib.from_dict(client_options) if client_options is None: - client_options = ClientOptions.ClientOptions() + client_options = client_options_lib.ClientOptions() + + # Create SSL credentials for mutual TLS if needed. + use_client_cert = bool( + util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")) + ) - if client_options.api_endpoint is None: - use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS", "never") + ssl_credentials = 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 + else: + creds = SslCredentials() + is_mtls = creds.is_mtls + ssl_credentials = creds.ssl_credentials if is_mtls else None + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + else: + use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") if use_mtls_env == "never": - client_options.api_endpoint = self.DEFAULT_ENDPOINT + api_endpoint = self.DEFAULT_ENDPOINT elif use_mtls_env == "always": - client_options.api_endpoint = self.DEFAULT_MTLS_ENDPOINT + api_endpoint = self.DEFAULT_MTLS_ENDPOINT elif use_mtls_env == "auto": - has_client_cert_source = ( - client_options.client_cert_source is not None - or mtls.has_default_client_cert_source() - ) - client_options.api_endpoint = ( - self.DEFAULT_MTLS_ENDPOINT - if has_client_cert_source - else self.DEFAULT_ENDPOINT + api_endpoint = ( + self.DEFAULT_MTLS_ENDPOINT if is_mtls else self.DEFAULT_ENDPOINT ) else: raise MutualTLSChannelError( - "Unsupported GOOGLE_API_USE_MTLS value. Accepted values: never, auto, always" + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always" ) # Save or instantiate the transport. @@ -233,11 +330,11 @@ def __init__( self._transport = Transport( credentials=credentials, credentials_file=client_options.credentials_file, - host=client_options.api_endpoint, + host=api_endpoint, scopes=client_options.scopes, - api_mtls_endpoint=client_options.api_endpoint, - client_cert_source=client_options.client_cert_source, + ssl_channel_credentials=ssl_credentials, quota_project_id=client_options.quota_project_id, + client_info=client_info, ) def list_realms( @@ -745,13 +842,13 @@ def preview_realm_update( try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() __all__ = ("RealmsServiceClient",) diff --git a/google/cloud/gaming_v1beta/services/realms_service/transports/base.py b/google/cloud/gaming_v1beta/services/realms_service/transports/base.py index ab96aab3..ee7b7b69 100644 --- a/google/cloud/gaming_v1beta/services/realms_service/transports/base.py +++ b/google/cloud/gaming_v1beta/services/realms_service/transports/base.py @@ -19,7 +19,7 @@ import typing import pkg_resources -from google import auth +from google import auth # type: ignore from google.api_core import exceptions # type: ignore from google.api_core import gapic_v1 # type: ignore from google.api_core import retry as retries # type: ignore @@ -31,13 +31,13 @@ try: - _client_info = gapic_v1.client_info.ClientInfo( + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=pkg_resources.get_distribution( "google-cloud-game-servers", ).version, ) except pkg_resources.DistributionNotFound: - _client_info = gapic_v1.client_info.ClientInfo() + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() class RealmsServiceTransport(abc.ABC): @@ -53,6 +53,7 @@ def __init__( credentials_file: typing.Optional[str] = None, scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES, quota_project_id: typing.Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, **kwargs, ) -> None: """Instantiate the transport. @@ -70,6 +71,11 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -97,9 +103,9 @@ def __init__( self._credentials = credentials # Lifted into its own function so it can be stubbed out during tests. - self._prep_wrapped_messages() + self._prep_wrapped_messages(client_info) - def _prep_wrapped_messages(self): + def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { self.list_realms: gapic_v1.method.wrap_method( @@ -111,7 +117,7 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.get_realm: gapic_v1.method.wrap_method( self.get_realm, @@ -122,16 +128,16 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), self.create_realm: gapic_v1.method.wrap_method( - self.create_realm, default_timeout=60.0, client_info=_client_info, + self.create_realm, default_timeout=60.0, client_info=client_info, ), self.delete_realm: gapic_v1.method.wrap_method( - self.delete_realm, default_timeout=60.0, client_info=_client_info, + self.delete_realm, default_timeout=60.0, client_info=client_info, ), self.update_realm: gapic_v1.method.wrap_method( - self.update_realm, default_timeout=60.0, client_info=_client_info, + self.update_realm, default_timeout=60.0, client_info=client_info, ), self.preview_realm_update: gapic_v1.method.wrap_method( self.preview_realm_update, @@ -142,7 +148,7 @@ def _prep_wrapped_messages(self): predicate=retries.if_exception_type(exceptions.ServiceUnavailable,), ), default_timeout=60.0, - client_info=_client_info, + client_info=client_info, ), } diff --git a/google/cloud/gaming_v1beta/services/realms_service/transports/grpc.py b/google/cloud/gaming_v1beta/services/realms_service/transports/grpc.py index fdfc9459..c592d900 100644 --- a/google/cloud/gaming_v1beta/services/realms_service/transports/grpc.py +++ b/google/cloud/gaming_v1beta/services/realms_service/transports/grpc.py @@ -15,21 +15,22 @@ # limitations under the License. # +import warnings from typing import Callable, Dict, Optional, Sequence, Tuple from google.api_core import grpc_helpers # type: ignore from google.api_core import operations_v1 # type: ignore +from google.api_core import gapic_v1 # type: ignore from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore - import grpc # type: ignore from google.cloud.gaming_v1beta.types import realms from google.longrunning import operations_pb2 as operations # type: ignore -from .base import RealmsServiceTransport +from .base import RealmsServiceTransport, DEFAULT_CLIENT_INFO class RealmsServiceGrpcTransport(RealmsServiceTransport): @@ -58,7 +59,9 @@ def __init__( channel: grpc.Channel = None, api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, - quota_project_id: Optional[str] = None + ssl_channel_credentials: grpc.ChannelCredentials = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -77,16 +80,23 @@ def __init__( ignored if ``channel`` is provided. channel (Optional[grpc.Channel]): A ``Channel`` instance through which to make calls. - api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If - provided, it overrides the ``host`` argument and tries to create + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from ``client_cert_source`` or applicatin default SSL credentials. - client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A - callback to provide client SSL certificate bytes and private key - bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` - is None. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for grpc channel. It is ignored if ``channel`` 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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -94,6 +104,8 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._ssl_channel_credentials = ssl_channel_credentials + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -101,7 +113,13 @@ def __init__( # If a channel was explicitly provided, set it. 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 @@ -132,6 +150,24 @@ def __init__( scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, ) + self._ssl_channel_credentials = ssl_credentials + else: + host = host if ":" in host else host + ":443" + + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + + # 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, + scopes=scopes or self.AUTH_SCOPES, + quota_project_id=quota_project_id, + ) self._stubs = {} # type: Dict[str, Callable] @@ -142,6 +178,7 @@ def __init__( credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) @classmethod @@ -152,7 +189,7 @@ def create_channel( credentials_file: str = None, scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, - **kwargs + **kwargs, ) -> grpc.Channel: """Create and return a gRPC channel object. Args: @@ -186,24 +223,13 @@ def create_channel( credentials_file=credentials_file, scopes=scopes, quota_project_id=quota_project_id, - **kwargs + **kwargs, ) @property def grpc_channel(self) -> grpc.Channel: - """Create the channel designed to connect to this service. - - This property caches on the instance; repeated calls return - the same channel. + """Return the channel designed to connect to this service. """ - # Sanity check: Only create a new channel if we do not already - # have one. - if not hasattr(self, "_grpc_channel"): - self._grpc_channel = self.create_channel( - self._host, credentials=self._credentials, - ) - - # Return the channel from cache. return self._grpc_channel @property diff --git a/google/cloud/gaming_v1beta/services/realms_service/transports/grpc_asyncio.py b/google/cloud/gaming_v1beta/services/realms_service/transports/grpc_asyncio.py index a287ddeb..0313db01 100644 --- a/google/cloud/gaming_v1beta/services/realms_service/transports/grpc_asyncio.py +++ b/google/cloud/gaming_v1beta/services/realms_service/transports/grpc_asyncio.py @@ -15,10 +15,13 @@ # limitations under the License. # +import warnings from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple +from google.api_core import gapic_v1 # type: ignore from google.api_core import grpc_helpers_async # type: ignore from google.api_core import operations_v1 # type: ignore +from google import auth # type: ignore from google.auth import credentials # type: ignore from google.auth.transport.grpc import SslCredentials # type: ignore @@ -28,7 +31,7 @@ from google.cloud.gaming_v1beta.types import realms from google.longrunning import operations_pb2 as operations # type: ignore -from .base import RealmsServiceTransport +from .base import RealmsServiceTransport, DEFAULT_CLIENT_INFO from .grpc import RealmsServiceGrpcTransport @@ -100,7 +103,9 @@ def __init__( channel: aio.Channel = None, api_mtls_endpoint: str = None, client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, + ssl_channel_credentials: grpc.ChannelCredentials = None, quota_project_id=None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, ) -> None: """Instantiate the transport. @@ -120,16 +125,23 @@ def __init__( are passed to :func:`google.auth.default`. channel (Optional[aio.Channel]): A ``Channel`` instance through which to make calls. - api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If - provided, it overrides the ``host`` argument and tries to create + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create a mutual TLS channel with client SSL credentials from ``client_cert_source`` or applicatin default SSL credentials. - client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A - callback to provide client SSL certificate bytes and private key - bytes, both in PEM format. It is ignored if ``api_mtls_endpoint`` - is None. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for grpc channel. It is ignored if ``channel`` 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): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -137,6 +149,8 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._ssl_channel_credentials = ssl_channel_credentials + if channel: # Sanity check: Ensure that channel and credentials are not both # provided. @@ -144,13 +158,24 @@ def __init__( # If a channel was explicitly provided, set it. 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 else api_mtls_endpoint + ":443" ) + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + # Create SSL credentials with client_cert_source or application # default SSL credentials. if client_cert_source: @@ -170,6 +195,24 @@ def __init__( scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, ) + self._ssl_channel_credentials = ssl_credentials + else: + host = host if ":" in host else host + ":443" + + if credentials is None: + credentials, _ = auth.default( + scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id + ) + + # 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, + scopes=scopes or self.AUTH_SCOPES, + quota_project_id=quota_project_id, + ) # Run the base constructor. super().__init__( @@ -178,6 +221,7 @@ def __init__( credentials_file=credentials_file, scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, + client_info=client_info, ) self._stubs = {} @@ -189,13 +233,6 @@ def grpc_channel(self) -> aio.Channel: This property caches on the instance; repeated calls return the same channel. """ - # Sanity check: Only create a new channel if we do not already - # have one. - if not hasattr(self, "_grpc_channel"): - self._grpc_channel = self.create_channel( - self._host, credentials=self._credentials, - ) - # Return the channel from cache. return self._grpc_channel diff --git a/google/cloud/gaming_v1beta/types/common.py b/google/cloud/gaming_v1beta/types/common.py index 839ca1d7..3efaba32 100644 --- a/google/cloud/gaming_v1beta/types/common.py +++ b/google/cloud/gaming_v1beta/types/common.py @@ -248,7 +248,7 @@ class TargetFleet(proto.Message): name = proto.Field(proto.STRING, number=1) - spec_source = proto.Field(proto.MESSAGE, number=2, message=SpecSource,) + spec_source = proto.Field(proto.MESSAGE, number=2, message="SpecSource",) class TargetFleetAutoscaler(proto.Message): r"""Target Agones autoscaler policy reference. @@ -263,7 +263,7 @@ class TargetFleetAutoscaler(proto.Message): name = proto.Field(proto.STRING, number=1) - spec_source = proto.Field(proto.MESSAGE, number=2, message=SpecSource,) + spec_source = proto.Field(proto.MESSAGE, number=2, message="SpecSource",) fleet = proto.Field( proto.MESSAGE, @@ -294,7 +294,7 @@ class TargetState(proto.Message): Details about Agones fleets. """ - details = proto.RepeatedField(proto.MESSAGE, number=1, message=TargetDetails,) + details = proto.RepeatedField(proto.MESSAGE, number=1, message="TargetDetails",) class DeployedFleetDetails(proto.Message): @@ -360,7 +360,7 @@ class DeployedFleetStatus(proto.Message): fleet_spec = proto.Field(proto.STRING, number=2) - spec_source = proto.Field(proto.MESSAGE, number=3, message=SpecSource,) + spec_source = proto.Field(proto.MESSAGE, number=3, message="SpecSource",) status = proto.Field( proto.MESSAGE, @@ -384,7 +384,7 @@ class DeployedFleetAutoscaler(proto.Message): autoscaler = proto.Field(proto.STRING, number=1) - spec_source = proto.Field(proto.MESSAGE, number=4, message=SpecSource,) + spec_source = proto.Field(proto.MESSAGE, number=4, message="SpecSource",) fleet_autoscaler_spec = proto.Field(proto.STRING, number=3) diff --git a/google/cloud/gaming_v1beta/types/game_server_clusters.py b/google/cloud/gaming_v1beta/types/game_server_clusters.py index f6b7f16d..5214f202 100644 --- a/google/cloud/gaming_v1beta/types/game_server_clusters.py +++ b/google/cloud/gaming_v1beta/types/game_server_clusters.py @@ -398,7 +398,7 @@ class GameServerCluster(proto.Message): labels = proto.MapField(proto.STRING, proto.STRING, number=4) connection_info = proto.Field( - proto.MESSAGE, number=5, message=GameServerClusterConnectionInfo, + proto.MESSAGE, number=5, message="GameServerClusterConnectionInfo", ) etag = proto.Field(proto.STRING, number=6) diff --git a/google/cloud/gaming_v1beta/types/game_server_configs.py b/google/cloud/gaming_v1beta/types/game_server_configs.py index c662b16d..dabb462d 100644 --- a/google/cloud/gaming_v1beta/types/game_server_configs.py +++ b/google/cloud/gaming_v1beta/types/game_server_configs.py @@ -244,10 +244,10 @@ class GameServerConfig(proto.Message): labels = proto.MapField(proto.STRING, proto.STRING, number=4) - fleet_configs = proto.RepeatedField(proto.MESSAGE, number=5, message=FleetConfig,) + fleet_configs = proto.RepeatedField(proto.MESSAGE, number=5, message="FleetConfig",) scaling_configs = proto.RepeatedField( - proto.MESSAGE, number=6, message=ScalingConfig, + proto.MESSAGE, number=6, message="ScalingConfig", ) description = proto.Field(proto.STRING, number=7) diff --git a/google/cloud/gaming_v1beta/types/game_server_deployments.py b/google/cloud/gaming_v1beta/types/game_server_deployments.py index 761e3a2a..dfae4b88 100644 --- a/google/cloud/gaming_v1beta/types/game_server_deployments.py +++ b/google/cloud/gaming_v1beta/types/game_server_deployments.py @@ -379,7 +379,7 @@ class GameServerDeploymentRollout(proto.Message): default_game_server_config = proto.Field(proto.STRING, number=4) game_server_config_overrides = proto.RepeatedField( - proto.MESSAGE, number=5, message=GameServerConfigOverride, + proto.MESSAGE, number=5, message="GameServerConfigOverride", ) etag = proto.Field(proto.STRING, number=6) @@ -405,7 +405,9 @@ class PreviewGameServerDeploymentRolloutRequest(proto.Message): proposed rollout completes. """ - rollout = proto.Field(proto.MESSAGE, number=1, message=GameServerDeploymentRollout,) + rollout = proto.Field( + proto.MESSAGE, number=1, message="GameServerDeploymentRollout", + ) update_mask = proto.Field(proto.MESSAGE, number=2, message=field_mask.FieldMask,) diff --git a/noxfile.py b/noxfile.py index ea5ed9f8..3d05d6c1 100644 --- a/noxfile.py +++ b/noxfile.py @@ -28,7 +28,7 @@ DEFAULT_PYTHON_VERSION = "3.8" SYSTEM_TEST_PYTHON_VERSIONS = ["3.8"] -UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8"] +UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9"] @nox.session(python=DEFAULT_PYTHON_VERSION) @@ -72,7 +72,9 @@ def default(session): # Install all test dependencies, then install this package in-place. session.install("asyncmock", "pytest-asyncio") - session.install("mock", "pytest", "pytest-cov") + session.install( + "mock", "pytest", "pytest-cov", + ) session.install("-e", ".") # Run py.test against the unit tests. @@ -173,7 +175,9 @@ def docfx(session): """Build the docfx yaml files for this library.""" session.install("-e", ".") - session.install("sphinx", "alabaster", "recommonmark", "sphinx-docfx-yaml") + # sphinx-docfx-yaml supports up to sphinx version 1.5.5. + # https://github.com/docascode/sphinx-docfx-yaml/issues/97 + session.install("sphinx==1.5.5", "alabaster", "recommonmark", "sphinx-docfx-yaml") shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True) session.run( diff --git a/samples/snippets/noxfile.py b/samples/snippets/noxfile.py index ba55d7ce..b90eef00 100644 --- a/samples/snippets/noxfile.py +++ b/samples/snippets/noxfile.py @@ -39,6 +39,10 @@ # You can opt out from the test for specific Python versions. 'ignored_versions': ["2.7"], + # Old samples are opted out of enforcing Python type hints + # All new samples should feature them + 'enforce_type_hints': False, + # An envvar key for determining the project id to use. Change it # to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a # build specific Cloud project. You can also use your own string @@ -132,7 +136,10 @@ def _determine_local_import_names(start_dir): @nox.session def lint(session): - session.install("flake8", "flake8-import-order") + if not TEST_CONFIG['enforce_type_hints']: + session.install("flake8", "flake8-import-order") + else: + session.install("flake8", "flake8-import-order", "flake8-annotations") local_names = _determine_local_import_names(".") args = FLAKE8_COMMON_ARGS + [ @@ -141,8 +148,18 @@ def lint(session): "." ] session.run("flake8", *args) +# +# Black +# +@nox.session +def blacken(session): + session.install("black") + python_files = [path for path in os.listdir(".") if path.endswith(".py")] + + session.run("black", *python_files) + # # Sample Tests # @@ -201,6 +218,11 @@ def _get_repo_root(): break if Path(p / ".git").exists(): return str(p) + # .git is not available in repos cloned via Cloud Build + # setup.py is always in the library's root, so use that instead + # https://github.com/googleapis/synthtool/issues/792 + if Path(p / "setup.py").exists(): + return str(p) p = p.parent raise Exception("Unable to detect repository root.") diff --git a/scripts/decrypt-secrets.sh b/scripts/decrypt-secrets.sh index ff599eb2..21f6d2a2 100755 --- a/scripts/decrypt-secrets.sh +++ b/scripts/decrypt-secrets.sh @@ -20,14 +20,27 @@ ROOT=$( dirname "$DIR" ) # Work from the project root. cd $ROOT +# Prevent it from overriding files. +# We recommend that sample authors use their own service account files and cloud project. +# In that case, they are supposed to prepare these files by themselves. +if [[ -f "testing/test-env.sh" ]] || \ + [[ -f "testing/service-account.json" ]] || \ + [[ -f "testing/client-secrets.json" ]]; then + echo "One or more target files exist, aborting." + exit 1 +fi + # Use SECRET_MANAGER_PROJECT if set, fallback to cloud-devrel-kokoro-resources. PROJECT_ID="${SECRET_MANAGER_PROJECT:-cloud-devrel-kokoro-resources}" gcloud secrets versions access latest --secret="python-docs-samples-test-env" \ + --project="${PROJECT_ID}" \ > testing/test-env.sh gcloud secrets versions access latest \ --secret="python-docs-samples-service-account" \ + --project="${PROJECT_ID}" \ > testing/service-account.json gcloud secrets versions access latest \ --secret="python-docs-samples-client-secrets" \ - > testing/client-secrets.json \ No newline at end of file + --project="${PROJECT_ID}" \ + > testing/client-secrets.json diff --git a/scripts/fixup_gaming_v1_keywords.py b/scripts/fixup_gaming_v1_keywords.py index e7239f29..18a00b63 100644 --- a/scripts/fixup_gaming_v1_keywords.py +++ b/scripts/fixup_gaming_v1_keywords.py @@ -1,3 +1,4 @@ +#! /usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright 2020 Google LLC diff --git a/scripts/fixup_gaming_v1beta_keywords.py b/scripts/fixup_gaming_v1beta_keywords.py index e7239f29..18a00b63 100644 --- a/scripts/fixup_gaming_v1beta_keywords.py +++ b/scripts/fixup_gaming_v1beta_keywords.py @@ -1,3 +1,4 @@ +#! /usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright 2020 Google LLC diff --git a/synth.metadata b/synth.metadata index 142de287..60e6c790 100644 --- a/synth.metadata +++ b/synth.metadata @@ -3,30 +3,30 @@ { "git": { "name": ".", - "remote": "https://github.com/googleapis/python-game-servers.git", - "sha": "ae50e3323d3e048d7495c870c288768fc7f10633" + "remote": "git@github.com:googleapis/python-game-servers", + "sha": "cfc8e5f7aeb3bc06f524cfb4684e0d3712a4939b" } }, { "git": { "name": "googleapis", "remote": "https://github.com/googleapis/googleapis.git", - "sha": "fb84629a56703d04f0b5304c4a9ade7313ebd92d", - "internalRef": "325339219" + "sha": "e3e7e7ddb0fecd7bc61ca03b5a9ddb29cc9b48d8", + "internalRef": "342967619" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "5f2f711c91199ba2f609d3f06a2fe22aee4e5be3" + "sha": "7fcc405a579d5d53a726ff3da1b7c8c08f0f2d58" } }, { "git": { "name": "synthtool", "remote": "https://github.com/googleapis/synthtool.git", - "sha": "5f2f711c91199ba2f609d3f06a2fe22aee4e5be3" + "sha": "7fcc405a579d5d53a726ff3da1b7c8c08f0f2d58" } } ], diff --git a/tests/unit/gapic/gaming_v1/test_game_server_clusters_service.py b/tests/unit/gapic/gaming_v1/test_game_server_clusters_service.py index 3dfea2c7..7f9e1eec 100644 --- a/tests/unit/gapic/gaming_v1/test_game_server_clusters_service.py +++ b/tests/unit/gapic/gaming_v1/test_game_server_clusters_service.py @@ -31,7 +31,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async -from google.api_core import operation_async +from google.api_core import operation_async # type: ignore from google.api_core import operations_v1 from google.auth import credentials from google.auth.exceptions import MutualTLSChannelError @@ -109,12 +109,12 @@ def test_game_server_clusters_service_client_from_service_account_file(client_cl ) as factory: factory.return_value = creds client = client_class.from_service_account_file("dummy/file/path.json") - assert client._transport._credentials == creds + assert client.transport._credentials == creds client = client_class.from_service_account_json("dummy/file/path.json") - assert client._transport._credentials == creds + assert client.transport._credentials == creds - assert client._transport._host == "gameservices.googleapis.com:443" + assert client.transport._host == "gameservices.googleapis.com:443" def test_game_server_clusters_service_client_get_transport_class(): @@ -178,14 +178,14 @@ def test_game_server_clusters_service_client_client_options( credentials_file=None, host="squid.clam.whelk", scopes=None, - api_mtls_endpoint="squid.clam.whelk", - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is # "never". - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "never"}): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None client = client_class() @@ -194,14 +194,14 @@ def test_game_server_clusters_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is # "always". - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "always"}): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None client = client_class() @@ -210,90 +210,185 @@ def test_game_server_clusters_service_client_client_options( credentials_file=None, host=client.DEFAULT_MTLS_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", and client_cert_source is provided. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError): + client = client_class() + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError): + client = client_class() + + # Check the case quota_project_id is provided + options = client_options.ClientOptions(quota_project_id="octopus") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + ssl_channel_credentials=None, + quota_project_id="octopus", + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,use_client_cert_env", + [ + ( + GameServerClustersServiceClient, + transports.GameServerClustersServiceGrpcTransport, + "grpc", + "true", + ), + ( + GameServerClustersServiceAsyncClient, + transports.GameServerClustersServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + ( + GameServerClustersServiceClient, + transports.GameServerClustersServiceGrpcTransport, + "grpc", + "false", + ), + ( + GameServerClustersServiceAsyncClient, + transports.GameServerClustersServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ], +) +@mock.patch.object( + GameServerClustersServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GameServerClustersServiceClient), +) +@mock.patch.object( + GameServerClustersServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GameServerClustersServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_game_server_clusters_service_client_mtls_env_auto( + client_class, transport_class, transport_name, use_client_cert_env +): + # This tests the endpoint autoswitch behavior. Endpoint is autoswitched to the default + # mtls endpoint, if GOOGLE_API_USE_CLIENT_CERTIFICATE is "true" and client cert exists. + + # Check the case client_cert_source is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): options = client_options.ClientOptions( client_cert_source=client_cert_source_callback ) with mock.patch.object(transport_class, "__init__") as patched: - patched.return_value = None - client = client_class(client_options=options) - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_MTLS_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=client_cert_source_callback, - quota_project_id=None, - ) - - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", and default_client_cert_source is provided. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): - with mock.patch.object(transport_class, "__init__") as patched: + ssl_channel_creds = mock.Mock() with mock.patch( - "google.auth.transport.mtls.has_default_client_cert_source", - return_value=True, + "grpc.ssl_channel_credentials", return_value=ssl_channel_creds ): patched.return_value = None - client = client_class() + 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 + patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_MTLS_ENDPOINT, + host=expected_host, scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=expected_ssl_channel_creds, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", but client_cert_source and default_client_cert_source are None. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): + # Check the case ADC client cert is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + 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, + "google.auth.transport.grpc.SslCredentials.__init__", return_value=None ): - patched.return_value = None - client = client_class() - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, - quota_project_id=None, - ) - - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS has - # unsupported value. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "Unsupported"}): - with pytest.raises(MutualTLSChannelError): - client = client_class() - - # Check the case quota_project_id is provided - options = client_options.ClientOptions(quota_project_id="octopus") - with mock.patch.object(transport_class, "__init__") as patched: - patched.return_value = None - client = client_class(client_options=options) - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, - quota_project_id="octopus", - ) + 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, + ) + + # 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, + scopes=None, + ssl_channel_credentials=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) @pytest.mark.parametrize( @@ -324,9 +419,9 @@ def test_game_server_clusters_service_client_client_options_scopes( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=["1", "2"], - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -358,9 +453,9 @@ def test_game_server_clusters_service_client_client_options_credentials_file( credentials_file="credentials.json", host=client.DEFAULT_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -377,9 +472,9 @@ def test_game_server_clusters_service_client_client_options_from_dict(): credentials_file=None, host="squid.clam.whelk", scopes=None, - api_mtls_endpoint="squid.clam.whelk", - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -397,7 +492,7 @@ def test_list_game_server_clusters( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_clusters), "__call__" + type(client.transport.list_game_server_clusters), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.ListGameServerClustersResponse( @@ -413,6 +508,7 @@ def test_list_game_server_clusters( assert args[0] == game_server_clusters.ListGameServerClustersRequest() # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListGameServerClustersPager) assert response.next_page_token == "next_page_token_value" @@ -425,18 +521,21 @@ def test_list_game_server_clusters_from_dict(): @pytest.mark.asyncio -async def test_list_game_server_clusters_async(transport: str = "grpc_asyncio"): +async def test_list_game_server_clusters_async( + transport: str = "grpc_asyncio", + request_type=game_server_clusters.ListGameServerClustersRequest, +): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_clusters.ListGameServerClustersRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_clusters), "__call__" + type(client.transport.list_game_server_clusters), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -452,7 +551,7 @@ async def test_list_game_server_clusters_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_clusters.ListGameServerClustersRequest() # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListGameServerClustersAsyncPager) @@ -462,6 +561,11 @@ async def test_list_game_server_clusters_async(transport: str = "grpc_asyncio"): assert response.unreachable == ["unreachable_value"] +@pytest.mark.asyncio +async def test_list_game_server_clusters_async_from_dict(): + await test_list_game_server_clusters_async(request_type=dict) + + def test_list_game_server_clusters_field_headers(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), @@ -474,7 +578,7 @@ def test_list_game_server_clusters_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_clusters), "__call__" + type(client.transport.list_game_server_clusters), "__call__" ) as call: call.return_value = game_server_clusters.ListGameServerClustersResponse() @@ -503,7 +607,7 @@ async def test_list_game_server_clusters_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_clusters), "__call__" + type(client.transport.list_game_server_clusters), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_clusters.ListGameServerClustersResponse() @@ -528,7 +632,7 @@ def test_list_game_server_clusters_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_clusters), "__call__" + type(client.transport.list_game_server_clusters), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.ListGameServerClustersResponse() @@ -566,7 +670,7 @@ async def test_list_game_server_clusters_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_clusters), "__call__" + type(client.transport.list_game_server_clusters), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.ListGameServerClustersResponse() @@ -607,7 +711,7 @@ def test_list_game_server_clusters_pager(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_clusters), "__call__" + type(client.transport.list_game_server_clusters), "__call__" ) as call: # Set the response to a series of pages. call.side_effect = ( @@ -657,7 +761,7 @@ def test_list_game_server_clusters_pages(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_clusters), "__call__" + type(client.transport.list_game_server_clusters), "__call__" ) as call: # Set the response to a series of pages. call.side_effect = ( @@ -685,8 +789,8 @@ def test_list_game_server_clusters_pages(): RuntimeError, ) pages = list(client.list_game_server_clusters(request={}).pages) - for page, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page.raw_page.next_page_token == token + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token @pytest.mark.asyncio @@ -697,7 +801,7 @@ async def test_list_game_server_clusters_async_pager(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_clusters), + type(client.transport.list_game_server_clusters), "__call__", new_callable=mock.AsyncMock, ) as call: @@ -746,7 +850,7 @@ async def test_list_game_server_clusters_async_pages(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_clusters), + type(client.transport.list_game_server_clusters), "__call__", new_callable=mock.AsyncMock, ) as call: @@ -776,10 +880,10 @@ async def test_list_game_server_clusters_async_pages(): RuntimeError, ) pages = [] - async for page in (await client.list_game_server_clusters(request={})).pages: - pages.append(page) - for page, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page.raw_page.next_page_token == token + async for page_ in (await client.list_game_server_clusters(request={})).pages: + pages.append(page_) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token def test_get_game_server_cluster( @@ -796,7 +900,7 @@ def test_get_game_server_cluster( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_cluster), "__call__" + type(client.transport.get_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.GameServerCluster( @@ -812,6 +916,7 @@ def test_get_game_server_cluster( assert args[0] == game_server_clusters.GetGameServerClusterRequest() # Establish that the response is the type that we expect. + assert isinstance(response, game_server_clusters.GameServerCluster) assert response.name == "name_value" @@ -826,18 +931,21 @@ def test_get_game_server_cluster_from_dict(): @pytest.mark.asyncio -async def test_get_game_server_cluster_async(transport: str = "grpc_asyncio"): +async def test_get_game_server_cluster_async( + transport: str = "grpc_asyncio", + request_type=game_server_clusters.GetGameServerClusterRequest, +): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_clusters.GetGameServerClusterRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_cluster), "__call__" + type(client.transport.get_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -852,7 +960,7 @@ async def test_get_game_server_cluster_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_clusters.GetGameServerClusterRequest() # Establish that the response is the type that we expect. assert isinstance(response, game_server_clusters.GameServerCluster) @@ -864,6 +972,11 @@ async def test_get_game_server_cluster_async(transport: str = "grpc_asyncio"): assert response.description == "description_value" +@pytest.mark.asyncio +async def test_get_game_server_cluster_async_from_dict(): + await test_get_game_server_cluster_async(request_type=dict) + + def test_get_game_server_cluster_field_headers(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), @@ -876,7 +989,7 @@ def test_get_game_server_cluster_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_cluster), "__call__" + type(client.transport.get_game_server_cluster), "__call__" ) as call: call.return_value = game_server_clusters.GameServerCluster() @@ -905,7 +1018,7 @@ async def test_get_game_server_cluster_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_cluster), "__call__" + type(client.transport.get_game_server_cluster), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_clusters.GameServerCluster() @@ -930,7 +1043,7 @@ def test_get_game_server_cluster_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_cluster), "__call__" + type(client.transport.get_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.GameServerCluster() @@ -968,7 +1081,7 @@ async def test_get_game_server_cluster_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_cluster), "__call__" + type(client.transport.get_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.GameServerCluster() @@ -1016,7 +1129,7 @@ def test_create_game_server_cluster( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_cluster), "__call__" + type(client.transport.create_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1038,18 +1151,21 @@ def test_create_game_server_cluster_from_dict(): @pytest.mark.asyncio -async def test_create_game_server_cluster_async(transport: str = "grpc_asyncio"): +async def test_create_game_server_cluster_async( + transport: str = "grpc_asyncio", + request_type=game_server_clusters.CreateGameServerClusterRequest, +): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_clusters.CreateGameServerClusterRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_cluster), "__call__" + type(client.transport.create_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1062,12 +1178,17 @@ async def test_create_game_server_cluster_async(transport: str = "grpc_asyncio") assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_clusters.CreateGameServerClusterRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_create_game_server_cluster_async_from_dict(): + await test_create_game_server_cluster_async(request_type=dict) + + def test_create_game_server_cluster_field_headers(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1080,7 +1201,7 @@ def test_create_game_server_cluster_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_cluster), "__call__" + type(client.transport.create_game_server_cluster), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -1109,7 +1230,7 @@ async def test_create_game_server_cluster_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_cluster), "__call__" + type(client.transport.create_game_server_cluster), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -1134,7 +1255,7 @@ def test_create_game_server_cluster_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_cluster), "__call__" + type(client.transport.create_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1189,7 +1310,7 @@ async def test_create_game_server_cluster_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_cluster), "__call__" + type(client.transport.create_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1254,7 +1375,7 @@ def test_preview_create_game_server_cluster( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_create_game_server_cluster), "__call__" + type(client.transport.preview_create_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.PreviewCreateGameServerClusterResponse( @@ -1270,6 +1391,7 @@ def test_preview_create_game_server_cluster( assert args[0] == game_server_clusters.PreviewCreateGameServerClusterRequest() # Establish that the response is the type that we expect. + assert isinstance( response, game_server_clusters.PreviewCreateGameServerClusterResponse ) @@ -1284,6 +1406,7 @@ def test_preview_create_game_server_cluster_from_dict(): @pytest.mark.asyncio async def test_preview_create_game_server_cluster_async( transport: str = "grpc_asyncio", + request_type=game_server_clusters.PreviewCreateGameServerClusterRequest, ): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, @@ -1291,11 +1414,11 @@ async def test_preview_create_game_server_cluster_async( # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_clusters.PreviewCreateGameServerClusterRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_create_game_server_cluster), "__call__" + type(client.transport.preview_create_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1310,7 +1433,7 @@ async def test_preview_create_game_server_cluster_async( assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_clusters.PreviewCreateGameServerClusterRequest() # Establish that the response is the type that we expect. assert isinstance( @@ -1320,6 +1443,11 @@ async def test_preview_create_game_server_cluster_async( assert response.etag == "etag_value" +@pytest.mark.asyncio +async def test_preview_create_game_server_cluster_async_from_dict(): + await test_preview_create_game_server_cluster_async(request_type=dict) + + def test_preview_create_game_server_cluster_field_headers(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1332,7 +1460,7 @@ def test_preview_create_game_server_cluster_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_create_game_server_cluster), "__call__" + type(client.transport.preview_create_game_server_cluster), "__call__" ) as call: call.return_value = ( game_server_clusters.PreviewCreateGameServerClusterResponse() @@ -1363,7 +1491,7 @@ async def test_preview_create_game_server_cluster_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_create_game_server_cluster), "__call__" + type(client.transport.preview_create_game_server_cluster), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_clusters.PreviewCreateGameServerClusterResponse() @@ -1395,7 +1523,7 @@ def test_delete_game_server_cluster( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_cluster), "__call__" + type(client.transport.delete_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1417,18 +1545,21 @@ def test_delete_game_server_cluster_from_dict(): @pytest.mark.asyncio -async def test_delete_game_server_cluster_async(transport: str = "grpc_asyncio"): +async def test_delete_game_server_cluster_async( + transport: str = "grpc_asyncio", + request_type=game_server_clusters.DeleteGameServerClusterRequest, +): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_clusters.DeleteGameServerClusterRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_cluster), "__call__" + type(client.transport.delete_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1441,12 +1572,17 @@ async def test_delete_game_server_cluster_async(transport: str = "grpc_asyncio") assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_clusters.DeleteGameServerClusterRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_delete_game_server_cluster_async_from_dict(): + await test_delete_game_server_cluster_async(request_type=dict) + + def test_delete_game_server_cluster_field_headers(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1459,7 +1595,7 @@ def test_delete_game_server_cluster_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_cluster), "__call__" + type(client.transport.delete_game_server_cluster), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -1488,7 +1624,7 @@ async def test_delete_game_server_cluster_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_cluster), "__call__" + type(client.transport.delete_game_server_cluster), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -1513,7 +1649,7 @@ def test_delete_game_server_cluster_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_cluster), "__call__" + type(client.transport.delete_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1551,7 +1687,7 @@ async def test_delete_game_server_cluster_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_cluster), "__call__" + type(client.transport.delete_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1599,7 +1735,7 @@ def test_preview_delete_game_server_cluster( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_delete_game_server_cluster), "__call__" + type(client.transport.preview_delete_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.PreviewDeleteGameServerClusterResponse( @@ -1615,6 +1751,7 @@ def test_preview_delete_game_server_cluster( assert args[0] == game_server_clusters.PreviewDeleteGameServerClusterRequest() # Establish that the response is the type that we expect. + assert isinstance( response, game_server_clusters.PreviewDeleteGameServerClusterResponse ) @@ -1629,6 +1766,7 @@ def test_preview_delete_game_server_cluster_from_dict(): @pytest.mark.asyncio async def test_preview_delete_game_server_cluster_async( transport: str = "grpc_asyncio", + request_type=game_server_clusters.PreviewDeleteGameServerClusterRequest, ): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, @@ -1636,11 +1774,11 @@ async def test_preview_delete_game_server_cluster_async( # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_clusters.PreviewDeleteGameServerClusterRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_delete_game_server_cluster), "__call__" + type(client.transport.preview_delete_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1655,7 +1793,7 @@ async def test_preview_delete_game_server_cluster_async( assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_clusters.PreviewDeleteGameServerClusterRequest() # Establish that the response is the type that we expect. assert isinstance( @@ -1665,6 +1803,11 @@ async def test_preview_delete_game_server_cluster_async( assert response.etag == "etag_value" +@pytest.mark.asyncio +async def test_preview_delete_game_server_cluster_async_from_dict(): + await test_preview_delete_game_server_cluster_async(request_type=dict) + + def test_preview_delete_game_server_cluster_field_headers(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1677,7 +1820,7 @@ def test_preview_delete_game_server_cluster_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_delete_game_server_cluster), "__call__" + type(client.transport.preview_delete_game_server_cluster), "__call__" ) as call: call.return_value = ( game_server_clusters.PreviewDeleteGameServerClusterResponse() @@ -1708,7 +1851,7 @@ async def test_preview_delete_game_server_cluster_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_delete_game_server_cluster), "__call__" + type(client.transport.preview_delete_game_server_cluster), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_clusters.PreviewDeleteGameServerClusterResponse() @@ -1740,7 +1883,7 @@ def test_update_game_server_cluster( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_cluster), "__call__" + type(client.transport.update_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1762,18 +1905,21 @@ def test_update_game_server_cluster_from_dict(): @pytest.mark.asyncio -async def test_update_game_server_cluster_async(transport: str = "grpc_asyncio"): +async def test_update_game_server_cluster_async( + transport: str = "grpc_asyncio", + request_type=game_server_clusters.UpdateGameServerClusterRequest, +): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_clusters.UpdateGameServerClusterRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_cluster), "__call__" + type(client.transport.update_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1786,12 +1932,17 @@ async def test_update_game_server_cluster_async(transport: str = "grpc_asyncio") assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_clusters.UpdateGameServerClusterRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_update_game_server_cluster_async_from_dict(): + await test_update_game_server_cluster_async(request_type=dict) + + def test_update_game_server_cluster_field_headers(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1804,7 +1955,7 @@ def test_update_game_server_cluster_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_cluster), "__call__" + type(client.transport.update_game_server_cluster), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -1836,7 +1987,7 @@ async def test_update_game_server_cluster_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_cluster), "__call__" + type(client.transport.update_game_server_cluster), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -1864,7 +2015,7 @@ def test_update_game_server_cluster_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_cluster), "__call__" + type(client.transport.update_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1915,7 +2066,7 @@ async def test_update_game_server_cluster_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_cluster), "__call__" + type(client.transport.update_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1976,7 +2127,7 @@ def test_preview_update_game_server_cluster( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_update_game_server_cluster), "__call__" + type(client.transport.preview_update_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.PreviewUpdateGameServerClusterResponse( @@ -1992,6 +2143,7 @@ def test_preview_update_game_server_cluster( assert args[0] == game_server_clusters.PreviewUpdateGameServerClusterRequest() # Establish that the response is the type that we expect. + assert isinstance( response, game_server_clusters.PreviewUpdateGameServerClusterResponse ) @@ -2006,6 +2158,7 @@ def test_preview_update_game_server_cluster_from_dict(): @pytest.mark.asyncio async def test_preview_update_game_server_cluster_async( transport: str = "grpc_asyncio", + request_type=game_server_clusters.PreviewUpdateGameServerClusterRequest, ): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, @@ -2013,11 +2166,11 @@ async def test_preview_update_game_server_cluster_async( # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_clusters.PreviewUpdateGameServerClusterRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_update_game_server_cluster), "__call__" + type(client.transport.preview_update_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -2032,7 +2185,7 @@ async def test_preview_update_game_server_cluster_async( assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_clusters.PreviewUpdateGameServerClusterRequest() # Establish that the response is the type that we expect. assert isinstance( @@ -2042,6 +2195,11 @@ async def test_preview_update_game_server_cluster_async( assert response.etag == "etag_value" +@pytest.mark.asyncio +async def test_preview_update_game_server_cluster_async_from_dict(): + await test_preview_update_game_server_cluster_async(request_type=dict) + + def test_preview_update_game_server_cluster_field_headers(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), @@ -2054,7 +2212,7 @@ def test_preview_update_game_server_cluster_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_update_game_server_cluster), "__call__" + type(client.transport.preview_update_game_server_cluster), "__call__" ) as call: call.return_value = ( game_server_clusters.PreviewUpdateGameServerClusterResponse() @@ -2088,7 +2246,7 @@ async def test_preview_update_game_server_cluster_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_update_game_server_cluster), "__call__" + type(client.transport.preview_update_game_server_cluster), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_clusters.PreviewUpdateGameServerClusterResponse() @@ -2145,7 +2303,7 @@ def test_transport_instance(): credentials=credentials.AnonymousCredentials(), ) client = GameServerClustersServiceClient(transport=transport) - assert client._transport is transport + assert client.transport is transport def test_transport_get_channel(): @@ -2163,13 +2321,28 @@ def test_transport_get_channel(): assert channel +@pytest.mark.parametrize( + "transport_class", + [ + transports.GameServerClustersServiceGrpcTransport, + transports.GameServerClustersServiceGrpcAsyncIOTransport, + ], +) +def test_transport_adc(transport_class): + # Test default credentials are used if not provided. + with mock.patch.object(auth, "default") as adc: + adc.return_value = (credentials.AnonymousCredentials(), None) + transport_class() + adc.assert_called_once() + + def test_transport_grpc_default(): # A client should use the gRPC transport by default. client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), ) assert isinstance( - client._transport, transports.GameServerClustersServiceGrpcTransport, + client.transport, transports.GameServerClustersServiceGrpcTransport, ) @@ -2233,6 +2406,17 @@ def test_game_server_clusters_service_base_transport_with_credentials_file(): ) +def test_game_server_clusters_service_base_transport_with_adc(): + # Test the default credentials are used if credentials and credentials_file are None. + with mock.patch.object(auth, "default") as adc, mock.patch( + "google.cloud.gaming_v1.services.game_server_clusters_service.transports.GameServerClustersServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (credentials.AnonymousCredentials(), None) + transport = transports.GameServerClustersServiceTransport() + adc.assert_called_once() + + def test_game_server_clusters_service_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(auth, "default") as adc: @@ -2265,7 +2449,7 @@ def test_game_server_clusters_service_host_no_port(): api_endpoint="gameservices.googleapis.com" ), ) - assert client._transport._host == "gameservices.googleapis.com:443" + assert client.transport._host == "gameservices.googleapis.com:443" def test_game_server_clusters_service_host_with_port(): @@ -2275,192 +2459,126 @@ def test_game_server_clusters_service_host_with_port(): api_endpoint="gameservices.googleapis.com:8000" ), ) - assert client._transport._host == "gameservices.googleapis.com:8000" + assert client.transport._host == "gameservices.googleapis.com:8000" def test_game_server_clusters_service_grpc_transport_channel(): channel = grpc.insecure_channel("http://localhost/") - # Check that if channel is provided, mtls endpoint and client_cert_source - # won't be used. - callback = mock.MagicMock() + # Check that channel is used if provided. transport = transports.GameServerClustersServiceGrpcTransport( - host="squid.clam.whelk", - channel=channel, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=callback, + host="squid.clam.whelk", channel=channel, ) assert transport.grpc_channel == channel assert transport._host == "squid.clam.whelk:443" - assert not callback.called + assert transport._ssl_channel_credentials == None def test_game_server_clusters_service_grpc_asyncio_transport_channel(): channel = aio.insecure_channel("http://localhost/") - # Check that if channel is provided, mtls endpoint and client_cert_source - # won't be used. - callback = mock.MagicMock() + # Check that channel is used if provided. transport = transports.GameServerClustersServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - channel=channel, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=callback, + host="squid.clam.whelk", channel=channel, ) assert transport.grpc_channel == channel assert transport._host == "squid.clam.whelk:443" - assert not callback.called - - -@mock.patch("grpc.ssl_channel_credentials", autospec=True) -@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) -def test_game_server_clusters_service_grpc_transport_channel_mtls_with_client_cert_source( - grpc_create_channel, grpc_ssl_channel_cred -): - # Check that if channel is None, but api_mtls_endpoint and client_cert_source - # are provided, then a mTLS channel will be created. - mock_cred = mock.Mock() - - mock_ssl_cred = mock.Mock() - grpc_ssl_channel_cred.return_value = mock_ssl_cred - - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - transport = transports.GameServerClustersServiceGrpcTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=client_cert_source_callback, - ) - grpc_ssl_channel_cred.assert_called_once_with( - certificate_chain=b"cert bytes", private_key=b"key bytes" - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel - - -@mock.patch("grpc.ssl_channel_credentials", autospec=True) -@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) -def test_game_server_clusters_service_grpc_asyncio_transport_channel_mtls_with_client_cert_source( - grpc_create_channel, grpc_ssl_channel_cred -): - # Check that if channel is None, but api_mtls_endpoint and client_cert_source - # are provided, then a mTLS channel will be created. - mock_cred = mock.Mock() - - mock_ssl_cred = mock.Mock() - grpc_ssl_channel_cred.return_value = mock_ssl_cred - - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - transport = transports.GameServerClustersServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=client_cert_source_callback, - ) - grpc_ssl_channel_cred.assert_called_once_with( - certificate_chain=b"cert bytes", private_key=b"key bytes" - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == None @pytest.mark.parametrize( - "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] + "transport_class", + [ + transports.GameServerClustersServiceGrpcTransport, + transports.GameServerClustersServiceGrpcAsyncIOTransport, + ], ) -@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) -def test_game_server_clusters_service_grpc_transport_channel_mtls_with_adc( - grpc_create_channel, api_mtls_endpoint +def test_game_server_clusters_service_transport_channel_mtls_with_client_cert_source( + transport_class, ): - # Check that if channel and client_cert_source are None, but api_mtls_endpoint - # is provided, then a mTLS channel will be created with SSL ADC. - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - # Mock google.auth.transport.grpc.SslCredentials class. - mock_ssl_cred = mock.Mock() - with mock.patch.multiple( - "google.auth.transport.grpc.SslCredentials", - __init__=mock.Mock(return_value=None), - ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), - ): - mock_cred = mock.Mock() - transport = transports.GameServerClustersServiceGrpcTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint=api_mtls_endpoint, - client_cert_source=None, - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + with mock.patch( + "grpc.ssl_channel_credentials", autospec=True + ) as grpc_ssl_channel_cred: + with mock.patch.object( + transport_class, "create_channel", autospec=True + ) as grpc_create_channel: + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + cred = credentials.AnonymousCredentials() + with pytest.warns(DeprecationWarning): + with mock.patch.object(auth, "default") as adc: + adc.return_value = (cred, None) + transport = transport_class( + host="squid.clam.whelk", + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + adc.assert_called_once() + + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + ) + assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == mock_ssl_cred @pytest.mark.parametrize( - "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] + "transport_class", + [ + transports.GameServerClustersServiceGrpcTransport, + transports.GameServerClustersServiceGrpcAsyncIOTransport, + ], ) -@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) -def test_game_server_clusters_service_grpc_asyncio_transport_channel_mtls_with_adc( - grpc_create_channel, api_mtls_endpoint -): - # Check that if channel and client_cert_source are None, but api_mtls_endpoint - # is provided, then a mTLS channel will be created with SSL ADC. - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - # Mock google.auth.transport.grpc.SslCredentials class. +def test_game_server_clusters_service_transport_channel_mtls_with_adc(transport_class): mock_ssl_cred = mock.Mock() with mock.patch.multiple( "google.auth.transport.grpc.SslCredentials", __init__=mock.Mock(return_value=None), ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), ): - mock_cred = mock.Mock() - transport = transports.GameServerClustersServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint=api_mtls_endpoint, - client_cert_source=None, - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + with mock.patch.object( + transport_class, "create_channel", autospec=True + ) as grpc_create_channel: + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + mock_cred = mock.Mock() + + with pytest.warns(DeprecationWarning): + transport = transport_class( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=None, + ) + + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + ) + assert transport.grpc_channel == mock_grpc_channel def test_game_server_clusters_service_grpc_lro_client(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), transport="grpc", ) - transport = client._transport + transport = client.transport # Ensure that we have a api-core operations client. assert isinstance(transport.operations_client, operations_v1.OperationsClient,) @@ -2473,7 +2591,7 @@ def test_game_server_clusters_service_grpc_lro_async_client(): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport="grpc_asyncio", ) - transport = client._client._transport + transport = client.transport # Ensure that we have a api-core operations client. assert isinstance(transport.operations_client, operations_v1.OperationsAsyncClient,) @@ -2509,3 +2627,127 @@ def test_parse_game_server_cluster_path(): # Check that the path construction is reversible. actual = GameServerClustersServiceClient.parse_game_server_cluster_path(path) assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "winkle" + + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = GameServerClustersServiceClient.common_billing_account_path( + billing_account + ) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "nautilus", + } + path = GameServerClustersServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerClustersServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "scallop" + + expected = "folders/{folder}".format(folder=folder,) + actual = GameServerClustersServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "abalone", + } + path = GameServerClustersServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerClustersServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "squid" + + expected = "organizations/{organization}".format(organization=organization,) + actual = GameServerClustersServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "clam", + } + path = GameServerClustersServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerClustersServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "whelk" + + expected = "projects/{project}".format(project=project,) + actual = GameServerClustersServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "octopus", + } + path = GameServerClustersServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerClustersServiceClient.parse_common_project_path(path) + assert expected == actual + + +def test_common_location_path(): + project = "oyster" + location = "nudibranch" + + expected = "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + actual = GameServerClustersServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "cuttlefish", + "location": "mussel", + } + path = GameServerClustersServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerClustersServiceClient.parse_common_location_path(path) + assert expected == actual + + +def test_client_withDEFAULT_CLIENT_INFO(): + client_info = gapic_v1.client_info.ClientInfo() + + with mock.patch.object( + transports.GameServerClustersServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = GameServerClustersServiceClient( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.GameServerClustersServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = GameServerClustersServiceClient.get_transport_class() + transport = transport_class( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) diff --git a/tests/unit/gapic/gaming_v1/test_game_server_configs_service.py b/tests/unit/gapic/gaming_v1/test_game_server_configs_service.py index 4e209ace..6aa4c939 100644 --- a/tests/unit/gapic/gaming_v1/test_game_server_configs_service.py +++ b/tests/unit/gapic/gaming_v1/test_game_server_configs_service.py @@ -31,7 +31,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async -from google.api_core import operation_async +from google.api_core import operation_async # type: ignore from google.api_core import operations_v1 from google.auth import credentials from google.auth.exceptions import MutualTLSChannelError @@ -107,12 +107,12 @@ def test_game_server_configs_service_client_from_service_account_file(client_cla ) as factory: factory.return_value = creds client = client_class.from_service_account_file("dummy/file/path.json") - assert client._transport._credentials == creds + assert client.transport._credentials == creds client = client_class.from_service_account_json("dummy/file/path.json") - assert client._transport._credentials == creds + assert client.transport._credentials == creds - assert client._transport._host == "gameservices.googleapis.com:443" + assert client.transport._host == "gameservices.googleapis.com:443" def test_game_server_configs_service_client_get_transport_class(): @@ -176,14 +176,14 @@ def test_game_server_configs_service_client_client_options( credentials_file=None, host="squid.clam.whelk", scopes=None, - api_mtls_endpoint="squid.clam.whelk", - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is # "never". - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "never"}): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None client = client_class() @@ -192,14 +192,14 @@ def test_game_server_configs_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is # "always". - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "always"}): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None client = client_class() @@ -208,90 +208,185 @@ def test_game_server_configs_service_client_client_options( credentials_file=None, host=client.DEFAULT_MTLS_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", and client_cert_source is provided. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError): + client = client_class() + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError): + client = client_class() + + # Check the case quota_project_id is provided + options = client_options.ClientOptions(quota_project_id="octopus") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + ssl_channel_credentials=None, + quota_project_id="octopus", + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,use_client_cert_env", + [ + ( + GameServerConfigsServiceClient, + transports.GameServerConfigsServiceGrpcTransport, + "grpc", + "true", + ), + ( + GameServerConfigsServiceAsyncClient, + transports.GameServerConfigsServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + ( + GameServerConfigsServiceClient, + transports.GameServerConfigsServiceGrpcTransport, + "grpc", + "false", + ), + ( + GameServerConfigsServiceAsyncClient, + transports.GameServerConfigsServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ], +) +@mock.patch.object( + GameServerConfigsServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GameServerConfigsServiceClient), +) +@mock.patch.object( + GameServerConfigsServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GameServerConfigsServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_game_server_configs_service_client_mtls_env_auto( + client_class, transport_class, transport_name, use_client_cert_env +): + # This tests the endpoint autoswitch behavior. Endpoint is autoswitched to the default + # mtls endpoint, if GOOGLE_API_USE_CLIENT_CERTIFICATE is "true" and client cert exists. + + # Check the case client_cert_source is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): options = client_options.ClientOptions( client_cert_source=client_cert_source_callback ) with mock.patch.object(transport_class, "__init__") as patched: - patched.return_value = None - client = client_class(client_options=options) - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_MTLS_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=client_cert_source_callback, - quota_project_id=None, - ) - - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", and default_client_cert_source is provided. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): - with mock.patch.object(transport_class, "__init__") as patched: + ssl_channel_creds = mock.Mock() with mock.patch( - "google.auth.transport.mtls.has_default_client_cert_source", - return_value=True, + "grpc.ssl_channel_credentials", return_value=ssl_channel_creds ): patched.return_value = None - client = client_class() + 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 + patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_MTLS_ENDPOINT, + host=expected_host, scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=expected_ssl_channel_creds, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", but client_cert_source and default_client_cert_source are None. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): + # Check the case ADC client cert is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + 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, + "google.auth.transport.grpc.SslCredentials.__init__", return_value=None ): - patched.return_value = None - client = client_class() - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, - quota_project_id=None, - ) - - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS has - # unsupported value. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "Unsupported"}): - with pytest.raises(MutualTLSChannelError): - client = client_class() - - # Check the case quota_project_id is provided - options = client_options.ClientOptions(quota_project_id="octopus") - with mock.patch.object(transport_class, "__init__") as patched: - patched.return_value = None - client = client_class(client_options=options) - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, - quota_project_id="octopus", - ) + 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, + ) + + # 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, + scopes=None, + ssl_channel_credentials=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) @pytest.mark.parametrize( @@ -322,9 +417,9 @@ def test_game_server_configs_service_client_client_options_scopes( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=["1", "2"], - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -356,9 +451,9 @@ def test_game_server_configs_service_client_client_options_credentials_file( credentials_file="credentials.json", host=client.DEFAULT_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -375,9 +470,9 @@ def test_game_server_configs_service_client_client_options_from_dict(): credentials_file=None, host="squid.clam.whelk", scopes=None, - api_mtls_endpoint="squid.clam.whelk", - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -395,7 +490,7 @@ def test_list_game_server_configs( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_configs), "__call__" + type(client.transport.list_game_server_configs), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_configs.ListGameServerConfigsResponse( @@ -411,6 +506,7 @@ def test_list_game_server_configs( assert args[0] == game_server_configs.ListGameServerConfigsRequest() # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListGameServerConfigsPager) assert response.next_page_token == "next_page_token_value" @@ -423,18 +519,21 @@ def test_list_game_server_configs_from_dict(): @pytest.mark.asyncio -async def test_list_game_server_configs_async(transport: str = "grpc_asyncio"): +async def test_list_game_server_configs_async( + transport: str = "grpc_asyncio", + request_type=game_server_configs.ListGameServerConfigsRequest, +): client = GameServerConfigsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_configs.ListGameServerConfigsRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_configs), "__call__" + type(client.transport.list_game_server_configs), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -450,7 +549,7 @@ async def test_list_game_server_configs_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_configs.ListGameServerConfigsRequest() # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListGameServerConfigsAsyncPager) @@ -460,6 +559,11 @@ async def test_list_game_server_configs_async(transport: str = "grpc_asyncio"): assert response.unreachable == ["unreachable_value"] +@pytest.mark.asyncio +async def test_list_game_server_configs_async_from_dict(): + await test_list_game_server_configs_async(request_type=dict) + + def test_list_game_server_configs_field_headers(): client = GameServerConfigsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -472,7 +576,7 @@ def test_list_game_server_configs_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_configs), "__call__" + type(client.transport.list_game_server_configs), "__call__" ) as call: call.return_value = game_server_configs.ListGameServerConfigsResponse() @@ -501,7 +605,7 @@ async def test_list_game_server_configs_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_configs), "__call__" + type(client.transport.list_game_server_configs), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_configs.ListGameServerConfigsResponse() @@ -526,7 +630,7 @@ def test_list_game_server_configs_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_configs), "__call__" + type(client.transport.list_game_server_configs), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_configs.ListGameServerConfigsResponse() @@ -564,7 +668,7 @@ async def test_list_game_server_configs_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_configs), "__call__" + type(client.transport.list_game_server_configs), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_configs.ListGameServerConfigsResponse() @@ -605,7 +709,7 @@ def test_list_game_server_configs_pager(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_configs), "__call__" + type(client.transport.list_game_server_configs), "__call__" ) as call: # Set the response to a series of pages. call.side_effect = ( @@ -653,7 +757,7 @@ def test_list_game_server_configs_pages(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_configs), "__call__" + type(client.transport.list_game_server_configs), "__call__" ) as call: # Set the response to a series of pages. call.side_effect = ( @@ -681,8 +785,8 @@ def test_list_game_server_configs_pages(): RuntimeError, ) pages = list(client.list_game_server_configs(request={}).pages) - for page, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page.raw_page.next_page_token == token + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token @pytest.mark.asyncio @@ -693,7 +797,7 @@ async def test_list_game_server_configs_async_pager(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_configs), + type(client.transport.list_game_server_configs), "__call__", new_callable=mock.AsyncMock, ) as call: @@ -742,7 +846,7 @@ async def test_list_game_server_configs_async_pages(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_configs), + type(client.transport.list_game_server_configs), "__call__", new_callable=mock.AsyncMock, ) as call: @@ -772,10 +876,10 @@ async def test_list_game_server_configs_async_pages(): RuntimeError, ) pages = [] - async for page in (await client.list_game_server_configs(request={})).pages: - pages.append(page) - for page, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page.raw_page.next_page_token == token + async for page_ in (await client.list_game_server_configs(request={})).pages: + pages.append(page_) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token def test_get_game_server_config( @@ -791,7 +895,7 @@ def test_get_game_server_config( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_config), "__call__" + type(client.transport.get_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_configs.GameServerConfig( @@ -807,6 +911,7 @@ def test_get_game_server_config( assert args[0] == game_server_configs.GetGameServerConfigRequest() # Establish that the response is the type that we expect. + assert isinstance(response, game_server_configs.GameServerConfig) assert response.name == "name_value" @@ -819,18 +924,21 @@ def test_get_game_server_config_from_dict(): @pytest.mark.asyncio -async def test_get_game_server_config_async(transport: str = "grpc_asyncio"): +async def test_get_game_server_config_async( + transport: str = "grpc_asyncio", + request_type=game_server_configs.GetGameServerConfigRequest, +): client = GameServerConfigsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_configs.GetGameServerConfigRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_config), "__call__" + type(client.transport.get_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -845,7 +953,7 @@ async def test_get_game_server_config_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_configs.GetGameServerConfigRequest() # Establish that the response is the type that we expect. assert isinstance(response, game_server_configs.GameServerConfig) @@ -855,6 +963,11 @@ async def test_get_game_server_config_async(transport: str = "grpc_asyncio"): assert response.description == "description_value" +@pytest.mark.asyncio +async def test_get_game_server_config_async_from_dict(): + await test_get_game_server_config_async(request_type=dict) + + def test_get_game_server_config_field_headers(): client = GameServerConfigsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -867,7 +980,7 @@ def test_get_game_server_config_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_config), "__call__" + type(client.transport.get_game_server_config), "__call__" ) as call: call.return_value = game_server_configs.GameServerConfig() @@ -896,7 +1009,7 @@ async def test_get_game_server_config_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_config), "__call__" + type(client.transport.get_game_server_config), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_configs.GameServerConfig() @@ -921,7 +1034,7 @@ def test_get_game_server_config_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_config), "__call__" + type(client.transport.get_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_configs.GameServerConfig() @@ -959,7 +1072,7 @@ async def test_get_game_server_config_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_config), "__call__" + type(client.transport.get_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_configs.GameServerConfig() @@ -1007,7 +1120,7 @@ def test_create_game_server_config( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_config), "__call__" + type(client.transport.create_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1029,18 +1142,21 @@ def test_create_game_server_config_from_dict(): @pytest.mark.asyncio -async def test_create_game_server_config_async(transport: str = "grpc_asyncio"): +async def test_create_game_server_config_async( + transport: str = "grpc_asyncio", + request_type=game_server_configs.CreateGameServerConfigRequest, +): client = GameServerConfigsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_configs.CreateGameServerConfigRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_config), "__call__" + type(client.transport.create_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1053,12 +1169,17 @@ async def test_create_game_server_config_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_configs.CreateGameServerConfigRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_create_game_server_config_async_from_dict(): + await test_create_game_server_config_async(request_type=dict) + + def test_create_game_server_config_field_headers(): client = GameServerConfigsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1071,7 +1192,7 @@ def test_create_game_server_config_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_config), "__call__" + type(client.transport.create_game_server_config), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -1100,7 +1221,7 @@ async def test_create_game_server_config_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_config), "__call__" + type(client.transport.create_game_server_config), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -1125,7 +1246,7 @@ def test_create_game_server_config_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_config), "__call__" + type(client.transport.create_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1172,7 +1293,7 @@ async def test_create_game_server_config_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_config), "__call__" + type(client.transport.create_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1229,7 +1350,7 @@ def test_delete_game_server_config( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_config), "__call__" + type(client.transport.delete_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1251,18 +1372,21 @@ def test_delete_game_server_config_from_dict(): @pytest.mark.asyncio -async def test_delete_game_server_config_async(transport: str = "grpc_asyncio"): +async def test_delete_game_server_config_async( + transport: str = "grpc_asyncio", + request_type=game_server_configs.DeleteGameServerConfigRequest, +): client = GameServerConfigsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_configs.DeleteGameServerConfigRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_config), "__call__" + type(client.transport.delete_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1275,12 +1399,17 @@ async def test_delete_game_server_config_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_configs.DeleteGameServerConfigRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_delete_game_server_config_async_from_dict(): + await test_delete_game_server_config_async(request_type=dict) + + def test_delete_game_server_config_field_headers(): client = GameServerConfigsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1293,7 +1422,7 @@ def test_delete_game_server_config_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_config), "__call__" + type(client.transport.delete_game_server_config), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -1322,7 +1451,7 @@ async def test_delete_game_server_config_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_config), "__call__" + type(client.transport.delete_game_server_config), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -1347,7 +1476,7 @@ def test_delete_game_server_config_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_config), "__call__" + type(client.transport.delete_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1385,7 +1514,7 @@ async def test_delete_game_server_config_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_config), "__call__" + type(client.transport.delete_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1455,7 +1584,7 @@ def test_transport_instance(): credentials=credentials.AnonymousCredentials(), ) client = GameServerConfigsServiceClient(transport=transport) - assert client._transport is transport + assert client.transport is transport def test_transport_get_channel(): @@ -1473,13 +1602,28 @@ def test_transport_get_channel(): assert channel +@pytest.mark.parametrize( + "transport_class", + [ + transports.GameServerConfigsServiceGrpcTransport, + transports.GameServerConfigsServiceGrpcAsyncIOTransport, + ], +) +def test_transport_adc(transport_class): + # Test default credentials are used if not provided. + with mock.patch.object(auth, "default") as adc: + adc.return_value = (credentials.AnonymousCredentials(), None) + transport_class() + adc.assert_called_once() + + def test_transport_grpc_default(): # A client should use the gRPC transport by default. client = GameServerConfigsServiceClient( credentials=credentials.AnonymousCredentials(), ) assert isinstance( - client._transport, transports.GameServerConfigsServiceGrpcTransport, + client.transport, transports.GameServerConfigsServiceGrpcTransport, ) @@ -1539,6 +1683,17 @@ def test_game_server_configs_service_base_transport_with_credentials_file(): ) +def test_game_server_configs_service_base_transport_with_adc(): + # Test the default credentials are used if credentials and credentials_file are None. + with mock.patch.object(auth, "default") as adc, mock.patch( + "google.cloud.gaming_v1.services.game_server_configs_service.transports.GameServerConfigsServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (credentials.AnonymousCredentials(), None) + transport = transports.GameServerConfigsServiceTransport() + adc.assert_called_once() + + def test_game_server_configs_service_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(auth, "default") as adc: @@ -1571,7 +1726,7 @@ def test_game_server_configs_service_host_no_port(): api_endpoint="gameservices.googleapis.com" ), ) - assert client._transport._host == "gameservices.googleapis.com:443" + assert client.transport._host == "gameservices.googleapis.com:443" def test_game_server_configs_service_host_with_port(): @@ -1581,192 +1736,126 @@ def test_game_server_configs_service_host_with_port(): api_endpoint="gameservices.googleapis.com:8000" ), ) - assert client._transport._host == "gameservices.googleapis.com:8000" + assert client.transport._host == "gameservices.googleapis.com:8000" def test_game_server_configs_service_grpc_transport_channel(): channel = grpc.insecure_channel("http://localhost/") - # Check that if channel is provided, mtls endpoint and client_cert_source - # won't be used. - callback = mock.MagicMock() + # Check that channel is used if provided. transport = transports.GameServerConfigsServiceGrpcTransport( - host="squid.clam.whelk", - channel=channel, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=callback, + host="squid.clam.whelk", channel=channel, ) assert transport.grpc_channel == channel assert transport._host == "squid.clam.whelk:443" - assert not callback.called + assert transport._ssl_channel_credentials == None def test_game_server_configs_service_grpc_asyncio_transport_channel(): channel = aio.insecure_channel("http://localhost/") - # Check that if channel is provided, mtls endpoint and client_cert_source - # won't be used. - callback = mock.MagicMock() + # Check that channel is used if provided. transport = transports.GameServerConfigsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - channel=channel, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=callback, + host="squid.clam.whelk", channel=channel, ) assert transport.grpc_channel == channel assert transport._host == "squid.clam.whelk:443" - assert not callback.called - - -@mock.patch("grpc.ssl_channel_credentials", autospec=True) -@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) -def test_game_server_configs_service_grpc_transport_channel_mtls_with_client_cert_source( - grpc_create_channel, grpc_ssl_channel_cred -): - # Check that if channel is None, but api_mtls_endpoint and client_cert_source - # are provided, then a mTLS channel will be created. - mock_cred = mock.Mock() - - mock_ssl_cred = mock.Mock() - grpc_ssl_channel_cred.return_value = mock_ssl_cred - - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - transport = transports.GameServerConfigsServiceGrpcTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=client_cert_source_callback, - ) - grpc_ssl_channel_cred.assert_called_once_with( - certificate_chain=b"cert bytes", private_key=b"key bytes" - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel - - -@mock.patch("grpc.ssl_channel_credentials", autospec=True) -@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) -def test_game_server_configs_service_grpc_asyncio_transport_channel_mtls_with_client_cert_source( - grpc_create_channel, grpc_ssl_channel_cred -): - # Check that if channel is None, but api_mtls_endpoint and client_cert_source - # are provided, then a mTLS channel will be created. - mock_cred = mock.Mock() - - mock_ssl_cred = mock.Mock() - grpc_ssl_channel_cred.return_value = mock_ssl_cred - - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - transport = transports.GameServerConfigsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=client_cert_source_callback, - ) - grpc_ssl_channel_cred.assert_called_once_with( - certificate_chain=b"cert bytes", private_key=b"key bytes" - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == None @pytest.mark.parametrize( - "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] + "transport_class", + [ + transports.GameServerConfigsServiceGrpcTransport, + transports.GameServerConfigsServiceGrpcAsyncIOTransport, + ], ) -@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) -def test_game_server_configs_service_grpc_transport_channel_mtls_with_adc( - grpc_create_channel, api_mtls_endpoint +def test_game_server_configs_service_transport_channel_mtls_with_client_cert_source( + transport_class, ): - # Check that if channel and client_cert_source are None, but api_mtls_endpoint - # is provided, then a mTLS channel will be created with SSL ADC. - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - # Mock google.auth.transport.grpc.SslCredentials class. - mock_ssl_cred = mock.Mock() - with mock.patch.multiple( - "google.auth.transport.grpc.SslCredentials", - __init__=mock.Mock(return_value=None), - ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), - ): - mock_cred = mock.Mock() - transport = transports.GameServerConfigsServiceGrpcTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint=api_mtls_endpoint, - client_cert_source=None, - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + with mock.patch( + "grpc.ssl_channel_credentials", autospec=True + ) as grpc_ssl_channel_cred: + with mock.patch.object( + transport_class, "create_channel", autospec=True + ) as grpc_create_channel: + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + cred = credentials.AnonymousCredentials() + with pytest.warns(DeprecationWarning): + with mock.patch.object(auth, "default") as adc: + adc.return_value = (cred, None) + transport = transport_class( + host="squid.clam.whelk", + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + adc.assert_called_once() + + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + ) + assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == mock_ssl_cred @pytest.mark.parametrize( - "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] + "transport_class", + [ + transports.GameServerConfigsServiceGrpcTransport, + transports.GameServerConfigsServiceGrpcAsyncIOTransport, + ], ) -@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) -def test_game_server_configs_service_grpc_asyncio_transport_channel_mtls_with_adc( - grpc_create_channel, api_mtls_endpoint -): - # Check that if channel and client_cert_source are None, but api_mtls_endpoint - # is provided, then a mTLS channel will be created with SSL ADC. - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - # Mock google.auth.transport.grpc.SslCredentials class. +def test_game_server_configs_service_transport_channel_mtls_with_adc(transport_class): mock_ssl_cred = mock.Mock() with mock.patch.multiple( "google.auth.transport.grpc.SslCredentials", __init__=mock.Mock(return_value=None), ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), ): - mock_cred = mock.Mock() - transport = transports.GameServerConfigsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint=api_mtls_endpoint, - client_cert_source=None, - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + with mock.patch.object( + transport_class, "create_channel", autospec=True + ) as grpc_create_channel: + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + mock_cred = mock.Mock() + + with pytest.warns(DeprecationWarning): + transport = transport_class( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=None, + ) + + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + ) + assert transport.grpc_channel == mock_grpc_channel def test_game_server_configs_service_grpc_lro_client(): client = GameServerConfigsServiceClient( credentials=credentials.AnonymousCredentials(), transport="grpc", ) - transport = client._transport + transport = client.transport # Ensure that we have a api-core operations client. assert isinstance(transport.operations_client, operations_v1.OperationsClient,) @@ -1779,7 +1868,7 @@ def test_game_server_configs_service_grpc_lro_async_client(): client = GameServerConfigsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport="grpc_asyncio", ) - transport = client._client._transport + transport = client.transport # Ensure that we have a api-core operations client. assert isinstance(transport.operations_client, operations_v1.OperationsAsyncClient,) @@ -1815,3 +1904,125 @@ def test_parse_game_server_config_path(): # Check that the path construction is reversible. actual = GameServerConfigsServiceClient.parse_game_server_config_path(path) assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "winkle" + + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = GameServerConfigsServiceClient.common_billing_account_path(billing_account) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "nautilus", + } + path = GameServerConfigsServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerConfigsServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "scallop" + + expected = "folders/{folder}".format(folder=folder,) + actual = GameServerConfigsServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "abalone", + } + path = GameServerConfigsServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerConfigsServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "squid" + + expected = "organizations/{organization}".format(organization=organization,) + actual = GameServerConfigsServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "clam", + } + path = GameServerConfigsServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerConfigsServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "whelk" + + expected = "projects/{project}".format(project=project,) + actual = GameServerConfigsServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "octopus", + } + path = GameServerConfigsServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerConfigsServiceClient.parse_common_project_path(path) + assert expected == actual + + +def test_common_location_path(): + project = "oyster" + location = "nudibranch" + + expected = "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + actual = GameServerConfigsServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "cuttlefish", + "location": "mussel", + } + path = GameServerConfigsServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerConfigsServiceClient.parse_common_location_path(path) + assert expected == actual + + +def test_client_withDEFAULT_CLIENT_INFO(): + client_info = gapic_v1.client_info.ClientInfo() + + with mock.patch.object( + transports.GameServerConfigsServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = GameServerConfigsServiceClient( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.GameServerConfigsServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = GameServerConfigsServiceClient.get_transport_class() + transport = transport_class( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) diff --git a/tests/unit/gapic/gaming_v1/test_game_server_deployments_service.py b/tests/unit/gapic/gaming_v1/test_game_server_deployments_service.py index de43fa13..a1a37442 100644 --- a/tests/unit/gapic/gaming_v1/test_game_server_deployments_service.py +++ b/tests/unit/gapic/gaming_v1/test_game_server_deployments_service.py @@ -31,7 +31,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async -from google.api_core import operation_async +from google.api_core import operation_async # type: ignore from google.api_core import operations_v1 from google.auth import credentials from google.auth.exceptions import MutualTLSChannelError @@ -109,12 +109,12 @@ def test_game_server_deployments_service_client_from_service_account_file(client ) as factory: factory.return_value = creds client = client_class.from_service_account_file("dummy/file/path.json") - assert client._transport._credentials == creds + assert client.transport._credentials == creds client = client_class.from_service_account_json("dummy/file/path.json") - assert client._transport._credentials == creds + assert client.transport._credentials == creds - assert client._transport._host == "gameservices.googleapis.com:443" + assert client.transport._host == "gameservices.googleapis.com:443" def test_game_server_deployments_service_client_get_transport_class(): @@ -178,14 +178,14 @@ def test_game_server_deployments_service_client_client_options( credentials_file=None, host="squid.clam.whelk", scopes=None, - api_mtls_endpoint="squid.clam.whelk", - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is # "never". - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "never"}): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None client = client_class() @@ -194,14 +194,14 @@ def test_game_server_deployments_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is # "always". - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "always"}): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None client = client_class() @@ -210,90 +210,185 @@ def test_game_server_deployments_service_client_client_options( credentials_file=None, host=client.DEFAULT_MTLS_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", and client_cert_source is provided. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError): + client = client_class() + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError): + client = client_class() + + # Check the case quota_project_id is provided + options = client_options.ClientOptions(quota_project_id="octopus") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + ssl_channel_credentials=None, + quota_project_id="octopus", + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,use_client_cert_env", + [ + ( + GameServerDeploymentsServiceClient, + transports.GameServerDeploymentsServiceGrpcTransport, + "grpc", + "true", + ), + ( + GameServerDeploymentsServiceAsyncClient, + transports.GameServerDeploymentsServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + ( + GameServerDeploymentsServiceClient, + transports.GameServerDeploymentsServiceGrpcTransport, + "grpc", + "false", + ), + ( + GameServerDeploymentsServiceAsyncClient, + transports.GameServerDeploymentsServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ], +) +@mock.patch.object( + GameServerDeploymentsServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GameServerDeploymentsServiceClient), +) +@mock.patch.object( + GameServerDeploymentsServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GameServerDeploymentsServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_game_server_deployments_service_client_mtls_env_auto( + client_class, transport_class, transport_name, use_client_cert_env +): + # This tests the endpoint autoswitch behavior. Endpoint is autoswitched to the default + # mtls endpoint, if GOOGLE_API_USE_CLIENT_CERTIFICATE is "true" and client cert exists. + + # Check the case client_cert_source is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): options = client_options.ClientOptions( client_cert_source=client_cert_source_callback ) with mock.patch.object(transport_class, "__init__") as patched: - patched.return_value = None - client = client_class(client_options=options) - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_MTLS_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=client_cert_source_callback, - quota_project_id=None, - ) - - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", and default_client_cert_source is provided. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): - with mock.patch.object(transport_class, "__init__") as patched: + ssl_channel_creds = mock.Mock() with mock.patch( - "google.auth.transport.mtls.has_default_client_cert_source", - return_value=True, + "grpc.ssl_channel_credentials", return_value=ssl_channel_creds ): patched.return_value = None - client = client_class() + 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 + patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_MTLS_ENDPOINT, + host=expected_host, scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=expected_ssl_channel_creds, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", but client_cert_source and default_client_cert_source are None. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): + # Check the case ADC client cert is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + 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, + "google.auth.transport.grpc.SslCredentials.__init__", return_value=None ): - patched.return_value = None - client = client_class() - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, - quota_project_id=None, - ) - - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS has - # unsupported value. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "Unsupported"}): - with pytest.raises(MutualTLSChannelError): - client = client_class() - - # Check the case quota_project_id is provided - options = client_options.ClientOptions(quota_project_id="octopus") - with mock.patch.object(transport_class, "__init__") as patched: - patched.return_value = None - client = client_class(client_options=options) - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, - quota_project_id="octopus", - ) + 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, + ) + + # 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, + scopes=None, + ssl_channel_credentials=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) @pytest.mark.parametrize( @@ -324,9 +419,9 @@ def test_game_server_deployments_service_client_client_options_scopes( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=["1", "2"], - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -358,9 +453,9 @@ def test_game_server_deployments_service_client_client_options_credentials_file( credentials_file="credentials.json", host=client.DEFAULT_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -377,9 +472,9 @@ def test_game_server_deployments_service_client_client_options_from_dict(): credentials_file=None, host="squid.clam.whelk", scopes=None, - api_mtls_endpoint="squid.clam.whelk", - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -397,7 +492,7 @@ def test_list_game_server_deployments( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_deployments), "__call__" + type(client.transport.list_game_server_deployments), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.ListGameServerDeploymentsResponse( @@ -413,6 +508,7 @@ def test_list_game_server_deployments( assert args[0] == game_server_deployments.ListGameServerDeploymentsRequest() # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListGameServerDeploymentsPager) assert response.next_page_token == "next_page_token_value" @@ -425,18 +521,21 @@ def test_list_game_server_deployments_from_dict(): @pytest.mark.asyncio -async def test_list_game_server_deployments_async(transport: str = "grpc_asyncio"): +async def test_list_game_server_deployments_async( + transport: str = "grpc_asyncio", + request_type=game_server_deployments.ListGameServerDeploymentsRequest, +): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.ListGameServerDeploymentsRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_deployments), "__call__" + type(client.transport.list_game_server_deployments), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -452,7 +551,7 @@ async def test_list_game_server_deployments_async(transport: str = "grpc_asyncio assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_deployments.ListGameServerDeploymentsRequest() # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListGameServerDeploymentsAsyncPager) @@ -462,6 +561,11 @@ async def test_list_game_server_deployments_async(transport: str = "grpc_asyncio assert response.unreachable == ["unreachable_value"] +@pytest.mark.asyncio +async def test_list_game_server_deployments_async_from_dict(): + await test_list_game_server_deployments_async(request_type=dict) + + def test_list_game_server_deployments_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -474,7 +578,7 @@ def test_list_game_server_deployments_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_deployments), "__call__" + type(client.transport.list_game_server_deployments), "__call__" ) as call: call.return_value = game_server_deployments.ListGameServerDeploymentsResponse() @@ -503,7 +607,7 @@ async def test_list_game_server_deployments_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_deployments), "__call__" + type(client.transport.list_game_server_deployments), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_deployments.ListGameServerDeploymentsResponse() @@ -528,7 +632,7 @@ def test_list_game_server_deployments_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_deployments), "__call__" + type(client.transport.list_game_server_deployments), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.ListGameServerDeploymentsResponse() @@ -567,7 +671,7 @@ async def test_list_game_server_deployments_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_deployments), "__call__" + type(client.transport.list_game_server_deployments), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.ListGameServerDeploymentsResponse() @@ -609,7 +713,7 @@ def test_list_game_server_deployments_pager(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_deployments), "__call__" + type(client.transport.list_game_server_deployments), "__call__" ) as call: # Set the response to a series of pages. call.side_effect = ( @@ -661,7 +765,7 @@ def test_list_game_server_deployments_pages(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_deployments), "__call__" + type(client.transport.list_game_server_deployments), "__call__" ) as call: # Set the response to a series of pages. call.side_effect = ( @@ -691,8 +795,8 @@ def test_list_game_server_deployments_pages(): RuntimeError, ) pages = list(client.list_game_server_deployments(request={}).pages) - for page, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page.raw_page.next_page_token == token + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token @pytest.mark.asyncio @@ -703,7 +807,7 @@ async def test_list_game_server_deployments_async_pager(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_deployments), + type(client.transport.list_game_server_deployments), "__call__", new_callable=mock.AsyncMock, ) as call: @@ -755,7 +859,7 @@ async def test_list_game_server_deployments_async_pages(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_deployments), + type(client.transport.list_game_server_deployments), "__call__", new_callable=mock.AsyncMock, ) as call: @@ -787,10 +891,12 @@ async def test_list_game_server_deployments_async_pages(): RuntimeError, ) pages = [] - async for page in (await client.list_game_server_deployments(request={})).pages: - pages.append(page) - for page, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page.raw_page.next_page_token == token + async for page_ in ( + await client.list_game_server_deployments(request={}) + ).pages: + pages.append(page_) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token def test_get_game_server_deployment( @@ -807,7 +913,7 @@ def test_get_game_server_deployment( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_deployment), "__call__" + type(client.transport.get_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.GameServerDeployment( @@ -823,6 +929,7 @@ def test_get_game_server_deployment( assert args[0] == game_server_deployments.GetGameServerDeploymentRequest() # Establish that the response is the type that we expect. + assert isinstance(response, game_server_deployments.GameServerDeployment) assert response.name == "name_value" @@ -837,18 +944,21 @@ def test_get_game_server_deployment_from_dict(): @pytest.mark.asyncio -async def test_get_game_server_deployment_async(transport: str = "grpc_asyncio"): +async def test_get_game_server_deployment_async( + transport: str = "grpc_asyncio", + request_type=game_server_deployments.GetGameServerDeploymentRequest, +): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.GetGameServerDeploymentRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_deployment), "__call__" + type(client.transport.get_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -863,7 +973,7 @@ async def test_get_game_server_deployment_async(transport: str = "grpc_asyncio") assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_deployments.GetGameServerDeploymentRequest() # Establish that the response is the type that we expect. assert isinstance(response, game_server_deployments.GameServerDeployment) @@ -875,6 +985,11 @@ async def test_get_game_server_deployment_async(transport: str = "grpc_asyncio") assert response.description == "description_value" +@pytest.mark.asyncio +async def test_get_game_server_deployment_async_from_dict(): + await test_get_game_server_deployment_async(request_type=dict) + + def test_get_game_server_deployment_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -887,7 +1002,7 @@ def test_get_game_server_deployment_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_deployment), "__call__" + type(client.transport.get_game_server_deployment), "__call__" ) as call: call.return_value = game_server_deployments.GameServerDeployment() @@ -916,7 +1031,7 @@ async def test_get_game_server_deployment_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_deployment), "__call__" + type(client.transport.get_game_server_deployment), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_deployments.GameServerDeployment() @@ -941,7 +1056,7 @@ def test_get_game_server_deployment_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_deployment), "__call__" + type(client.transport.get_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.GameServerDeployment() @@ -979,7 +1094,7 @@ async def test_get_game_server_deployment_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_deployment), "__call__" + type(client.transport.get_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.GameServerDeployment() @@ -1027,7 +1142,7 @@ def test_create_game_server_deployment( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_deployment), "__call__" + type(client.transport.create_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1049,18 +1164,21 @@ def test_create_game_server_deployment_from_dict(): @pytest.mark.asyncio -async def test_create_game_server_deployment_async(transport: str = "grpc_asyncio"): +async def test_create_game_server_deployment_async( + transport: str = "grpc_asyncio", + request_type=game_server_deployments.CreateGameServerDeploymentRequest, +): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.CreateGameServerDeploymentRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_deployment), "__call__" + type(client.transport.create_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1073,12 +1191,17 @@ async def test_create_game_server_deployment_async(transport: str = "grpc_asynci assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_deployments.CreateGameServerDeploymentRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_create_game_server_deployment_async_from_dict(): + await test_create_game_server_deployment_async(request_type=dict) + + def test_create_game_server_deployment_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1091,7 +1214,7 @@ def test_create_game_server_deployment_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_deployment), "__call__" + type(client.transport.create_game_server_deployment), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -1120,7 +1243,7 @@ async def test_create_game_server_deployment_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_deployment), "__call__" + type(client.transport.create_game_server_deployment), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -1145,7 +1268,7 @@ def test_create_game_server_deployment_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_deployment), "__call__" + type(client.transport.create_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1198,7 +1321,7 @@ async def test_create_game_server_deployment_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_deployment), "__call__" + type(client.transport.create_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1261,7 +1384,7 @@ def test_delete_game_server_deployment( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_deployment), "__call__" + type(client.transport.delete_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1283,18 +1406,21 @@ def test_delete_game_server_deployment_from_dict(): @pytest.mark.asyncio -async def test_delete_game_server_deployment_async(transport: str = "grpc_asyncio"): +async def test_delete_game_server_deployment_async( + transport: str = "grpc_asyncio", + request_type=game_server_deployments.DeleteGameServerDeploymentRequest, +): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.DeleteGameServerDeploymentRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_deployment), "__call__" + type(client.transport.delete_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1307,12 +1433,17 @@ async def test_delete_game_server_deployment_async(transport: str = "grpc_asynci assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_deployments.DeleteGameServerDeploymentRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_delete_game_server_deployment_async_from_dict(): + await test_delete_game_server_deployment_async(request_type=dict) + + def test_delete_game_server_deployment_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1325,7 +1456,7 @@ def test_delete_game_server_deployment_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_deployment), "__call__" + type(client.transport.delete_game_server_deployment), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -1354,7 +1485,7 @@ async def test_delete_game_server_deployment_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_deployment), "__call__" + type(client.transport.delete_game_server_deployment), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -1379,7 +1510,7 @@ def test_delete_game_server_deployment_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_deployment), "__call__" + type(client.transport.delete_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1418,7 +1549,7 @@ async def test_delete_game_server_deployment_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_deployment), "__call__" + type(client.transport.delete_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1467,7 +1598,7 @@ def test_update_game_server_deployment( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_deployment), "__call__" + type(client.transport.update_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1489,18 +1620,21 @@ def test_update_game_server_deployment_from_dict(): @pytest.mark.asyncio -async def test_update_game_server_deployment_async(transport: str = "grpc_asyncio"): +async def test_update_game_server_deployment_async( + transport: str = "grpc_asyncio", + request_type=game_server_deployments.UpdateGameServerDeploymentRequest, +): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.UpdateGameServerDeploymentRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_deployment), "__call__" + type(client.transport.update_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1513,12 +1647,17 @@ async def test_update_game_server_deployment_async(transport: str = "grpc_asynci assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_deployments.UpdateGameServerDeploymentRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_update_game_server_deployment_async_from_dict(): + await test_update_game_server_deployment_async(request_type=dict) + + def test_update_game_server_deployment_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1531,7 +1670,7 @@ def test_update_game_server_deployment_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_deployment), "__call__" + type(client.transport.update_game_server_deployment), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -1563,7 +1702,7 @@ async def test_update_game_server_deployment_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_deployment), "__call__" + type(client.transport.update_game_server_deployment), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -1591,7 +1730,7 @@ def test_update_game_server_deployment_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_deployment), "__call__" + type(client.transport.update_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1644,7 +1783,7 @@ async def test_update_game_server_deployment_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_deployment), "__call__" + type(client.transport.update_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1707,7 +1846,7 @@ def test_get_game_server_deployment_rollout( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_deployment_rollout), "__call__" + type(client.transport.get_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.GameServerDeploymentRollout( @@ -1727,6 +1866,7 @@ def test_get_game_server_deployment_rollout( ) # Establish that the response is the type that we expect. + assert isinstance(response, game_server_deployments.GameServerDeploymentRollout) assert response.name == "name_value" @@ -1743,6 +1883,7 @@ def test_get_game_server_deployment_rollout_from_dict(): @pytest.mark.asyncio async def test_get_game_server_deployment_rollout_async( transport: str = "grpc_asyncio", + request_type=game_server_deployments.GetGameServerDeploymentRolloutRequest, ): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, @@ -1750,11 +1891,11 @@ async def test_get_game_server_deployment_rollout_async( # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.GetGameServerDeploymentRolloutRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_deployment_rollout), "__call__" + type(client.transport.get_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1771,7 +1912,9 @@ async def test_get_game_server_deployment_rollout_async( assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert ( + args[0] == game_server_deployments.GetGameServerDeploymentRolloutRequest() + ) # Establish that the response is the type that we expect. assert isinstance(response, game_server_deployments.GameServerDeploymentRollout) @@ -1783,6 +1926,11 @@ async def test_get_game_server_deployment_rollout_async( assert response.etag == "etag_value" +@pytest.mark.asyncio +async def test_get_game_server_deployment_rollout_async_from_dict(): + await test_get_game_server_deployment_rollout_async(request_type=dict) + + def test_get_game_server_deployment_rollout_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1795,7 +1943,7 @@ def test_get_game_server_deployment_rollout_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_deployment_rollout), "__call__" + type(client.transport.get_game_server_deployment_rollout), "__call__" ) as call: call.return_value = game_server_deployments.GameServerDeploymentRollout() @@ -1824,7 +1972,7 @@ async def test_get_game_server_deployment_rollout_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_deployment_rollout), "__call__" + type(client.transport.get_game_server_deployment_rollout), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_deployments.GameServerDeploymentRollout() @@ -1849,7 +1997,7 @@ def test_get_game_server_deployment_rollout_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_deployment_rollout), "__call__" + type(client.transport.get_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.GameServerDeploymentRollout() @@ -1888,7 +2036,7 @@ async def test_get_game_server_deployment_rollout_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_deployment_rollout), "__call__" + type(client.transport.get_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.GameServerDeploymentRollout() @@ -1937,7 +2085,7 @@ def test_update_game_server_deployment_rollout( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_deployment_rollout), "__call__" + type(client.transport.update_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1964,6 +2112,7 @@ def test_update_game_server_deployment_rollout_from_dict(): @pytest.mark.asyncio async def test_update_game_server_deployment_rollout_async( transport: str = "grpc_asyncio", + request_type=game_server_deployments.UpdateGameServerDeploymentRolloutRequest, ): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, @@ -1971,12 +2120,11 @@ async def test_update_game_server_deployment_rollout_async( # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.UpdateGameServerDeploymentRolloutRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_deployment_rollout), - "__call__", + type(client.transport.update_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1989,12 +2137,20 @@ async def test_update_game_server_deployment_rollout_async( assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert ( + args[0] + == game_server_deployments.UpdateGameServerDeploymentRolloutRequest() + ) # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_update_game_server_deployment_rollout_async_from_dict(): + await test_update_game_server_deployment_rollout_async(request_type=dict) + + def test_update_game_server_deployment_rollout_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -2007,7 +2163,7 @@ def test_update_game_server_deployment_rollout_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_deployment_rollout), "__call__" + type(client.transport.update_game_server_deployment_rollout), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -2038,8 +2194,7 @@ async def test_update_game_server_deployment_rollout_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_deployment_rollout), - "__call__", + type(client.transport.update_game_server_deployment_rollout), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -2066,7 +2221,7 @@ def test_update_game_server_deployment_rollout_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_deployment_rollout), "__call__" + type(client.transport.update_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -2117,8 +2272,7 @@ async def test_update_game_server_deployment_rollout_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_deployment_rollout), - "__call__", + type(client.transport.update_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -2179,7 +2333,7 @@ def test_preview_game_server_deployment_rollout( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_game_server_deployment_rollout), "__call__" + type(client.transport.preview_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.PreviewGameServerDeploymentRolloutResponse( @@ -2198,6 +2352,7 @@ def test_preview_game_server_deployment_rollout( ) # Establish that the response is the type that we expect. + assert isinstance( response, game_server_deployments.PreviewGameServerDeploymentRolloutResponse ) @@ -2214,6 +2369,7 @@ def test_preview_game_server_deployment_rollout_from_dict(): @pytest.mark.asyncio async def test_preview_game_server_deployment_rollout_async( transport: str = "grpc_asyncio", + request_type=game_server_deployments.PreviewGameServerDeploymentRolloutRequest, ): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, @@ -2221,12 +2377,11 @@ async def test_preview_game_server_deployment_rollout_async( # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.PreviewGameServerDeploymentRolloutRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_game_server_deployment_rollout), - "__call__", + type(client.transport.preview_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -2241,7 +2396,10 @@ async def test_preview_game_server_deployment_rollout_async( assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert ( + args[0] + == game_server_deployments.PreviewGameServerDeploymentRolloutRequest() + ) # Establish that the response is the type that we expect. assert isinstance( @@ -2253,6 +2411,11 @@ async def test_preview_game_server_deployment_rollout_async( assert response.etag == "etag_value" +@pytest.mark.asyncio +async def test_preview_game_server_deployment_rollout_async_from_dict(): + await test_preview_game_server_deployment_rollout_async(request_type=dict) + + def test_preview_game_server_deployment_rollout_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -2265,7 +2428,7 @@ def test_preview_game_server_deployment_rollout_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_game_server_deployment_rollout), "__call__" + type(client.transport.preview_game_server_deployment_rollout), "__call__" ) as call: call.return_value = ( game_server_deployments.PreviewGameServerDeploymentRolloutResponse() @@ -2298,8 +2461,7 @@ async def test_preview_game_server_deployment_rollout_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_game_server_deployment_rollout), - "__call__", + type(client.transport.preview_game_server_deployment_rollout), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_deployments.PreviewGameServerDeploymentRolloutResponse() @@ -2333,7 +2495,7 @@ def test_fetch_deployment_state( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.fetch_deployment_state), "__call__" + type(client.transport.fetch_deployment_state), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.FetchDeploymentStateResponse( @@ -2349,6 +2511,7 @@ def test_fetch_deployment_state( assert args[0] == game_server_deployments.FetchDeploymentStateRequest() # Establish that the response is the type that we expect. + assert isinstance(response, game_server_deployments.FetchDeploymentStateResponse) assert response.unavailable == ["unavailable_value"] @@ -2359,18 +2522,21 @@ def test_fetch_deployment_state_from_dict(): @pytest.mark.asyncio -async def test_fetch_deployment_state_async(transport: str = "grpc_asyncio"): +async def test_fetch_deployment_state_async( + transport: str = "grpc_asyncio", + request_type=game_server_deployments.FetchDeploymentStateRequest, +): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.FetchDeploymentStateRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.fetch_deployment_state), "__call__" + type(client.transport.fetch_deployment_state), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -2385,7 +2551,7 @@ async def test_fetch_deployment_state_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_deployments.FetchDeploymentStateRequest() # Establish that the response is the type that we expect. assert isinstance(response, game_server_deployments.FetchDeploymentStateResponse) @@ -2393,6 +2559,11 @@ async def test_fetch_deployment_state_async(transport: str = "grpc_asyncio"): assert response.unavailable == ["unavailable_value"] +@pytest.mark.asyncio +async def test_fetch_deployment_state_async_from_dict(): + await test_fetch_deployment_state_async(request_type=dict) + + def test_fetch_deployment_state_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -2405,7 +2576,7 @@ def test_fetch_deployment_state_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.fetch_deployment_state), "__call__" + type(client.transport.fetch_deployment_state), "__call__" ) as call: call.return_value = game_server_deployments.FetchDeploymentStateResponse() @@ -2434,7 +2605,7 @@ async def test_fetch_deployment_state_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.fetch_deployment_state), "__call__" + type(client.transport.fetch_deployment_state), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_deployments.FetchDeploymentStateResponse() @@ -2488,7 +2659,7 @@ def test_transport_instance(): credentials=credentials.AnonymousCredentials(), ) client = GameServerDeploymentsServiceClient(transport=transport) - assert client._transport is transport + assert client.transport is transport def test_transport_get_channel(): @@ -2506,13 +2677,28 @@ def test_transport_get_channel(): assert channel +@pytest.mark.parametrize( + "transport_class", + [ + transports.GameServerDeploymentsServiceGrpcTransport, + transports.GameServerDeploymentsServiceGrpcAsyncIOTransport, + ], +) +def test_transport_adc(transport_class): + # Test default credentials are used if not provided. + with mock.patch.object(auth, "default") as adc: + adc.return_value = (credentials.AnonymousCredentials(), None) + transport_class() + adc.assert_called_once() + + def test_transport_grpc_default(): # A client should use the gRPC transport by default. client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), ) assert isinstance( - client._transport, transports.GameServerDeploymentsServiceGrpcTransport, + client.transport, transports.GameServerDeploymentsServiceGrpcTransport, ) @@ -2577,6 +2763,17 @@ def test_game_server_deployments_service_base_transport_with_credentials_file(): ) +def test_game_server_deployments_service_base_transport_with_adc(): + # Test the default credentials are used if credentials and credentials_file are None. + with mock.patch.object(auth, "default") as adc, mock.patch( + "google.cloud.gaming_v1.services.game_server_deployments_service.transports.GameServerDeploymentsServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (credentials.AnonymousCredentials(), None) + transport = transports.GameServerDeploymentsServiceTransport() + adc.assert_called_once() + + def test_game_server_deployments_service_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(auth, "default") as adc: @@ -2609,7 +2806,7 @@ def test_game_server_deployments_service_host_no_port(): api_endpoint="gameservices.googleapis.com" ), ) - assert client._transport._host == "gameservices.googleapis.com:443" + assert client.transport._host == "gameservices.googleapis.com:443" def test_game_server_deployments_service_host_with_port(): @@ -2619,192 +2816,128 @@ def test_game_server_deployments_service_host_with_port(): api_endpoint="gameservices.googleapis.com:8000" ), ) - assert client._transport._host == "gameservices.googleapis.com:8000" + assert client.transport._host == "gameservices.googleapis.com:8000" def test_game_server_deployments_service_grpc_transport_channel(): channel = grpc.insecure_channel("http://localhost/") - # Check that if channel is provided, mtls endpoint and client_cert_source - # won't be used. - callback = mock.MagicMock() + # Check that channel is used if provided. transport = transports.GameServerDeploymentsServiceGrpcTransport( - host="squid.clam.whelk", - channel=channel, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=callback, + host="squid.clam.whelk", channel=channel, ) assert transport.grpc_channel == channel assert transport._host == "squid.clam.whelk:443" - assert not callback.called + assert transport._ssl_channel_credentials == None def test_game_server_deployments_service_grpc_asyncio_transport_channel(): channel = aio.insecure_channel("http://localhost/") - # Check that if channel is provided, mtls endpoint and client_cert_source - # won't be used. - callback = mock.MagicMock() + # Check that channel is used if provided. transport = transports.GameServerDeploymentsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - channel=channel, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=callback, + host="squid.clam.whelk", channel=channel, ) assert transport.grpc_channel == channel assert transport._host == "squid.clam.whelk:443" - assert not callback.called - - -@mock.patch("grpc.ssl_channel_credentials", autospec=True) -@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) -def test_game_server_deployments_service_grpc_transport_channel_mtls_with_client_cert_source( - grpc_create_channel, grpc_ssl_channel_cred -): - # Check that if channel is None, but api_mtls_endpoint and client_cert_source - # are provided, then a mTLS channel will be created. - mock_cred = mock.Mock() - - mock_ssl_cred = mock.Mock() - grpc_ssl_channel_cred.return_value = mock_ssl_cred - - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - transport = transports.GameServerDeploymentsServiceGrpcTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=client_cert_source_callback, - ) - grpc_ssl_channel_cred.assert_called_once_with( - certificate_chain=b"cert bytes", private_key=b"key bytes" - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel - - -@mock.patch("grpc.ssl_channel_credentials", autospec=True) -@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) -def test_game_server_deployments_service_grpc_asyncio_transport_channel_mtls_with_client_cert_source( - grpc_create_channel, grpc_ssl_channel_cred -): - # Check that if channel is None, but api_mtls_endpoint and client_cert_source - # are provided, then a mTLS channel will be created. - mock_cred = mock.Mock() - - mock_ssl_cred = mock.Mock() - grpc_ssl_channel_cred.return_value = mock_ssl_cred - - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - transport = transports.GameServerDeploymentsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=client_cert_source_callback, - ) - grpc_ssl_channel_cred.assert_called_once_with( - certificate_chain=b"cert bytes", private_key=b"key bytes" - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == None @pytest.mark.parametrize( - "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] + "transport_class", + [ + transports.GameServerDeploymentsServiceGrpcTransport, + transports.GameServerDeploymentsServiceGrpcAsyncIOTransport, + ], ) -@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) -def test_game_server_deployments_service_grpc_transport_channel_mtls_with_adc( - grpc_create_channel, api_mtls_endpoint +def test_game_server_deployments_service_transport_channel_mtls_with_client_cert_source( + transport_class, ): - # Check that if channel and client_cert_source are None, but api_mtls_endpoint - # is provided, then a mTLS channel will be created with SSL ADC. - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - # Mock google.auth.transport.grpc.SslCredentials class. - mock_ssl_cred = mock.Mock() - with mock.patch.multiple( - "google.auth.transport.grpc.SslCredentials", - __init__=mock.Mock(return_value=None), - ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), - ): - mock_cred = mock.Mock() - transport = transports.GameServerDeploymentsServiceGrpcTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint=api_mtls_endpoint, - client_cert_source=None, - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + with mock.patch( + "grpc.ssl_channel_credentials", autospec=True + ) as grpc_ssl_channel_cred: + with mock.patch.object( + transport_class, "create_channel", autospec=True + ) as grpc_create_channel: + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + cred = credentials.AnonymousCredentials() + with pytest.warns(DeprecationWarning): + with mock.patch.object(auth, "default") as adc: + adc.return_value = (cred, None) + transport = transport_class( + host="squid.clam.whelk", + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + adc.assert_called_once() + + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + ) + assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == mock_ssl_cred @pytest.mark.parametrize( - "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] + "transport_class", + [ + transports.GameServerDeploymentsServiceGrpcTransport, + transports.GameServerDeploymentsServiceGrpcAsyncIOTransport, + ], ) -@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) -def test_game_server_deployments_service_grpc_asyncio_transport_channel_mtls_with_adc( - grpc_create_channel, api_mtls_endpoint +def test_game_server_deployments_service_transport_channel_mtls_with_adc( + transport_class, ): - # Check that if channel and client_cert_source are None, but api_mtls_endpoint - # is provided, then a mTLS channel will be created with SSL ADC. - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - # Mock google.auth.transport.grpc.SslCredentials class. mock_ssl_cred = mock.Mock() with mock.patch.multiple( "google.auth.transport.grpc.SslCredentials", __init__=mock.Mock(return_value=None), ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), ): - mock_cred = mock.Mock() - transport = transports.GameServerDeploymentsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint=api_mtls_endpoint, - client_cert_source=None, - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + with mock.patch.object( + transport_class, "create_channel", autospec=True + ) as grpc_create_channel: + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + mock_cred = mock.Mock() + + with pytest.warns(DeprecationWarning): + transport = transport_class( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=None, + ) + + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + ) + assert transport.grpc_channel == mock_grpc_channel def test_game_server_deployments_service_grpc_lro_client(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), transport="grpc", ) - transport = client._transport + transport = client.transport # Ensure that we have a api-core operations client. assert isinstance(transport.operations_client, operations_v1.OperationsClient,) @@ -2817,7 +2950,7 @@ def test_game_server_deployments_service_grpc_lro_async_client(): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport="grpc_asyncio", ) - transport = client._client._transport + transport = client.transport # Ensure that we have a api-core operations client. assert isinstance(transport.operations_client, operations_v1.OperationsAsyncClient,) @@ -2826,26 +2959,53 @@ def test_game_server_deployments_service_grpc_lro_async_client(): assert transport.operations_client is transport.operations_client -def test_game_server_deployment_rollout_path(): +def test_game_server_deployment_path(): project = "squid" location = "clam" deployment = "whelk" - expected = "projects/{project}/locations/{location}/gameServerDeployments/{deployment}/rollout".format( + expected = "projects/{project}/locations/{location}/gameServerDeployments/{deployment}".format( project=project, location=location, deployment=deployment, ) - actual = GameServerDeploymentsServiceClient.game_server_deployment_rollout_path( + actual = GameServerDeploymentsServiceClient.game_server_deployment_path( project, location, deployment ) assert expected == actual -def test_parse_game_server_deployment_rollout_path(): +def test_parse_game_server_deployment_path(): expected = { "project": "octopus", "location": "oyster", "deployment": "nudibranch", } + path = GameServerDeploymentsServiceClient.game_server_deployment_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerDeploymentsServiceClient.parse_game_server_deployment_path(path) + assert expected == actual + + +def test_game_server_deployment_rollout_path(): + project = "cuttlefish" + location = "mussel" + deployment = "winkle" + + expected = "projects/{project}/locations/{location}/gameServerDeployments/{deployment}/rollout".format( + project=project, location=location, deployment=deployment, + ) + actual = GameServerDeploymentsServiceClient.game_server_deployment_rollout_path( + project, location, deployment + ) + assert expected == actual + + +def test_parse_game_server_deployment_rollout_path(): + expected = { + "project": "nautilus", + "location": "scallop", + "deployment": "abalone", + } path = GameServerDeploymentsServiceClient.game_server_deployment_rollout_path( **expected ) @@ -2857,28 +3017,125 @@ def test_parse_game_server_deployment_rollout_path(): assert expected == actual -def test_game_server_deployment_path(): - project = "squid" - location = "clam" - deployment = "whelk" +def test_common_billing_account_path(): + billing_account = "squid" - expected = "projects/{project}/locations/{location}/gameServerDeployments/{deployment}".format( - project=project, location=location, deployment=deployment, + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, ) - actual = GameServerDeploymentsServiceClient.game_server_deployment_path( - project, location, deployment + actual = GameServerDeploymentsServiceClient.common_billing_account_path( + billing_account ) assert expected == actual -def test_parse_game_server_deployment_path(): +def test_parse_common_billing_account_path(): expected = { - "project": "octopus", - "location": "oyster", - "deployment": "nudibranch", + "billing_account": "clam", } - path = GameServerDeploymentsServiceClient.game_server_deployment_path(**expected) + path = GameServerDeploymentsServiceClient.common_billing_account_path(**expected) # Check that the path construction is reversible. - actual = GameServerDeploymentsServiceClient.parse_game_server_deployment_path(path) + actual = GameServerDeploymentsServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "whelk" + + expected = "folders/{folder}".format(folder=folder,) + actual = GameServerDeploymentsServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "octopus", + } + path = GameServerDeploymentsServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerDeploymentsServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "oyster" + + expected = "organizations/{organization}".format(organization=organization,) + actual = GameServerDeploymentsServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "nudibranch", + } + path = GameServerDeploymentsServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerDeploymentsServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "cuttlefish" + + expected = "projects/{project}".format(project=project,) + actual = GameServerDeploymentsServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "mussel", + } + path = GameServerDeploymentsServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerDeploymentsServiceClient.parse_common_project_path(path) + assert expected == actual + + +def test_common_location_path(): + project = "winkle" + location = "nautilus" + + expected = "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + actual = GameServerDeploymentsServiceClient.common_location_path(project, location) assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "scallop", + "location": "abalone", + } + path = GameServerDeploymentsServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerDeploymentsServiceClient.parse_common_location_path(path) + assert expected == actual + + +def test_client_withDEFAULT_CLIENT_INFO(): + client_info = gapic_v1.client_info.ClientInfo() + + with mock.patch.object( + transports.GameServerDeploymentsServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = GameServerDeploymentsServiceClient( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.GameServerDeploymentsServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = GameServerDeploymentsServiceClient.get_transport_class() + transport = transport_class( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) diff --git a/tests/unit/gapic/gaming_v1/test_realms_service.py b/tests/unit/gapic/gaming_v1/test_realms_service.py index 1b2a75c7..ca3d9632 100644 --- a/tests/unit/gapic/gaming_v1/test_realms_service.py +++ b/tests/unit/gapic/gaming_v1/test_realms_service.py @@ -31,7 +31,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async -from google.api_core import operation_async +from google.api_core import operation_async # type: ignore from google.api_core import operations_v1 from google.auth import credentials from google.auth.exceptions import MutualTLSChannelError @@ -101,12 +101,12 @@ def test_realms_service_client_from_service_account_file(client_class): ) as factory: factory.return_value = creds client = client_class.from_service_account_file("dummy/file/path.json") - assert client._transport._credentials == creds + assert client.transport._credentials == creds client = client_class.from_service_account_json("dummy/file/path.json") - assert client._transport._credentials == creds + assert client.transport._credentials == creds - assert client._transport._host == "gameservices.googleapis.com:443" + assert client.transport._host == "gameservices.googleapis.com:443" def test_realms_service_client_get_transport_class(): @@ -162,14 +162,14 @@ def test_realms_service_client_client_options( credentials_file=None, host="squid.clam.whelk", scopes=None, - api_mtls_endpoint="squid.clam.whelk", - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is # "never". - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "never"}): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None client = client_class() @@ -178,14 +178,14 @@ def test_realms_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is # "always". - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "always"}): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None client = client_class() @@ -194,90 +194,175 @@ def test_realms_service_client_client_options( credentials_file=None, host=client.DEFAULT_MTLS_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", and client_cert_source is provided. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError): + client = client_class() + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError): + client = client_class() + + # Check the case quota_project_id is provided + options = client_options.ClientOptions(quota_project_id="octopus") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + ssl_channel_credentials=None, + quota_project_id="octopus", + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,use_client_cert_env", + [ + (RealmsServiceClient, transports.RealmsServiceGrpcTransport, "grpc", "true"), + ( + RealmsServiceAsyncClient, + transports.RealmsServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + (RealmsServiceClient, transports.RealmsServiceGrpcTransport, "grpc", "false"), + ( + RealmsServiceAsyncClient, + transports.RealmsServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ], +) +@mock.patch.object( + RealmsServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(RealmsServiceClient), +) +@mock.patch.object( + RealmsServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(RealmsServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_realms_service_client_mtls_env_auto( + client_class, transport_class, transport_name, use_client_cert_env +): + # This tests the endpoint autoswitch behavior. Endpoint is autoswitched to the default + # mtls endpoint, if GOOGLE_API_USE_CLIENT_CERTIFICATE is "true" and client cert exists. + + # Check the case client_cert_source is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): options = client_options.ClientOptions( client_cert_source=client_cert_source_callback ) with mock.patch.object(transport_class, "__init__") as patched: - patched.return_value = None - client = client_class(client_options=options) - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_MTLS_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=client_cert_source_callback, - quota_project_id=None, - ) - - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", and default_client_cert_source is provided. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): - with mock.patch.object(transport_class, "__init__") as patched: + ssl_channel_creds = mock.Mock() with mock.patch( - "google.auth.transport.mtls.has_default_client_cert_source", - return_value=True, + "grpc.ssl_channel_credentials", return_value=ssl_channel_creds ): patched.return_value = None - client = client_class() + 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 + patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_MTLS_ENDPOINT, + host=expected_host, scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=expected_ssl_channel_creds, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", but client_cert_source and default_client_cert_source are None. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): + # Check the case ADC client cert is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + 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, + "google.auth.transport.grpc.SslCredentials.__init__", return_value=None ): - patched.return_value = None - client = client_class() - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, - quota_project_id=None, - ) - - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS has - # unsupported value. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "Unsupported"}): - with pytest.raises(MutualTLSChannelError): - client = client_class() - - # Check the case quota_project_id is provided - options = client_options.ClientOptions(quota_project_id="octopus") - with mock.patch.object(transport_class, "__init__") as patched: - patched.return_value = None - client = client_class(client_options=options) - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, - quota_project_id="octopus", - ) + 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, + ) + + # 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, + scopes=None, + ssl_channel_credentials=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) @pytest.mark.parametrize( @@ -304,9 +389,9 @@ def test_realms_service_client_client_options_scopes( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=["1", "2"], - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -334,9 +419,9 @@ def test_realms_service_client_client_options_credentials_file( credentials_file="credentials.json", host=client.DEFAULT_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -353,9 +438,9 @@ def test_realms_service_client_client_options_from_dict(): credentials_file=None, host="squid.clam.whelk", scopes=None, - api_mtls_endpoint="squid.clam.whelk", - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -369,7 +454,7 @@ def test_list_realms(transport: str = "grpc", request_type=realms.ListRealmsRequ request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.list_realms), "__call__") as call: + with mock.patch.object(type(client.transport.list_realms), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = realms.ListRealmsResponse( next_page_token="next_page_token_value", unreachable=["unreachable_value"], @@ -384,6 +469,7 @@ def test_list_realms(transport: str = "grpc", request_type=realms.ListRealmsRequ assert args[0] == realms.ListRealmsRequest() # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListRealmsPager) assert response.next_page_token == "next_page_token_value" @@ -396,19 +482,19 @@ def test_list_realms_from_dict(): @pytest.mark.asyncio -async def test_list_realms_async(transport: str = "grpc_asyncio"): +async def test_list_realms_async( + transport: str = "grpc_asyncio", request_type=realms.ListRealmsRequest +): client = RealmsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = realms.ListRealmsRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.list_realms), "__call__" - ) as call: + with mock.patch.object(type(client.transport.list_realms), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( realms.ListRealmsResponse( @@ -423,7 +509,7 @@ async def test_list_realms_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == realms.ListRealmsRequest() # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListRealmsAsyncPager) @@ -433,6 +519,11 @@ async def test_list_realms_async(transport: str = "grpc_asyncio"): assert response.unreachable == ["unreachable_value"] +@pytest.mark.asyncio +async def test_list_realms_async_from_dict(): + await test_list_realms_async(request_type=dict) + + def test_list_realms_field_headers(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) @@ -442,7 +533,7 @@ def test_list_realms_field_headers(): request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.list_realms), "__call__") as call: + with mock.patch.object(type(client.transport.list_realms), "__call__") as call: call.return_value = realms.ListRealmsResponse() client.list_realms(request) @@ -467,9 +558,7 @@ async def test_list_realms_field_headers_async(): request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.list_realms), "__call__" - ) as call: + with mock.patch.object(type(client.transport.list_realms), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( realms.ListRealmsResponse() ) @@ -490,7 +579,7 @@ def test_list_realms_flattened(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.list_realms), "__call__") as call: + with mock.patch.object(type(client.transport.list_realms), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = realms.ListRealmsResponse() @@ -522,9 +611,7 @@ async def test_list_realms_flattened_async(): client = RealmsServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.list_realms), "__call__" - ) as call: + with mock.patch.object(type(client.transport.list_realms), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = realms.ListRealmsResponse() @@ -559,7 +646,7 @@ def test_list_realms_pager(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials,) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.list_realms), "__call__") as call: + with mock.patch.object(type(client.transport.list_realms), "__call__") as call: # Set the response to a series of pages. call.side_effect = ( realms.ListRealmsResponse( @@ -589,7 +676,7 @@ def test_list_realms_pages(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials,) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.list_realms), "__call__") as call: + with mock.patch.object(type(client.transport.list_realms), "__call__") as call: # Set the response to a series of pages. call.side_effect = ( realms.ListRealmsResponse( @@ -602,8 +689,8 @@ def test_list_realms_pages(): RuntimeError, ) pages = list(client.list_realms(request={}).pages) - for page, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page.raw_page.next_page_token == token + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token @pytest.mark.asyncio @@ -612,9 +699,7 @@ async def test_list_realms_async_pager(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_realms), - "__call__", - new_callable=mock.AsyncMock, + type(client.transport.list_realms), "__call__", new_callable=mock.AsyncMock ) as call: # Set the response to a series of pages. call.side_effect = ( @@ -643,9 +728,7 @@ async def test_list_realms_async_pages(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_realms), - "__call__", - new_callable=mock.AsyncMock, + type(client.transport.list_realms), "__call__", new_callable=mock.AsyncMock ) as call: # Set the response to a series of pages. call.side_effect = ( @@ -659,10 +742,10 @@ async def test_list_realms_async_pages(): RuntimeError, ) pages = [] - async for page in (await client.list_realms(request={})).pages: - pages.append(page) - for page, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page.raw_page.next_page_token == token + async for page_ in (await client.list_realms(request={})).pages: + pages.append(page_) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token def test_get_realm(transport: str = "grpc", request_type=realms.GetRealmRequest): @@ -675,7 +758,7 @@ def test_get_realm(transport: str = "grpc", request_type=realms.GetRealmRequest) request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.get_realm), "__call__") as call: + with mock.patch.object(type(client.transport.get_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = realms.Realm( name="name_value", @@ -693,6 +776,7 @@ def test_get_realm(transport: str = "grpc", request_type=realms.GetRealmRequest) assert args[0] == realms.GetRealmRequest() # Establish that the response is the type that we expect. + assert isinstance(response, realms.Realm) assert response.name == "name_value" @@ -709,19 +793,19 @@ def test_get_realm_from_dict(): @pytest.mark.asyncio -async def test_get_realm_async(transport: str = "grpc_asyncio"): +async def test_get_realm_async( + transport: str = "grpc_asyncio", request_type=realms.GetRealmRequest +): client = RealmsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = realms.GetRealmRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.get_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.get_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( realms.Realm( @@ -738,7 +822,7 @@ async def test_get_realm_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == realms.GetRealmRequest() # Establish that the response is the type that we expect. assert isinstance(response, realms.Realm) @@ -752,6 +836,11 @@ async def test_get_realm_async(transport: str = "grpc_asyncio"): assert response.description == "description_value" +@pytest.mark.asyncio +async def test_get_realm_async_from_dict(): + await test_get_realm_async(request_type=dict) + + def test_get_realm_field_headers(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) @@ -761,7 +850,7 @@ def test_get_realm_field_headers(): request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.get_realm), "__call__") as call: + with mock.patch.object(type(client.transport.get_realm), "__call__") as call: call.return_value = realms.Realm() client.get_realm(request) @@ -786,9 +875,7 @@ async def test_get_realm_field_headers_async(): request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.get_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.get_realm), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(realms.Realm()) await client.get_realm(request) @@ -807,7 +894,7 @@ def test_get_realm_flattened(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.get_realm), "__call__") as call: + with mock.patch.object(type(client.transport.get_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = realms.Realm() @@ -839,9 +926,7 @@ async def test_get_realm_flattened_async(): client = RealmsServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.get_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.get_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = realms.Realm() @@ -880,7 +965,7 @@ def test_create_realm(transport: str = "grpc", request_type=realms.CreateRealmRe request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.create_realm), "__call__") as call: + with mock.patch.object(type(client.transport.create_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -901,19 +986,19 @@ def test_create_realm_from_dict(): @pytest.mark.asyncio -async def test_create_realm_async(transport: str = "grpc_asyncio"): +async def test_create_realm_async( + transport: str = "grpc_asyncio", request_type=realms.CreateRealmRequest +): client = RealmsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = realms.CreateRealmRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.create_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.create_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/spam") @@ -925,12 +1010,17 @@ async def test_create_realm_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == realms.CreateRealmRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_create_realm_async_from_dict(): + await test_create_realm_async(request_type=dict) + + def test_create_realm_field_headers(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) @@ -940,7 +1030,7 @@ def test_create_realm_field_headers(): request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.create_realm), "__call__") as call: + with mock.patch.object(type(client.transport.create_realm), "__call__") as call: call.return_value = operations_pb2.Operation(name="operations/op") client.create_realm(request) @@ -965,9 +1055,7 @@ async def test_create_realm_field_headers_async(): request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.create_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.create_realm), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") ) @@ -988,7 +1076,7 @@ def test_create_realm_flattened(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.create_realm), "__call__") as call: + with mock.patch.object(type(client.transport.create_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1031,9 +1119,7 @@ async def test_create_realm_flattened_async(): client = RealmsServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.create_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.create_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1085,7 +1171,7 @@ def test_delete_realm(transport: str = "grpc", request_type=realms.DeleteRealmRe request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.delete_realm), "__call__") as call: + with mock.patch.object(type(client.transport.delete_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1106,19 +1192,19 @@ def test_delete_realm_from_dict(): @pytest.mark.asyncio -async def test_delete_realm_async(transport: str = "grpc_asyncio"): +async def test_delete_realm_async( + transport: str = "grpc_asyncio", request_type=realms.DeleteRealmRequest +): client = RealmsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = realms.DeleteRealmRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.delete_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.delete_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/spam") @@ -1130,12 +1216,17 @@ async def test_delete_realm_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == realms.DeleteRealmRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_delete_realm_async_from_dict(): + await test_delete_realm_async(request_type=dict) + + def test_delete_realm_field_headers(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) @@ -1145,7 +1236,7 @@ def test_delete_realm_field_headers(): request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.delete_realm), "__call__") as call: + with mock.patch.object(type(client.transport.delete_realm), "__call__") as call: call.return_value = operations_pb2.Operation(name="operations/op") client.delete_realm(request) @@ -1170,9 +1261,7 @@ async def test_delete_realm_field_headers_async(): request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.delete_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.delete_realm), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") ) @@ -1193,7 +1282,7 @@ def test_delete_realm_flattened(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.delete_realm), "__call__") as call: + with mock.patch.object(type(client.transport.delete_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1225,9 +1314,7 @@ async def test_delete_realm_flattened_async(): client = RealmsServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.delete_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.delete_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1268,7 +1355,7 @@ def test_update_realm(transport: str = "grpc", request_type=realms.UpdateRealmRe request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.update_realm), "__call__") as call: + with mock.patch.object(type(client.transport.update_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1289,19 +1376,19 @@ def test_update_realm_from_dict(): @pytest.mark.asyncio -async def test_update_realm_async(transport: str = "grpc_asyncio"): +async def test_update_realm_async( + transport: str = "grpc_asyncio", request_type=realms.UpdateRealmRequest +): client = RealmsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = realms.UpdateRealmRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.update_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.update_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/spam") @@ -1313,12 +1400,17 @@ async def test_update_realm_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == realms.UpdateRealmRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_update_realm_async_from_dict(): + await test_update_realm_async(request_type=dict) + + def test_update_realm_field_headers(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) @@ -1328,7 +1420,7 @@ def test_update_realm_field_headers(): request.realm.name = "realm.name/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.update_realm), "__call__") as call: + with mock.patch.object(type(client.transport.update_realm), "__call__") as call: call.return_value = operations_pb2.Operation(name="operations/op") client.update_realm(request) @@ -1353,9 +1445,7 @@ async def test_update_realm_field_headers_async(): request.realm.name = "realm.name/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.update_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.update_realm), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") ) @@ -1376,7 +1466,7 @@ def test_update_realm_flattened(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.update_realm), "__call__") as call: + with mock.patch.object(type(client.transport.update_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1415,9 +1505,7 @@ async def test_update_realm_flattened_async(): client = RealmsServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.update_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.update_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1468,7 +1556,7 @@ def test_preview_realm_update( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_realm_update), "__call__" + type(client.transport.preview_realm_update), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = realms.PreviewRealmUpdateResponse(etag="etag_value",) @@ -1482,6 +1570,7 @@ def test_preview_realm_update( assert args[0] == realms.PreviewRealmUpdateRequest() # Establish that the response is the type that we expect. + assert isinstance(response, realms.PreviewRealmUpdateResponse) assert response.etag == "etag_value" @@ -1492,18 +1581,20 @@ def test_preview_realm_update_from_dict(): @pytest.mark.asyncio -async def test_preview_realm_update_async(transport: str = "grpc_asyncio"): +async def test_preview_realm_update_async( + transport: str = "grpc_asyncio", request_type=realms.PreviewRealmUpdateRequest +): client = RealmsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = realms.PreviewRealmUpdateRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_realm_update), "__call__" + type(client.transport.preview_realm_update), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1516,7 +1607,7 @@ async def test_preview_realm_update_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == realms.PreviewRealmUpdateRequest() # Establish that the response is the type that we expect. assert isinstance(response, realms.PreviewRealmUpdateResponse) @@ -1524,6 +1615,11 @@ async def test_preview_realm_update_async(transport: str = "grpc_asyncio"): assert response.etag == "etag_value" +@pytest.mark.asyncio +async def test_preview_realm_update_async_from_dict(): + await test_preview_realm_update_async(request_type=dict) + + def test_preview_realm_update_field_headers(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) @@ -1534,7 +1630,7 @@ def test_preview_realm_update_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_realm_update), "__call__" + type(client.transport.preview_realm_update), "__call__" ) as call: call.return_value = realms.PreviewRealmUpdateResponse() @@ -1561,7 +1657,7 @@ async def test_preview_realm_update_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_realm_update), "__call__" + type(client.transport.preview_realm_update), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( realms.PreviewRealmUpdateResponse() @@ -1615,7 +1711,7 @@ def test_transport_instance(): credentials=credentials.AnonymousCredentials(), ) client = RealmsServiceClient(transport=transport) - assert client._transport is transport + assert client.transport is transport def test_transport_get_channel(): @@ -1633,10 +1729,25 @@ def test_transport_get_channel(): assert channel +@pytest.mark.parametrize( + "transport_class", + [ + transports.RealmsServiceGrpcTransport, + transports.RealmsServiceGrpcAsyncIOTransport, + ], +) +def test_transport_adc(transport_class): + # Test default credentials are used if not provided. + with mock.patch.object(auth, "default") as adc: + adc.return_value = (credentials.AnonymousCredentials(), None) + transport_class() + adc.assert_called_once() + + def test_transport_grpc_default(): # A client should use the gRPC transport by default. client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) - assert isinstance(client._transport, transports.RealmsServiceGrpcTransport,) + assert isinstance(client.transport, transports.RealmsServiceGrpcTransport,) def test_realms_service_base_transport_error(): @@ -1697,6 +1808,17 @@ def test_realms_service_base_transport_with_credentials_file(): ) +def test_realms_service_base_transport_with_adc(): + # Test the default credentials are used if credentials and credentials_file are None. + with mock.patch.object(auth, "default") as adc, mock.patch( + "google.cloud.gaming_v1.services.realms_service.transports.RealmsServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (credentials.AnonymousCredentials(), None) + transport = transports.RealmsServiceTransport() + adc.assert_called_once() + + def test_realms_service_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(auth, "default") as adc: @@ -1729,7 +1851,7 @@ def test_realms_service_host_no_port(): api_endpoint="gameservices.googleapis.com" ), ) - assert client._transport._host == "gameservices.googleapis.com:443" + assert client.transport._host == "gameservices.googleapis.com:443" def test_realms_service_host_with_port(): @@ -1739,192 +1861,124 @@ def test_realms_service_host_with_port(): api_endpoint="gameservices.googleapis.com:8000" ), ) - assert client._transport._host == "gameservices.googleapis.com:8000" + assert client.transport._host == "gameservices.googleapis.com:8000" def test_realms_service_grpc_transport_channel(): channel = grpc.insecure_channel("http://localhost/") - # Check that if channel is provided, mtls endpoint and client_cert_source - # won't be used. - callback = mock.MagicMock() + # Check that channel is used if provided. transport = transports.RealmsServiceGrpcTransport( - host="squid.clam.whelk", - channel=channel, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=callback, + host="squid.clam.whelk", channel=channel, ) assert transport.grpc_channel == channel assert transport._host == "squid.clam.whelk:443" - assert not callback.called + assert transport._ssl_channel_credentials == None def test_realms_service_grpc_asyncio_transport_channel(): channel = aio.insecure_channel("http://localhost/") - # Check that if channel is provided, mtls endpoint and client_cert_source - # won't be used. - callback = mock.MagicMock() + # Check that channel is used if provided. transport = transports.RealmsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - channel=channel, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=callback, + host="squid.clam.whelk", channel=channel, ) assert transport.grpc_channel == channel assert transport._host == "squid.clam.whelk:443" - assert not callback.called - - -@mock.patch("grpc.ssl_channel_credentials", autospec=True) -@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) -def test_realms_service_grpc_transport_channel_mtls_with_client_cert_source( - grpc_create_channel, grpc_ssl_channel_cred -): - # Check that if channel is None, but api_mtls_endpoint and client_cert_source - # are provided, then a mTLS channel will be created. - mock_cred = mock.Mock() - - mock_ssl_cred = mock.Mock() - grpc_ssl_channel_cred.return_value = mock_ssl_cred - - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - transport = transports.RealmsServiceGrpcTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=client_cert_source_callback, - ) - grpc_ssl_channel_cred.assert_called_once_with( - certificate_chain=b"cert bytes", private_key=b"key bytes" - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel - - -@mock.patch("grpc.ssl_channel_credentials", autospec=True) -@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) -def test_realms_service_grpc_asyncio_transport_channel_mtls_with_client_cert_source( - grpc_create_channel, grpc_ssl_channel_cred -): - # Check that if channel is None, but api_mtls_endpoint and client_cert_source - # are provided, then a mTLS channel will be created. - mock_cred = mock.Mock() - - mock_ssl_cred = mock.Mock() - grpc_ssl_channel_cred.return_value = mock_ssl_cred - - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - transport = transports.RealmsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=client_cert_source_callback, - ) - grpc_ssl_channel_cred.assert_called_once_with( - certificate_chain=b"cert bytes", private_key=b"key bytes" - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == None @pytest.mark.parametrize( - "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] + "transport_class", + [ + transports.RealmsServiceGrpcTransport, + transports.RealmsServiceGrpcAsyncIOTransport, + ], ) -@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) -def test_realms_service_grpc_transport_channel_mtls_with_adc( - grpc_create_channel, api_mtls_endpoint -): - # Check that if channel and client_cert_source are None, but api_mtls_endpoint - # is provided, then a mTLS channel will be created with SSL ADC. - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - # Mock google.auth.transport.grpc.SslCredentials class. - mock_ssl_cred = mock.Mock() - with mock.patch.multiple( - "google.auth.transport.grpc.SslCredentials", - __init__=mock.Mock(return_value=None), - ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), - ): - mock_cred = mock.Mock() - transport = transports.RealmsServiceGrpcTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint=api_mtls_endpoint, - client_cert_source=None, - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel +def test_realms_service_transport_channel_mtls_with_client_cert_source(transport_class): + with mock.patch( + "grpc.ssl_channel_credentials", autospec=True + ) as grpc_ssl_channel_cred: + with mock.patch.object( + transport_class, "create_channel", autospec=True + ) as grpc_create_channel: + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + cred = credentials.AnonymousCredentials() + with pytest.warns(DeprecationWarning): + with mock.patch.object(auth, "default") as adc: + adc.return_value = (cred, None) + transport = transport_class( + host="squid.clam.whelk", + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + adc.assert_called_once() + + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + ) + assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == mock_ssl_cred @pytest.mark.parametrize( - "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] + "transport_class", + [ + transports.RealmsServiceGrpcTransport, + transports.RealmsServiceGrpcAsyncIOTransport, + ], ) -@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) -def test_realms_service_grpc_asyncio_transport_channel_mtls_with_adc( - grpc_create_channel, api_mtls_endpoint -): - # Check that if channel and client_cert_source are None, but api_mtls_endpoint - # is provided, then a mTLS channel will be created with SSL ADC. - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - # Mock google.auth.transport.grpc.SslCredentials class. +def test_realms_service_transport_channel_mtls_with_adc(transport_class): mock_ssl_cred = mock.Mock() with mock.patch.multiple( "google.auth.transport.grpc.SslCredentials", __init__=mock.Mock(return_value=None), ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), ): - mock_cred = mock.Mock() - transport = transports.RealmsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint=api_mtls_endpoint, - client_cert_source=None, - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + with mock.patch.object( + transport_class, "create_channel", autospec=True + ) as grpc_create_channel: + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + mock_cred = mock.Mock() + + with pytest.warns(DeprecationWarning): + transport = transport_class( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=None, + ) + + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + ) + assert transport.grpc_channel == mock_grpc_channel def test_realms_service_grpc_lro_client(): client = RealmsServiceClient( credentials=credentials.AnonymousCredentials(), transport="grpc", ) - transport = client._transport + transport = client.transport # Ensure that we have a api-core operations client. assert isinstance(transport.operations_client, operations_v1.OperationsClient,) @@ -1937,7 +1991,7 @@ def test_realms_service_grpc_lro_async_client(): client = RealmsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport="grpc_asyncio", ) - transport = client._client._transport + transport = client.transport # Ensure that we have a api-core operations client. assert isinstance(transport.operations_client, operations_v1.OperationsAsyncClient,) @@ -1969,3 +2023,125 @@ def test_parse_realm_path(): # Check that the path construction is reversible. actual = RealmsServiceClient.parse_realm_path(path) assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "cuttlefish" + + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = RealmsServiceClient.common_billing_account_path(billing_account) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "mussel", + } + path = RealmsServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = RealmsServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "winkle" + + expected = "folders/{folder}".format(folder=folder,) + actual = RealmsServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "nautilus", + } + path = RealmsServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = RealmsServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "scallop" + + expected = "organizations/{organization}".format(organization=organization,) + actual = RealmsServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "abalone", + } + path = RealmsServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = RealmsServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "squid" + + expected = "projects/{project}".format(project=project,) + actual = RealmsServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "clam", + } + path = RealmsServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = RealmsServiceClient.parse_common_project_path(path) + assert expected == actual + + +def test_common_location_path(): + project = "whelk" + location = "octopus" + + expected = "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + actual = RealmsServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "oyster", + "location": "nudibranch", + } + path = RealmsServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = RealmsServiceClient.parse_common_location_path(path) + assert expected == actual + + +def test_client_withDEFAULT_CLIENT_INFO(): + client_info = gapic_v1.client_info.ClientInfo() + + with mock.patch.object( + transports.RealmsServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = RealmsServiceClient( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.RealmsServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = RealmsServiceClient.get_transport_class() + transport = transport_class( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) diff --git a/tests/unit/gapic/gaming_v1beta/test_game_server_clusters_service.py b/tests/unit/gapic/gaming_v1beta/test_game_server_clusters_service.py index 1fa50a7c..16e1fa31 100644 --- a/tests/unit/gapic/gaming_v1beta/test_game_server_clusters_service.py +++ b/tests/unit/gapic/gaming_v1beta/test_game_server_clusters_service.py @@ -31,7 +31,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async -from google.api_core import operation_async +from google.api_core import operation_async # type: ignore from google.api_core import operations_v1 from google.auth import credentials from google.auth.exceptions import MutualTLSChannelError @@ -109,12 +109,12 @@ def test_game_server_clusters_service_client_from_service_account_file(client_cl ) as factory: factory.return_value = creds client = client_class.from_service_account_file("dummy/file/path.json") - assert client._transport._credentials == creds + assert client.transport._credentials == creds client = client_class.from_service_account_json("dummy/file/path.json") - assert client._transport._credentials == creds + assert client.transport._credentials == creds - assert client._transport._host == "gameservices.googleapis.com:443" + assert client.transport._host == "gameservices.googleapis.com:443" def test_game_server_clusters_service_client_get_transport_class(): @@ -178,14 +178,14 @@ def test_game_server_clusters_service_client_client_options( credentials_file=None, host="squid.clam.whelk", scopes=None, - api_mtls_endpoint="squid.clam.whelk", - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is # "never". - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "never"}): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None client = client_class() @@ -194,14 +194,14 @@ def test_game_server_clusters_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is # "always". - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "always"}): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None client = client_class() @@ -210,90 +210,185 @@ def test_game_server_clusters_service_client_client_options( credentials_file=None, host=client.DEFAULT_MTLS_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", and client_cert_source is provided. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError): + client = client_class() + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError): + client = client_class() + + # Check the case quota_project_id is provided + options = client_options.ClientOptions(quota_project_id="octopus") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + ssl_channel_credentials=None, + quota_project_id="octopus", + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,use_client_cert_env", + [ + ( + GameServerClustersServiceClient, + transports.GameServerClustersServiceGrpcTransport, + "grpc", + "true", + ), + ( + GameServerClustersServiceAsyncClient, + transports.GameServerClustersServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + ( + GameServerClustersServiceClient, + transports.GameServerClustersServiceGrpcTransport, + "grpc", + "false", + ), + ( + GameServerClustersServiceAsyncClient, + transports.GameServerClustersServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ], +) +@mock.patch.object( + GameServerClustersServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GameServerClustersServiceClient), +) +@mock.patch.object( + GameServerClustersServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GameServerClustersServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_game_server_clusters_service_client_mtls_env_auto( + client_class, transport_class, transport_name, use_client_cert_env +): + # This tests the endpoint autoswitch behavior. Endpoint is autoswitched to the default + # mtls endpoint, if GOOGLE_API_USE_CLIENT_CERTIFICATE is "true" and client cert exists. + + # Check the case client_cert_source is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): options = client_options.ClientOptions( client_cert_source=client_cert_source_callback ) with mock.patch.object(transport_class, "__init__") as patched: - patched.return_value = None - client = client_class(client_options=options) - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_MTLS_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=client_cert_source_callback, - quota_project_id=None, - ) - - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", and default_client_cert_source is provided. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): - with mock.patch.object(transport_class, "__init__") as patched: + ssl_channel_creds = mock.Mock() with mock.patch( - "google.auth.transport.mtls.has_default_client_cert_source", - return_value=True, + "grpc.ssl_channel_credentials", return_value=ssl_channel_creds ): patched.return_value = None - client = client_class() + 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 + patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_MTLS_ENDPOINT, + host=expected_host, scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=expected_ssl_channel_creds, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", but client_cert_source and default_client_cert_source are None. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): + # Check the case ADC client cert is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + 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, + "google.auth.transport.grpc.SslCredentials.__init__", return_value=None ): - patched.return_value = None - client = client_class() - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, - quota_project_id=None, - ) - - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS has - # unsupported value. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "Unsupported"}): - with pytest.raises(MutualTLSChannelError): - client = client_class() - - # Check the case quota_project_id is provided - options = client_options.ClientOptions(quota_project_id="octopus") - with mock.patch.object(transport_class, "__init__") as patched: - patched.return_value = None - client = client_class(client_options=options) - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, - quota_project_id="octopus", - ) + 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, + ) + + # 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, + scopes=None, + ssl_channel_credentials=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) @pytest.mark.parametrize( @@ -324,9 +419,9 @@ def test_game_server_clusters_service_client_client_options_scopes( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=["1", "2"], - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -358,9 +453,9 @@ def test_game_server_clusters_service_client_client_options_credentials_file( credentials_file="credentials.json", host=client.DEFAULT_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -377,9 +472,9 @@ def test_game_server_clusters_service_client_client_options_from_dict(): credentials_file=None, host="squid.clam.whelk", scopes=None, - api_mtls_endpoint="squid.clam.whelk", - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -397,7 +492,7 @@ def test_list_game_server_clusters( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_clusters), "__call__" + type(client.transport.list_game_server_clusters), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.ListGameServerClustersResponse( @@ -413,6 +508,7 @@ def test_list_game_server_clusters( assert args[0] == game_server_clusters.ListGameServerClustersRequest() # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListGameServerClustersPager) assert response.next_page_token == "next_page_token_value" @@ -425,18 +521,21 @@ def test_list_game_server_clusters_from_dict(): @pytest.mark.asyncio -async def test_list_game_server_clusters_async(transport: str = "grpc_asyncio"): +async def test_list_game_server_clusters_async( + transport: str = "grpc_asyncio", + request_type=game_server_clusters.ListGameServerClustersRequest, +): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_clusters.ListGameServerClustersRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_clusters), "__call__" + type(client.transport.list_game_server_clusters), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -452,7 +551,7 @@ async def test_list_game_server_clusters_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_clusters.ListGameServerClustersRequest() # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListGameServerClustersAsyncPager) @@ -462,6 +561,11 @@ async def test_list_game_server_clusters_async(transport: str = "grpc_asyncio"): assert response.unreachable == ["unreachable_value"] +@pytest.mark.asyncio +async def test_list_game_server_clusters_async_from_dict(): + await test_list_game_server_clusters_async(request_type=dict) + + def test_list_game_server_clusters_field_headers(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), @@ -474,7 +578,7 @@ def test_list_game_server_clusters_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_clusters), "__call__" + type(client.transport.list_game_server_clusters), "__call__" ) as call: call.return_value = game_server_clusters.ListGameServerClustersResponse() @@ -503,7 +607,7 @@ async def test_list_game_server_clusters_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_clusters), "__call__" + type(client.transport.list_game_server_clusters), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_clusters.ListGameServerClustersResponse() @@ -528,7 +632,7 @@ def test_list_game_server_clusters_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_clusters), "__call__" + type(client.transport.list_game_server_clusters), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.ListGameServerClustersResponse() @@ -566,7 +670,7 @@ async def test_list_game_server_clusters_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_clusters), "__call__" + type(client.transport.list_game_server_clusters), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.ListGameServerClustersResponse() @@ -607,7 +711,7 @@ def test_list_game_server_clusters_pager(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_clusters), "__call__" + type(client.transport.list_game_server_clusters), "__call__" ) as call: # Set the response to a series of pages. call.side_effect = ( @@ -657,7 +761,7 @@ def test_list_game_server_clusters_pages(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_clusters), "__call__" + type(client.transport.list_game_server_clusters), "__call__" ) as call: # Set the response to a series of pages. call.side_effect = ( @@ -685,8 +789,8 @@ def test_list_game_server_clusters_pages(): RuntimeError, ) pages = list(client.list_game_server_clusters(request={}).pages) - for page, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page.raw_page.next_page_token == token + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token @pytest.mark.asyncio @@ -697,7 +801,7 @@ async def test_list_game_server_clusters_async_pager(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_clusters), + type(client.transport.list_game_server_clusters), "__call__", new_callable=mock.AsyncMock, ) as call: @@ -746,7 +850,7 @@ async def test_list_game_server_clusters_async_pages(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_clusters), + type(client.transport.list_game_server_clusters), "__call__", new_callable=mock.AsyncMock, ) as call: @@ -776,10 +880,10 @@ async def test_list_game_server_clusters_async_pages(): RuntimeError, ) pages = [] - async for page in (await client.list_game_server_clusters(request={})).pages: - pages.append(page) - for page, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page.raw_page.next_page_token == token + async for page_ in (await client.list_game_server_clusters(request={})).pages: + pages.append(page_) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token def test_get_game_server_cluster( @@ -796,7 +900,7 @@ def test_get_game_server_cluster( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_cluster), "__call__" + type(client.transport.get_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.GameServerCluster( @@ -812,6 +916,7 @@ def test_get_game_server_cluster( assert args[0] == game_server_clusters.GetGameServerClusterRequest() # Establish that the response is the type that we expect. + assert isinstance(response, game_server_clusters.GameServerCluster) assert response.name == "name_value" @@ -826,18 +931,21 @@ def test_get_game_server_cluster_from_dict(): @pytest.mark.asyncio -async def test_get_game_server_cluster_async(transport: str = "grpc_asyncio"): +async def test_get_game_server_cluster_async( + transport: str = "grpc_asyncio", + request_type=game_server_clusters.GetGameServerClusterRequest, +): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_clusters.GetGameServerClusterRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_cluster), "__call__" + type(client.transport.get_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -852,7 +960,7 @@ async def test_get_game_server_cluster_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_clusters.GetGameServerClusterRequest() # Establish that the response is the type that we expect. assert isinstance(response, game_server_clusters.GameServerCluster) @@ -864,6 +972,11 @@ async def test_get_game_server_cluster_async(transport: str = "grpc_asyncio"): assert response.description == "description_value" +@pytest.mark.asyncio +async def test_get_game_server_cluster_async_from_dict(): + await test_get_game_server_cluster_async(request_type=dict) + + def test_get_game_server_cluster_field_headers(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), @@ -876,7 +989,7 @@ def test_get_game_server_cluster_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_cluster), "__call__" + type(client.transport.get_game_server_cluster), "__call__" ) as call: call.return_value = game_server_clusters.GameServerCluster() @@ -905,7 +1018,7 @@ async def test_get_game_server_cluster_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_cluster), "__call__" + type(client.transport.get_game_server_cluster), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_clusters.GameServerCluster() @@ -930,7 +1043,7 @@ def test_get_game_server_cluster_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_cluster), "__call__" + type(client.transport.get_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.GameServerCluster() @@ -968,7 +1081,7 @@ async def test_get_game_server_cluster_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_cluster), "__call__" + type(client.transport.get_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.GameServerCluster() @@ -1016,7 +1129,7 @@ def test_create_game_server_cluster( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_cluster), "__call__" + type(client.transport.create_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1038,18 +1151,21 @@ def test_create_game_server_cluster_from_dict(): @pytest.mark.asyncio -async def test_create_game_server_cluster_async(transport: str = "grpc_asyncio"): +async def test_create_game_server_cluster_async( + transport: str = "grpc_asyncio", + request_type=game_server_clusters.CreateGameServerClusterRequest, +): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_clusters.CreateGameServerClusterRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_cluster), "__call__" + type(client.transport.create_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1062,12 +1178,17 @@ async def test_create_game_server_cluster_async(transport: str = "grpc_asyncio") assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_clusters.CreateGameServerClusterRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_create_game_server_cluster_async_from_dict(): + await test_create_game_server_cluster_async(request_type=dict) + + def test_create_game_server_cluster_field_headers(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1080,7 +1201,7 @@ def test_create_game_server_cluster_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_cluster), "__call__" + type(client.transport.create_game_server_cluster), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -1109,7 +1230,7 @@ async def test_create_game_server_cluster_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_cluster), "__call__" + type(client.transport.create_game_server_cluster), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -1134,7 +1255,7 @@ def test_create_game_server_cluster_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_cluster), "__call__" + type(client.transport.create_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1189,7 +1310,7 @@ async def test_create_game_server_cluster_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_cluster), "__call__" + type(client.transport.create_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1254,7 +1375,7 @@ def test_preview_create_game_server_cluster( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_create_game_server_cluster), "__call__" + type(client.transport.preview_create_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.PreviewCreateGameServerClusterResponse( @@ -1270,6 +1391,7 @@ def test_preview_create_game_server_cluster( assert args[0] == game_server_clusters.PreviewCreateGameServerClusterRequest() # Establish that the response is the type that we expect. + assert isinstance( response, game_server_clusters.PreviewCreateGameServerClusterResponse ) @@ -1284,6 +1406,7 @@ def test_preview_create_game_server_cluster_from_dict(): @pytest.mark.asyncio async def test_preview_create_game_server_cluster_async( transport: str = "grpc_asyncio", + request_type=game_server_clusters.PreviewCreateGameServerClusterRequest, ): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, @@ -1291,11 +1414,11 @@ async def test_preview_create_game_server_cluster_async( # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_clusters.PreviewCreateGameServerClusterRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_create_game_server_cluster), "__call__" + type(client.transport.preview_create_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1310,7 +1433,7 @@ async def test_preview_create_game_server_cluster_async( assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_clusters.PreviewCreateGameServerClusterRequest() # Establish that the response is the type that we expect. assert isinstance( @@ -1320,6 +1443,11 @@ async def test_preview_create_game_server_cluster_async( assert response.etag == "etag_value" +@pytest.mark.asyncio +async def test_preview_create_game_server_cluster_async_from_dict(): + await test_preview_create_game_server_cluster_async(request_type=dict) + + def test_preview_create_game_server_cluster_field_headers(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1332,7 +1460,7 @@ def test_preview_create_game_server_cluster_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_create_game_server_cluster), "__call__" + type(client.transport.preview_create_game_server_cluster), "__call__" ) as call: call.return_value = ( game_server_clusters.PreviewCreateGameServerClusterResponse() @@ -1363,7 +1491,7 @@ async def test_preview_create_game_server_cluster_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_create_game_server_cluster), "__call__" + type(client.transport.preview_create_game_server_cluster), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_clusters.PreviewCreateGameServerClusterResponse() @@ -1395,7 +1523,7 @@ def test_delete_game_server_cluster( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_cluster), "__call__" + type(client.transport.delete_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1417,18 +1545,21 @@ def test_delete_game_server_cluster_from_dict(): @pytest.mark.asyncio -async def test_delete_game_server_cluster_async(transport: str = "grpc_asyncio"): +async def test_delete_game_server_cluster_async( + transport: str = "grpc_asyncio", + request_type=game_server_clusters.DeleteGameServerClusterRequest, +): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_clusters.DeleteGameServerClusterRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_cluster), "__call__" + type(client.transport.delete_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1441,12 +1572,17 @@ async def test_delete_game_server_cluster_async(transport: str = "grpc_asyncio") assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_clusters.DeleteGameServerClusterRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_delete_game_server_cluster_async_from_dict(): + await test_delete_game_server_cluster_async(request_type=dict) + + def test_delete_game_server_cluster_field_headers(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1459,7 +1595,7 @@ def test_delete_game_server_cluster_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_cluster), "__call__" + type(client.transport.delete_game_server_cluster), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -1488,7 +1624,7 @@ async def test_delete_game_server_cluster_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_cluster), "__call__" + type(client.transport.delete_game_server_cluster), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -1513,7 +1649,7 @@ def test_delete_game_server_cluster_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_cluster), "__call__" + type(client.transport.delete_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1551,7 +1687,7 @@ async def test_delete_game_server_cluster_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_cluster), "__call__" + type(client.transport.delete_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1599,7 +1735,7 @@ def test_preview_delete_game_server_cluster( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_delete_game_server_cluster), "__call__" + type(client.transport.preview_delete_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.PreviewDeleteGameServerClusterResponse( @@ -1615,6 +1751,7 @@ def test_preview_delete_game_server_cluster( assert args[0] == game_server_clusters.PreviewDeleteGameServerClusterRequest() # Establish that the response is the type that we expect. + assert isinstance( response, game_server_clusters.PreviewDeleteGameServerClusterResponse ) @@ -1629,6 +1766,7 @@ def test_preview_delete_game_server_cluster_from_dict(): @pytest.mark.asyncio async def test_preview_delete_game_server_cluster_async( transport: str = "grpc_asyncio", + request_type=game_server_clusters.PreviewDeleteGameServerClusterRequest, ): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, @@ -1636,11 +1774,11 @@ async def test_preview_delete_game_server_cluster_async( # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_clusters.PreviewDeleteGameServerClusterRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_delete_game_server_cluster), "__call__" + type(client.transport.preview_delete_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1655,7 +1793,7 @@ async def test_preview_delete_game_server_cluster_async( assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_clusters.PreviewDeleteGameServerClusterRequest() # Establish that the response is the type that we expect. assert isinstance( @@ -1665,6 +1803,11 @@ async def test_preview_delete_game_server_cluster_async( assert response.etag == "etag_value" +@pytest.mark.asyncio +async def test_preview_delete_game_server_cluster_async_from_dict(): + await test_preview_delete_game_server_cluster_async(request_type=dict) + + def test_preview_delete_game_server_cluster_field_headers(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1677,7 +1820,7 @@ def test_preview_delete_game_server_cluster_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_delete_game_server_cluster), "__call__" + type(client.transport.preview_delete_game_server_cluster), "__call__" ) as call: call.return_value = ( game_server_clusters.PreviewDeleteGameServerClusterResponse() @@ -1708,7 +1851,7 @@ async def test_preview_delete_game_server_cluster_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_delete_game_server_cluster), "__call__" + type(client.transport.preview_delete_game_server_cluster), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_clusters.PreviewDeleteGameServerClusterResponse() @@ -1740,7 +1883,7 @@ def test_update_game_server_cluster( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_cluster), "__call__" + type(client.transport.update_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1762,18 +1905,21 @@ def test_update_game_server_cluster_from_dict(): @pytest.mark.asyncio -async def test_update_game_server_cluster_async(transport: str = "grpc_asyncio"): +async def test_update_game_server_cluster_async( + transport: str = "grpc_asyncio", + request_type=game_server_clusters.UpdateGameServerClusterRequest, +): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_clusters.UpdateGameServerClusterRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_cluster), "__call__" + type(client.transport.update_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1786,12 +1932,17 @@ async def test_update_game_server_cluster_async(transport: str = "grpc_asyncio") assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_clusters.UpdateGameServerClusterRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_update_game_server_cluster_async_from_dict(): + await test_update_game_server_cluster_async(request_type=dict) + + def test_update_game_server_cluster_field_headers(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1804,7 +1955,7 @@ def test_update_game_server_cluster_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_cluster), "__call__" + type(client.transport.update_game_server_cluster), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -1836,7 +1987,7 @@ async def test_update_game_server_cluster_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_cluster), "__call__" + type(client.transport.update_game_server_cluster), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -1864,7 +2015,7 @@ def test_update_game_server_cluster_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_cluster), "__call__" + type(client.transport.update_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1915,7 +2066,7 @@ async def test_update_game_server_cluster_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_cluster), "__call__" + type(client.transport.update_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1976,7 +2127,7 @@ def test_preview_update_game_server_cluster( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_update_game_server_cluster), "__call__" + type(client.transport.preview_update_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_clusters.PreviewUpdateGameServerClusterResponse( @@ -1992,6 +2143,7 @@ def test_preview_update_game_server_cluster( assert args[0] == game_server_clusters.PreviewUpdateGameServerClusterRequest() # Establish that the response is the type that we expect. + assert isinstance( response, game_server_clusters.PreviewUpdateGameServerClusterResponse ) @@ -2006,6 +2158,7 @@ def test_preview_update_game_server_cluster_from_dict(): @pytest.mark.asyncio async def test_preview_update_game_server_cluster_async( transport: str = "grpc_asyncio", + request_type=game_server_clusters.PreviewUpdateGameServerClusterRequest, ): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, @@ -2013,11 +2166,11 @@ async def test_preview_update_game_server_cluster_async( # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_clusters.PreviewUpdateGameServerClusterRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_update_game_server_cluster), "__call__" + type(client.transport.preview_update_game_server_cluster), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -2032,7 +2185,7 @@ async def test_preview_update_game_server_cluster_async( assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_clusters.PreviewUpdateGameServerClusterRequest() # Establish that the response is the type that we expect. assert isinstance( @@ -2042,6 +2195,11 @@ async def test_preview_update_game_server_cluster_async( assert response.etag == "etag_value" +@pytest.mark.asyncio +async def test_preview_update_game_server_cluster_async_from_dict(): + await test_preview_update_game_server_cluster_async(request_type=dict) + + def test_preview_update_game_server_cluster_field_headers(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), @@ -2054,7 +2212,7 @@ def test_preview_update_game_server_cluster_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_update_game_server_cluster), "__call__" + type(client.transport.preview_update_game_server_cluster), "__call__" ) as call: call.return_value = ( game_server_clusters.PreviewUpdateGameServerClusterResponse() @@ -2088,7 +2246,7 @@ async def test_preview_update_game_server_cluster_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_update_game_server_cluster), "__call__" + type(client.transport.preview_update_game_server_cluster), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_clusters.PreviewUpdateGameServerClusterResponse() @@ -2145,7 +2303,7 @@ def test_transport_instance(): credentials=credentials.AnonymousCredentials(), ) client = GameServerClustersServiceClient(transport=transport) - assert client._transport is transport + assert client.transport is transport def test_transport_get_channel(): @@ -2163,13 +2321,28 @@ def test_transport_get_channel(): assert channel +@pytest.mark.parametrize( + "transport_class", + [ + transports.GameServerClustersServiceGrpcTransport, + transports.GameServerClustersServiceGrpcAsyncIOTransport, + ], +) +def test_transport_adc(transport_class): + # Test default credentials are used if not provided. + with mock.patch.object(auth, "default") as adc: + adc.return_value = (credentials.AnonymousCredentials(), None) + transport_class() + adc.assert_called_once() + + def test_transport_grpc_default(): # A client should use the gRPC transport by default. client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), ) assert isinstance( - client._transport, transports.GameServerClustersServiceGrpcTransport, + client.transport, transports.GameServerClustersServiceGrpcTransport, ) @@ -2233,6 +2406,17 @@ def test_game_server_clusters_service_base_transport_with_credentials_file(): ) +def test_game_server_clusters_service_base_transport_with_adc(): + # Test the default credentials are used if credentials and credentials_file are None. + with mock.patch.object(auth, "default") as adc, mock.patch( + "google.cloud.gaming_v1beta.services.game_server_clusters_service.transports.GameServerClustersServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (credentials.AnonymousCredentials(), None) + transport = transports.GameServerClustersServiceTransport() + adc.assert_called_once() + + def test_game_server_clusters_service_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(auth, "default") as adc: @@ -2265,7 +2449,7 @@ def test_game_server_clusters_service_host_no_port(): api_endpoint="gameservices.googleapis.com" ), ) - assert client._transport._host == "gameservices.googleapis.com:443" + assert client.transport._host == "gameservices.googleapis.com:443" def test_game_server_clusters_service_host_with_port(): @@ -2275,192 +2459,126 @@ def test_game_server_clusters_service_host_with_port(): api_endpoint="gameservices.googleapis.com:8000" ), ) - assert client._transport._host == "gameservices.googleapis.com:8000" + assert client.transport._host == "gameservices.googleapis.com:8000" def test_game_server_clusters_service_grpc_transport_channel(): channel = grpc.insecure_channel("http://localhost/") - # Check that if channel is provided, mtls endpoint and client_cert_source - # won't be used. - callback = mock.MagicMock() + # Check that channel is used if provided. transport = transports.GameServerClustersServiceGrpcTransport( - host="squid.clam.whelk", - channel=channel, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=callback, + host="squid.clam.whelk", channel=channel, ) assert transport.grpc_channel == channel assert transport._host == "squid.clam.whelk:443" - assert not callback.called + assert transport._ssl_channel_credentials == None def test_game_server_clusters_service_grpc_asyncio_transport_channel(): channel = aio.insecure_channel("http://localhost/") - # Check that if channel is provided, mtls endpoint and client_cert_source - # won't be used. - callback = mock.MagicMock() + # Check that channel is used if provided. transport = transports.GameServerClustersServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - channel=channel, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=callback, + host="squid.clam.whelk", channel=channel, ) assert transport.grpc_channel == channel assert transport._host == "squid.clam.whelk:443" - assert not callback.called - - -@mock.patch("grpc.ssl_channel_credentials", autospec=True) -@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) -def test_game_server_clusters_service_grpc_transport_channel_mtls_with_client_cert_source( - grpc_create_channel, grpc_ssl_channel_cred -): - # Check that if channel is None, but api_mtls_endpoint and client_cert_source - # are provided, then a mTLS channel will be created. - mock_cred = mock.Mock() - - mock_ssl_cred = mock.Mock() - grpc_ssl_channel_cred.return_value = mock_ssl_cred - - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - transport = transports.GameServerClustersServiceGrpcTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=client_cert_source_callback, - ) - grpc_ssl_channel_cred.assert_called_once_with( - certificate_chain=b"cert bytes", private_key=b"key bytes" - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel - - -@mock.patch("grpc.ssl_channel_credentials", autospec=True) -@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) -def test_game_server_clusters_service_grpc_asyncio_transport_channel_mtls_with_client_cert_source( - grpc_create_channel, grpc_ssl_channel_cred -): - # Check that if channel is None, but api_mtls_endpoint and client_cert_source - # are provided, then a mTLS channel will be created. - mock_cred = mock.Mock() - - mock_ssl_cred = mock.Mock() - grpc_ssl_channel_cred.return_value = mock_ssl_cred - - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - transport = transports.GameServerClustersServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=client_cert_source_callback, - ) - grpc_ssl_channel_cred.assert_called_once_with( - certificate_chain=b"cert bytes", private_key=b"key bytes" - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == None @pytest.mark.parametrize( - "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] + "transport_class", + [ + transports.GameServerClustersServiceGrpcTransport, + transports.GameServerClustersServiceGrpcAsyncIOTransport, + ], ) -@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) -def test_game_server_clusters_service_grpc_transport_channel_mtls_with_adc( - grpc_create_channel, api_mtls_endpoint +def test_game_server_clusters_service_transport_channel_mtls_with_client_cert_source( + transport_class, ): - # Check that if channel and client_cert_source are None, but api_mtls_endpoint - # is provided, then a mTLS channel will be created with SSL ADC. - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - # Mock google.auth.transport.grpc.SslCredentials class. - mock_ssl_cred = mock.Mock() - with mock.patch.multiple( - "google.auth.transport.grpc.SslCredentials", - __init__=mock.Mock(return_value=None), - ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), - ): - mock_cred = mock.Mock() - transport = transports.GameServerClustersServiceGrpcTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint=api_mtls_endpoint, - client_cert_source=None, - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + with mock.patch( + "grpc.ssl_channel_credentials", autospec=True + ) as grpc_ssl_channel_cred: + with mock.patch.object( + transport_class, "create_channel", autospec=True + ) as grpc_create_channel: + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + cred = credentials.AnonymousCredentials() + with pytest.warns(DeprecationWarning): + with mock.patch.object(auth, "default") as adc: + adc.return_value = (cred, None) + transport = transport_class( + host="squid.clam.whelk", + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + adc.assert_called_once() + + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + ) + assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == mock_ssl_cred @pytest.mark.parametrize( - "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] + "transport_class", + [ + transports.GameServerClustersServiceGrpcTransport, + transports.GameServerClustersServiceGrpcAsyncIOTransport, + ], ) -@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) -def test_game_server_clusters_service_grpc_asyncio_transport_channel_mtls_with_adc( - grpc_create_channel, api_mtls_endpoint -): - # Check that if channel and client_cert_source are None, but api_mtls_endpoint - # is provided, then a mTLS channel will be created with SSL ADC. - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - # Mock google.auth.transport.grpc.SslCredentials class. +def test_game_server_clusters_service_transport_channel_mtls_with_adc(transport_class): mock_ssl_cred = mock.Mock() with mock.patch.multiple( "google.auth.transport.grpc.SslCredentials", __init__=mock.Mock(return_value=None), ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), ): - mock_cred = mock.Mock() - transport = transports.GameServerClustersServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint=api_mtls_endpoint, - client_cert_source=None, - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + with mock.patch.object( + transport_class, "create_channel", autospec=True + ) as grpc_create_channel: + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + mock_cred = mock.Mock() + + with pytest.warns(DeprecationWarning): + transport = transport_class( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=None, + ) + + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + ) + assert transport.grpc_channel == mock_grpc_channel def test_game_server_clusters_service_grpc_lro_client(): client = GameServerClustersServiceClient( credentials=credentials.AnonymousCredentials(), transport="grpc", ) - transport = client._transport + transport = client.transport # Ensure that we have a api-core operations client. assert isinstance(transport.operations_client, operations_v1.OperationsClient,) @@ -2473,7 +2591,7 @@ def test_game_server_clusters_service_grpc_lro_async_client(): client = GameServerClustersServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport="grpc_asyncio", ) - transport = client._client._transport + transport = client.transport # Ensure that we have a api-core operations client. assert isinstance(transport.operations_client, operations_v1.OperationsAsyncClient,) @@ -2509,3 +2627,127 @@ def test_parse_game_server_cluster_path(): # Check that the path construction is reversible. actual = GameServerClustersServiceClient.parse_game_server_cluster_path(path) assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "winkle" + + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = GameServerClustersServiceClient.common_billing_account_path( + billing_account + ) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "nautilus", + } + path = GameServerClustersServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerClustersServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "scallop" + + expected = "folders/{folder}".format(folder=folder,) + actual = GameServerClustersServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "abalone", + } + path = GameServerClustersServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerClustersServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "squid" + + expected = "organizations/{organization}".format(organization=organization,) + actual = GameServerClustersServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "clam", + } + path = GameServerClustersServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerClustersServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "whelk" + + expected = "projects/{project}".format(project=project,) + actual = GameServerClustersServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "octopus", + } + path = GameServerClustersServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerClustersServiceClient.parse_common_project_path(path) + assert expected == actual + + +def test_common_location_path(): + project = "oyster" + location = "nudibranch" + + expected = "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + actual = GameServerClustersServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "cuttlefish", + "location": "mussel", + } + path = GameServerClustersServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerClustersServiceClient.parse_common_location_path(path) + assert expected == actual + + +def test_client_withDEFAULT_CLIENT_INFO(): + client_info = gapic_v1.client_info.ClientInfo() + + with mock.patch.object( + transports.GameServerClustersServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = GameServerClustersServiceClient( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.GameServerClustersServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = GameServerClustersServiceClient.get_transport_class() + transport = transport_class( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) diff --git a/tests/unit/gapic/gaming_v1beta/test_game_server_configs_service.py b/tests/unit/gapic/gaming_v1beta/test_game_server_configs_service.py index 90e4939b..3dfc58bd 100644 --- a/tests/unit/gapic/gaming_v1beta/test_game_server_configs_service.py +++ b/tests/unit/gapic/gaming_v1beta/test_game_server_configs_service.py @@ -31,7 +31,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async -from google.api_core import operation_async +from google.api_core import operation_async # type: ignore from google.api_core import operations_v1 from google.auth import credentials from google.auth.exceptions import MutualTLSChannelError @@ -107,12 +107,12 @@ def test_game_server_configs_service_client_from_service_account_file(client_cla ) as factory: factory.return_value = creds client = client_class.from_service_account_file("dummy/file/path.json") - assert client._transport._credentials == creds + assert client.transport._credentials == creds client = client_class.from_service_account_json("dummy/file/path.json") - assert client._transport._credentials == creds + assert client.transport._credentials == creds - assert client._transport._host == "gameservices.googleapis.com:443" + assert client.transport._host == "gameservices.googleapis.com:443" def test_game_server_configs_service_client_get_transport_class(): @@ -176,14 +176,14 @@ def test_game_server_configs_service_client_client_options( credentials_file=None, host="squid.clam.whelk", scopes=None, - api_mtls_endpoint="squid.clam.whelk", - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is # "never". - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "never"}): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None client = client_class() @@ -192,14 +192,14 @@ def test_game_server_configs_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is # "always". - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "always"}): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None client = client_class() @@ -208,90 +208,185 @@ def test_game_server_configs_service_client_client_options( credentials_file=None, host=client.DEFAULT_MTLS_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", and client_cert_source is provided. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError): + client = client_class() + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError): + client = client_class() + + # Check the case quota_project_id is provided + options = client_options.ClientOptions(quota_project_id="octopus") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + ssl_channel_credentials=None, + quota_project_id="octopus", + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,use_client_cert_env", + [ + ( + GameServerConfigsServiceClient, + transports.GameServerConfigsServiceGrpcTransport, + "grpc", + "true", + ), + ( + GameServerConfigsServiceAsyncClient, + transports.GameServerConfigsServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + ( + GameServerConfigsServiceClient, + transports.GameServerConfigsServiceGrpcTransport, + "grpc", + "false", + ), + ( + GameServerConfigsServiceAsyncClient, + transports.GameServerConfigsServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ], +) +@mock.patch.object( + GameServerConfigsServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GameServerConfigsServiceClient), +) +@mock.patch.object( + GameServerConfigsServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GameServerConfigsServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_game_server_configs_service_client_mtls_env_auto( + client_class, transport_class, transport_name, use_client_cert_env +): + # This tests the endpoint autoswitch behavior. Endpoint is autoswitched to the default + # mtls endpoint, if GOOGLE_API_USE_CLIENT_CERTIFICATE is "true" and client cert exists. + + # Check the case client_cert_source is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): options = client_options.ClientOptions( client_cert_source=client_cert_source_callback ) with mock.patch.object(transport_class, "__init__") as patched: - patched.return_value = None - client = client_class(client_options=options) - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_MTLS_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=client_cert_source_callback, - quota_project_id=None, - ) - - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", and default_client_cert_source is provided. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): - with mock.patch.object(transport_class, "__init__") as patched: + ssl_channel_creds = mock.Mock() with mock.patch( - "google.auth.transport.mtls.has_default_client_cert_source", - return_value=True, + "grpc.ssl_channel_credentials", return_value=ssl_channel_creds ): patched.return_value = None - client = client_class() + 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 + patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_MTLS_ENDPOINT, + host=expected_host, scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=expected_ssl_channel_creds, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", but client_cert_source and default_client_cert_source are None. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): + # Check the case ADC client cert is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + 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, + "google.auth.transport.grpc.SslCredentials.__init__", return_value=None ): - patched.return_value = None - client = client_class() - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, - quota_project_id=None, - ) - - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS has - # unsupported value. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "Unsupported"}): - with pytest.raises(MutualTLSChannelError): - client = client_class() - - # Check the case quota_project_id is provided - options = client_options.ClientOptions(quota_project_id="octopus") - with mock.patch.object(transport_class, "__init__") as patched: - patched.return_value = None - client = client_class(client_options=options) - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, - quota_project_id="octopus", - ) + 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, + ) + + # 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, + scopes=None, + ssl_channel_credentials=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) @pytest.mark.parametrize( @@ -322,9 +417,9 @@ def test_game_server_configs_service_client_client_options_scopes( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=["1", "2"], - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -356,9 +451,9 @@ def test_game_server_configs_service_client_client_options_credentials_file( credentials_file="credentials.json", host=client.DEFAULT_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -375,9 +470,9 @@ def test_game_server_configs_service_client_client_options_from_dict(): credentials_file=None, host="squid.clam.whelk", scopes=None, - api_mtls_endpoint="squid.clam.whelk", - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -395,7 +490,7 @@ def test_list_game_server_configs( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_configs), "__call__" + type(client.transport.list_game_server_configs), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_configs.ListGameServerConfigsResponse( @@ -411,6 +506,7 @@ def test_list_game_server_configs( assert args[0] == game_server_configs.ListGameServerConfigsRequest() # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListGameServerConfigsPager) assert response.next_page_token == "next_page_token_value" @@ -423,18 +519,21 @@ def test_list_game_server_configs_from_dict(): @pytest.mark.asyncio -async def test_list_game_server_configs_async(transport: str = "grpc_asyncio"): +async def test_list_game_server_configs_async( + transport: str = "grpc_asyncio", + request_type=game_server_configs.ListGameServerConfigsRequest, +): client = GameServerConfigsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_configs.ListGameServerConfigsRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_configs), "__call__" + type(client.transport.list_game_server_configs), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -450,7 +549,7 @@ async def test_list_game_server_configs_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_configs.ListGameServerConfigsRequest() # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListGameServerConfigsAsyncPager) @@ -460,6 +559,11 @@ async def test_list_game_server_configs_async(transport: str = "grpc_asyncio"): assert response.unreachable == ["unreachable_value"] +@pytest.mark.asyncio +async def test_list_game_server_configs_async_from_dict(): + await test_list_game_server_configs_async(request_type=dict) + + def test_list_game_server_configs_field_headers(): client = GameServerConfigsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -472,7 +576,7 @@ def test_list_game_server_configs_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_configs), "__call__" + type(client.transport.list_game_server_configs), "__call__" ) as call: call.return_value = game_server_configs.ListGameServerConfigsResponse() @@ -501,7 +605,7 @@ async def test_list_game_server_configs_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_configs), "__call__" + type(client.transport.list_game_server_configs), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_configs.ListGameServerConfigsResponse() @@ -526,7 +630,7 @@ def test_list_game_server_configs_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_configs), "__call__" + type(client.transport.list_game_server_configs), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_configs.ListGameServerConfigsResponse() @@ -564,7 +668,7 @@ async def test_list_game_server_configs_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_configs), "__call__" + type(client.transport.list_game_server_configs), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_configs.ListGameServerConfigsResponse() @@ -605,7 +709,7 @@ def test_list_game_server_configs_pager(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_configs), "__call__" + type(client.transport.list_game_server_configs), "__call__" ) as call: # Set the response to a series of pages. call.side_effect = ( @@ -653,7 +757,7 @@ def test_list_game_server_configs_pages(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_configs), "__call__" + type(client.transport.list_game_server_configs), "__call__" ) as call: # Set the response to a series of pages. call.side_effect = ( @@ -681,8 +785,8 @@ def test_list_game_server_configs_pages(): RuntimeError, ) pages = list(client.list_game_server_configs(request={}).pages) - for page, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page.raw_page.next_page_token == token + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token @pytest.mark.asyncio @@ -693,7 +797,7 @@ async def test_list_game_server_configs_async_pager(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_configs), + type(client.transport.list_game_server_configs), "__call__", new_callable=mock.AsyncMock, ) as call: @@ -742,7 +846,7 @@ async def test_list_game_server_configs_async_pages(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_configs), + type(client.transport.list_game_server_configs), "__call__", new_callable=mock.AsyncMock, ) as call: @@ -772,10 +876,10 @@ async def test_list_game_server_configs_async_pages(): RuntimeError, ) pages = [] - async for page in (await client.list_game_server_configs(request={})).pages: - pages.append(page) - for page, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page.raw_page.next_page_token == token + async for page_ in (await client.list_game_server_configs(request={})).pages: + pages.append(page_) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token def test_get_game_server_config( @@ -791,7 +895,7 @@ def test_get_game_server_config( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_config), "__call__" + type(client.transport.get_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_configs.GameServerConfig( @@ -807,6 +911,7 @@ def test_get_game_server_config( assert args[0] == game_server_configs.GetGameServerConfigRequest() # Establish that the response is the type that we expect. + assert isinstance(response, game_server_configs.GameServerConfig) assert response.name == "name_value" @@ -819,18 +924,21 @@ def test_get_game_server_config_from_dict(): @pytest.mark.asyncio -async def test_get_game_server_config_async(transport: str = "grpc_asyncio"): +async def test_get_game_server_config_async( + transport: str = "grpc_asyncio", + request_type=game_server_configs.GetGameServerConfigRequest, +): client = GameServerConfigsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_configs.GetGameServerConfigRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_config), "__call__" + type(client.transport.get_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -845,7 +953,7 @@ async def test_get_game_server_config_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_configs.GetGameServerConfigRequest() # Establish that the response is the type that we expect. assert isinstance(response, game_server_configs.GameServerConfig) @@ -855,6 +963,11 @@ async def test_get_game_server_config_async(transport: str = "grpc_asyncio"): assert response.description == "description_value" +@pytest.mark.asyncio +async def test_get_game_server_config_async_from_dict(): + await test_get_game_server_config_async(request_type=dict) + + def test_get_game_server_config_field_headers(): client = GameServerConfigsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -867,7 +980,7 @@ def test_get_game_server_config_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_config), "__call__" + type(client.transport.get_game_server_config), "__call__" ) as call: call.return_value = game_server_configs.GameServerConfig() @@ -896,7 +1009,7 @@ async def test_get_game_server_config_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_config), "__call__" + type(client.transport.get_game_server_config), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_configs.GameServerConfig() @@ -921,7 +1034,7 @@ def test_get_game_server_config_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_config), "__call__" + type(client.transport.get_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_configs.GameServerConfig() @@ -959,7 +1072,7 @@ async def test_get_game_server_config_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_config), "__call__" + type(client.transport.get_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_configs.GameServerConfig() @@ -1007,7 +1120,7 @@ def test_create_game_server_config( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_config), "__call__" + type(client.transport.create_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1029,18 +1142,21 @@ def test_create_game_server_config_from_dict(): @pytest.mark.asyncio -async def test_create_game_server_config_async(transport: str = "grpc_asyncio"): +async def test_create_game_server_config_async( + transport: str = "grpc_asyncio", + request_type=game_server_configs.CreateGameServerConfigRequest, +): client = GameServerConfigsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_configs.CreateGameServerConfigRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_config), "__call__" + type(client.transport.create_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1053,12 +1169,17 @@ async def test_create_game_server_config_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_configs.CreateGameServerConfigRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_create_game_server_config_async_from_dict(): + await test_create_game_server_config_async(request_type=dict) + + def test_create_game_server_config_field_headers(): client = GameServerConfigsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1071,7 +1192,7 @@ def test_create_game_server_config_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_config), "__call__" + type(client.transport.create_game_server_config), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -1100,7 +1221,7 @@ async def test_create_game_server_config_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_config), "__call__" + type(client.transport.create_game_server_config), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -1125,7 +1246,7 @@ def test_create_game_server_config_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_config), "__call__" + type(client.transport.create_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1172,7 +1293,7 @@ async def test_create_game_server_config_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_config), "__call__" + type(client.transport.create_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1229,7 +1350,7 @@ def test_delete_game_server_config( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_config), "__call__" + type(client.transport.delete_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1251,18 +1372,21 @@ def test_delete_game_server_config_from_dict(): @pytest.mark.asyncio -async def test_delete_game_server_config_async(transport: str = "grpc_asyncio"): +async def test_delete_game_server_config_async( + transport: str = "grpc_asyncio", + request_type=game_server_configs.DeleteGameServerConfigRequest, +): client = GameServerConfigsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_configs.DeleteGameServerConfigRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_config), "__call__" + type(client.transport.delete_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1275,12 +1399,17 @@ async def test_delete_game_server_config_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_configs.DeleteGameServerConfigRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_delete_game_server_config_async_from_dict(): + await test_delete_game_server_config_async(request_type=dict) + + def test_delete_game_server_config_field_headers(): client = GameServerConfigsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1293,7 +1422,7 @@ def test_delete_game_server_config_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_config), "__call__" + type(client.transport.delete_game_server_config), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -1322,7 +1451,7 @@ async def test_delete_game_server_config_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_config), "__call__" + type(client.transport.delete_game_server_config), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -1347,7 +1476,7 @@ def test_delete_game_server_config_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_config), "__call__" + type(client.transport.delete_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1385,7 +1514,7 @@ async def test_delete_game_server_config_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_config), "__call__" + type(client.transport.delete_game_server_config), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1455,7 +1584,7 @@ def test_transport_instance(): credentials=credentials.AnonymousCredentials(), ) client = GameServerConfigsServiceClient(transport=transport) - assert client._transport is transport + assert client.transport is transport def test_transport_get_channel(): @@ -1473,13 +1602,28 @@ def test_transport_get_channel(): assert channel +@pytest.mark.parametrize( + "transport_class", + [ + transports.GameServerConfigsServiceGrpcTransport, + transports.GameServerConfigsServiceGrpcAsyncIOTransport, + ], +) +def test_transport_adc(transport_class): + # Test default credentials are used if not provided. + with mock.patch.object(auth, "default") as adc: + adc.return_value = (credentials.AnonymousCredentials(), None) + transport_class() + adc.assert_called_once() + + def test_transport_grpc_default(): # A client should use the gRPC transport by default. client = GameServerConfigsServiceClient( credentials=credentials.AnonymousCredentials(), ) assert isinstance( - client._transport, transports.GameServerConfigsServiceGrpcTransport, + client.transport, transports.GameServerConfigsServiceGrpcTransport, ) @@ -1539,6 +1683,17 @@ def test_game_server_configs_service_base_transport_with_credentials_file(): ) +def test_game_server_configs_service_base_transport_with_adc(): + # Test the default credentials are used if credentials and credentials_file are None. + with mock.patch.object(auth, "default") as adc, mock.patch( + "google.cloud.gaming_v1beta.services.game_server_configs_service.transports.GameServerConfigsServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (credentials.AnonymousCredentials(), None) + transport = transports.GameServerConfigsServiceTransport() + adc.assert_called_once() + + def test_game_server_configs_service_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(auth, "default") as adc: @@ -1571,7 +1726,7 @@ def test_game_server_configs_service_host_no_port(): api_endpoint="gameservices.googleapis.com" ), ) - assert client._transport._host == "gameservices.googleapis.com:443" + assert client.transport._host == "gameservices.googleapis.com:443" def test_game_server_configs_service_host_with_port(): @@ -1581,192 +1736,126 @@ def test_game_server_configs_service_host_with_port(): api_endpoint="gameservices.googleapis.com:8000" ), ) - assert client._transport._host == "gameservices.googleapis.com:8000" + assert client.transport._host == "gameservices.googleapis.com:8000" def test_game_server_configs_service_grpc_transport_channel(): channel = grpc.insecure_channel("http://localhost/") - # Check that if channel is provided, mtls endpoint and client_cert_source - # won't be used. - callback = mock.MagicMock() + # Check that channel is used if provided. transport = transports.GameServerConfigsServiceGrpcTransport( - host="squid.clam.whelk", - channel=channel, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=callback, + host="squid.clam.whelk", channel=channel, ) assert transport.grpc_channel == channel assert transport._host == "squid.clam.whelk:443" - assert not callback.called + assert transport._ssl_channel_credentials == None def test_game_server_configs_service_grpc_asyncio_transport_channel(): channel = aio.insecure_channel("http://localhost/") - # Check that if channel is provided, mtls endpoint and client_cert_source - # won't be used. - callback = mock.MagicMock() + # Check that channel is used if provided. transport = transports.GameServerConfigsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - channel=channel, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=callback, + host="squid.clam.whelk", channel=channel, ) assert transport.grpc_channel == channel assert transport._host == "squid.clam.whelk:443" - assert not callback.called - - -@mock.patch("grpc.ssl_channel_credentials", autospec=True) -@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) -def test_game_server_configs_service_grpc_transport_channel_mtls_with_client_cert_source( - grpc_create_channel, grpc_ssl_channel_cred -): - # Check that if channel is None, but api_mtls_endpoint and client_cert_source - # are provided, then a mTLS channel will be created. - mock_cred = mock.Mock() - - mock_ssl_cred = mock.Mock() - grpc_ssl_channel_cred.return_value = mock_ssl_cred - - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - transport = transports.GameServerConfigsServiceGrpcTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=client_cert_source_callback, - ) - grpc_ssl_channel_cred.assert_called_once_with( - certificate_chain=b"cert bytes", private_key=b"key bytes" - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel - - -@mock.patch("grpc.ssl_channel_credentials", autospec=True) -@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) -def test_game_server_configs_service_grpc_asyncio_transport_channel_mtls_with_client_cert_source( - grpc_create_channel, grpc_ssl_channel_cred -): - # Check that if channel is None, but api_mtls_endpoint and client_cert_source - # are provided, then a mTLS channel will be created. - mock_cred = mock.Mock() - - mock_ssl_cred = mock.Mock() - grpc_ssl_channel_cred.return_value = mock_ssl_cred - - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - transport = transports.GameServerConfigsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=client_cert_source_callback, - ) - grpc_ssl_channel_cred.assert_called_once_with( - certificate_chain=b"cert bytes", private_key=b"key bytes" - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == None @pytest.mark.parametrize( - "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] + "transport_class", + [ + transports.GameServerConfigsServiceGrpcTransport, + transports.GameServerConfigsServiceGrpcAsyncIOTransport, + ], ) -@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) -def test_game_server_configs_service_grpc_transport_channel_mtls_with_adc( - grpc_create_channel, api_mtls_endpoint +def test_game_server_configs_service_transport_channel_mtls_with_client_cert_source( + transport_class, ): - # Check that if channel and client_cert_source are None, but api_mtls_endpoint - # is provided, then a mTLS channel will be created with SSL ADC. - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - # Mock google.auth.transport.grpc.SslCredentials class. - mock_ssl_cred = mock.Mock() - with mock.patch.multiple( - "google.auth.transport.grpc.SslCredentials", - __init__=mock.Mock(return_value=None), - ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), - ): - mock_cred = mock.Mock() - transport = transports.GameServerConfigsServiceGrpcTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint=api_mtls_endpoint, - client_cert_source=None, - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + with mock.patch( + "grpc.ssl_channel_credentials", autospec=True + ) as grpc_ssl_channel_cred: + with mock.patch.object( + transport_class, "create_channel", autospec=True + ) as grpc_create_channel: + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + cred = credentials.AnonymousCredentials() + with pytest.warns(DeprecationWarning): + with mock.patch.object(auth, "default") as adc: + adc.return_value = (cred, None) + transport = transport_class( + host="squid.clam.whelk", + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + adc.assert_called_once() + + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + ) + assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == mock_ssl_cred @pytest.mark.parametrize( - "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] + "transport_class", + [ + transports.GameServerConfigsServiceGrpcTransport, + transports.GameServerConfigsServiceGrpcAsyncIOTransport, + ], ) -@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) -def test_game_server_configs_service_grpc_asyncio_transport_channel_mtls_with_adc( - grpc_create_channel, api_mtls_endpoint -): - # Check that if channel and client_cert_source are None, but api_mtls_endpoint - # is provided, then a mTLS channel will be created with SSL ADC. - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - # Mock google.auth.transport.grpc.SslCredentials class. +def test_game_server_configs_service_transport_channel_mtls_with_adc(transport_class): mock_ssl_cred = mock.Mock() with mock.patch.multiple( "google.auth.transport.grpc.SslCredentials", __init__=mock.Mock(return_value=None), ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), ): - mock_cred = mock.Mock() - transport = transports.GameServerConfigsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint=api_mtls_endpoint, - client_cert_source=None, - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + with mock.patch.object( + transport_class, "create_channel", autospec=True + ) as grpc_create_channel: + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + mock_cred = mock.Mock() + + with pytest.warns(DeprecationWarning): + transport = transport_class( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=None, + ) + + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + ) + assert transport.grpc_channel == mock_grpc_channel def test_game_server_configs_service_grpc_lro_client(): client = GameServerConfigsServiceClient( credentials=credentials.AnonymousCredentials(), transport="grpc", ) - transport = client._transport + transport = client.transport # Ensure that we have a api-core operations client. assert isinstance(transport.operations_client, operations_v1.OperationsClient,) @@ -1779,7 +1868,7 @@ def test_game_server_configs_service_grpc_lro_async_client(): client = GameServerConfigsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport="grpc_asyncio", ) - transport = client._client._transport + transport = client.transport # Ensure that we have a api-core operations client. assert isinstance(transport.operations_client, operations_v1.OperationsAsyncClient,) @@ -1815,3 +1904,125 @@ def test_parse_game_server_config_path(): # Check that the path construction is reversible. actual = GameServerConfigsServiceClient.parse_game_server_config_path(path) assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "winkle" + + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = GameServerConfigsServiceClient.common_billing_account_path(billing_account) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "nautilus", + } + path = GameServerConfigsServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerConfigsServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "scallop" + + expected = "folders/{folder}".format(folder=folder,) + actual = GameServerConfigsServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "abalone", + } + path = GameServerConfigsServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerConfigsServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "squid" + + expected = "organizations/{organization}".format(organization=organization,) + actual = GameServerConfigsServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "clam", + } + path = GameServerConfigsServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerConfigsServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "whelk" + + expected = "projects/{project}".format(project=project,) + actual = GameServerConfigsServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "octopus", + } + path = GameServerConfigsServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerConfigsServiceClient.parse_common_project_path(path) + assert expected == actual + + +def test_common_location_path(): + project = "oyster" + location = "nudibranch" + + expected = "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + actual = GameServerConfigsServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "cuttlefish", + "location": "mussel", + } + path = GameServerConfigsServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerConfigsServiceClient.parse_common_location_path(path) + assert expected == actual + + +def test_client_withDEFAULT_CLIENT_INFO(): + client_info = gapic_v1.client_info.ClientInfo() + + with mock.patch.object( + transports.GameServerConfigsServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = GameServerConfigsServiceClient( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.GameServerConfigsServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = GameServerConfigsServiceClient.get_transport_class() + transport = transport_class( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) diff --git a/tests/unit/gapic/gaming_v1beta/test_game_server_deployments_service.py b/tests/unit/gapic/gaming_v1beta/test_game_server_deployments_service.py index f4255984..e56c8556 100644 --- a/tests/unit/gapic/gaming_v1beta/test_game_server_deployments_service.py +++ b/tests/unit/gapic/gaming_v1beta/test_game_server_deployments_service.py @@ -31,7 +31,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async -from google.api_core import operation_async +from google.api_core import operation_async # type: ignore from google.api_core import operations_v1 from google.auth import credentials from google.auth.exceptions import MutualTLSChannelError @@ -111,12 +111,12 @@ def test_game_server_deployments_service_client_from_service_account_file(client ) as factory: factory.return_value = creds client = client_class.from_service_account_file("dummy/file/path.json") - assert client._transport._credentials == creds + assert client.transport._credentials == creds client = client_class.from_service_account_json("dummy/file/path.json") - assert client._transport._credentials == creds + assert client.transport._credentials == creds - assert client._transport._host == "gameservices.googleapis.com:443" + assert client.transport._host == "gameservices.googleapis.com:443" def test_game_server_deployments_service_client_get_transport_class(): @@ -180,14 +180,14 @@ def test_game_server_deployments_service_client_client_options( credentials_file=None, host="squid.clam.whelk", scopes=None, - api_mtls_endpoint="squid.clam.whelk", - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is # "never". - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "never"}): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None client = client_class() @@ -196,14 +196,14 @@ def test_game_server_deployments_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is # "always". - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "always"}): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None client = client_class() @@ -212,90 +212,185 @@ def test_game_server_deployments_service_client_client_options( credentials_file=None, host=client.DEFAULT_MTLS_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", and client_cert_source is provided. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError): + client = client_class() + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError): + client = client_class() + + # Check the case quota_project_id is provided + options = client_options.ClientOptions(quota_project_id="octopus") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + ssl_channel_credentials=None, + quota_project_id="octopus", + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,use_client_cert_env", + [ + ( + GameServerDeploymentsServiceClient, + transports.GameServerDeploymentsServiceGrpcTransport, + "grpc", + "true", + ), + ( + GameServerDeploymentsServiceAsyncClient, + transports.GameServerDeploymentsServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + ( + GameServerDeploymentsServiceClient, + transports.GameServerDeploymentsServiceGrpcTransport, + "grpc", + "false", + ), + ( + GameServerDeploymentsServiceAsyncClient, + transports.GameServerDeploymentsServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ], +) +@mock.patch.object( + GameServerDeploymentsServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GameServerDeploymentsServiceClient), +) +@mock.patch.object( + GameServerDeploymentsServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GameServerDeploymentsServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_game_server_deployments_service_client_mtls_env_auto( + client_class, transport_class, transport_name, use_client_cert_env +): + # This tests the endpoint autoswitch behavior. Endpoint is autoswitched to the default + # mtls endpoint, if GOOGLE_API_USE_CLIENT_CERTIFICATE is "true" and client cert exists. + + # Check the case client_cert_source is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): options = client_options.ClientOptions( client_cert_source=client_cert_source_callback ) with mock.patch.object(transport_class, "__init__") as patched: - patched.return_value = None - client = client_class(client_options=options) - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_MTLS_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=client_cert_source_callback, - quota_project_id=None, - ) - - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", and default_client_cert_source is provided. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): - with mock.patch.object(transport_class, "__init__") as patched: + ssl_channel_creds = mock.Mock() with mock.patch( - "google.auth.transport.mtls.has_default_client_cert_source", - return_value=True, + "grpc.ssl_channel_credentials", return_value=ssl_channel_creds ): patched.return_value = None - client = client_class() + 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 + patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_MTLS_ENDPOINT, + host=expected_host, scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=expected_ssl_channel_creds, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", but client_cert_source and default_client_cert_source are None. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): + # Check the case ADC client cert is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + 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, + "google.auth.transport.grpc.SslCredentials.__init__", return_value=None ): - patched.return_value = None - client = client_class() - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, - quota_project_id=None, - ) - - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS has - # unsupported value. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "Unsupported"}): - with pytest.raises(MutualTLSChannelError): - client = client_class() - - # Check the case quota_project_id is provided - options = client_options.ClientOptions(quota_project_id="octopus") - with mock.patch.object(transport_class, "__init__") as patched: - patched.return_value = None - client = client_class(client_options=options) - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, - quota_project_id="octopus", - ) + 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, + ) + + # 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, + scopes=None, + ssl_channel_credentials=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) @pytest.mark.parametrize( @@ -326,9 +421,9 @@ def test_game_server_deployments_service_client_client_options_scopes( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=["1", "2"], - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -360,9 +455,9 @@ def test_game_server_deployments_service_client_client_options_credentials_file( credentials_file="credentials.json", host=client.DEFAULT_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -379,9 +474,9 @@ def test_game_server_deployments_service_client_client_options_from_dict(): credentials_file=None, host="squid.clam.whelk", scopes=None, - api_mtls_endpoint="squid.clam.whelk", - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -399,7 +494,7 @@ def test_list_game_server_deployments( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_deployments), "__call__" + type(client.transport.list_game_server_deployments), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.ListGameServerDeploymentsResponse( @@ -415,6 +510,7 @@ def test_list_game_server_deployments( assert args[0] == game_server_deployments.ListGameServerDeploymentsRequest() # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListGameServerDeploymentsPager) assert response.next_page_token == "next_page_token_value" @@ -427,18 +523,21 @@ def test_list_game_server_deployments_from_dict(): @pytest.mark.asyncio -async def test_list_game_server_deployments_async(transport: str = "grpc_asyncio"): +async def test_list_game_server_deployments_async( + transport: str = "grpc_asyncio", + request_type=game_server_deployments.ListGameServerDeploymentsRequest, +): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.ListGameServerDeploymentsRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_deployments), "__call__" + type(client.transport.list_game_server_deployments), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -454,7 +553,7 @@ async def test_list_game_server_deployments_async(transport: str = "grpc_asyncio assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_deployments.ListGameServerDeploymentsRequest() # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListGameServerDeploymentsAsyncPager) @@ -464,6 +563,11 @@ async def test_list_game_server_deployments_async(transport: str = "grpc_asyncio assert response.unreachable == ["unreachable_value"] +@pytest.mark.asyncio +async def test_list_game_server_deployments_async_from_dict(): + await test_list_game_server_deployments_async(request_type=dict) + + def test_list_game_server_deployments_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -476,7 +580,7 @@ def test_list_game_server_deployments_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_deployments), "__call__" + type(client.transport.list_game_server_deployments), "__call__" ) as call: call.return_value = game_server_deployments.ListGameServerDeploymentsResponse() @@ -505,7 +609,7 @@ async def test_list_game_server_deployments_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_deployments), "__call__" + type(client.transport.list_game_server_deployments), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_deployments.ListGameServerDeploymentsResponse() @@ -530,7 +634,7 @@ def test_list_game_server_deployments_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_deployments), "__call__" + type(client.transport.list_game_server_deployments), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.ListGameServerDeploymentsResponse() @@ -569,7 +673,7 @@ async def test_list_game_server_deployments_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_deployments), "__call__" + type(client.transport.list_game_server_deployments), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.ListGameServerDeploymentsResponse() @@ -611,7 +715,7 @@ def test_list_game_server_deployments_pager(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_deployments), "__call__" + type(client.transport.list_game_server_deployments), "__call__" ) as call: # Set the response to a series of pages. call.side_effect = ( @@ -663,7 +767,7 @@ def test_list_game_server_deployments_pages(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.list_game_server_deployments), "__call__" + type(client.transport.list_game_server_deployments), "__call__" ) as call: # Set the response to a series of pages. call.side_effect = ( @@ -693,8 +797,8 @@ def test_list_game_server_deployments_pages(): RuntimeError, ) pages = list(client.list_game_server_deployments(request={}).pages) - for page, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page.raw_page.next_page_token == token + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token @pytest.mark.asyncio @@ -705,7 +809,7 @@ async def test_list_game_server_deployments_async_pager(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_deployments), + type(client.transport.list_game_server_deployments), "__call__", new_callable=mock.AsyncMock, ) as call: @@ -757,7 +861,7 @@ async def test_list_game_server_deployments_async_pages(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_game_server_deployments), + type(client.transport.list_game_server_deployments), "__call__", new_callable=mock.AsyncMock, ) as call: @@ -789,10 +893,12 @@ async def test_list_game_server_deployments_async_pages(): RuntimeError, ) pages = [] - async for page in (await client.list_game_server_deployments(request={})).pages: - pages.append(page) - for page, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page.raw_page.next_page_token == token + async for page_ in ( + await client.list_game_server_deployments(request={}) + ).pages: + pages.append(page_) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token def test_get_game_server_deployment( @@ -809,7 +915,7 @@ def test_get_game_server_deployment( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_deployment), "__call__" + type(client.transport.get_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.GameServerDeployment( @@ -825,6 +931,7 @@ def test_get_game_server_deployment( assert args[0] == game_server_deployments.GetGameServerDeploymentRequest() # Establish that the response is the type that we expect. + assert isinstance(response, game_server_deployments.GameServerDeployment) assert response.name == "name_value" @@ -839,18 +946,21 @@ def test_get_game_server_deployment_from_dict(): @pytest.mark.asyncio -async def test_get_game_server_deployment_async(transport: str = "grpc_asyncio"): +async def test_get_game_server_deployment_async( + transport: str = "grpc_asyncio", + request_type=game_server_deployments.GetGameServerDeploymentRequest, +): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.GetGameServerDeploymentRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_deployment), "__call__" + type(client.transport.get_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -865,7 +975,7 @@ async def test_get_game_server_deployment_async(transport: str = "grpc_asyncio") assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_deployments.GetGameServerDeploymentRequest() # Establish that the response is the type that we expect. assert isinstance(response, game_server_deployments.GameServerDeployment) @@ -877,6 +987,11 @@ async def test_get_game_server_deployment_async(transport: str = "grpc_asyncio") assert response.description == "description_value" +@pytest.mark.asyncio +async def test_get_game_server_deployment_async_from_dict(): + await test_get_game_server_deployment_async(request_type=dict) + + def test_get_game_server_deployment_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -889,7 +1004,7 @@ def test_get_game_server_deployment_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_deployment), "__call__" + type(client.transport.get_game_server_deployment), "__call__" ) as call: call.return_value = game_server_deployments.GameServerDeployment() @@ -918,7 +1033,7 @@ async def test_get_game_server_deployment_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_deployment), "__call__" + type(client.transport.get_game_server_deployment), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_deployments.GameServerDeployment() @@ -943,7 +1058,7 @@ def test_get_game_server_deployment_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_deployment), "__call__" + type(client.transport.get_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.GameServerDeployment() @@ -981,7 +1096,7 @@ async def test_get_game_server_deployment_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_deployment), "__call__" + type(client.transport.get_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.GameServerDeployment() @@ -1029,7 +1144,7 @@ def test_create_game_server_deployment( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_deployment), "__call__" + type(client.transport.create_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1051,18 +1166,21 @@ def test_create_game_server_deployment_from_dict(): @pytest.mark.asyncio -async def test_create_game_server_deployment_async(transport: str = "grpc_asyncio"): +async def test_create_game_server_deployment_async( + transport: str = "grpc_asyncio", + request_type=game_server_deployments.CreateGameServerDeploymentRequest, +): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.CreateGameServerDeploymentRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_deployment), "__call__" + type(client.transport.create_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1075,12 +1193,17 @@ async def test_create_game_server_deployment_async(transport: str = "grpc_asynci assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_deployments.CreateGameServerDeploymentRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_create_game_server_deployment_async_from_dict(): + await test_create_game_server_deployment_async(request_type=dict) + + def test_create_game_server_deployment_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1093,7 +1216,7 @@ def test_create_game_server_deployment_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_deployment), "__call__" + type(client.transport.create_game_server_deployment), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -1122,7 +1245,7 @@ async def test_create_game_server_deployment_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_deployment), "__call__" + type(client.transport.create_game_server_deployment), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -1147,7 +1270,7 @@ def test_create_game_server_deployment_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.create_game_server_deployment), "__call__" + type(client.transport.create_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1200,7 +1323,7 @@ async def test_create_game_server_deployment_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.create_game_server_deployment), "__call__" + type(client.transport.create_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1263,7 +1386,7 @@ def test_delete_game_server_deployment( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_deployment), "__call__" + type(client.transport.delete_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1285,18 +1408,21 @@ def test_delete_game_server_deployment_from_dict(): @pytest.mark.asyncio -async def test_delete_game_server_deployment_async(transport: str = "grpc_asyncio"): +async def test_delete_game_server_deployment_async( + transport: str = "grpc_asyncio", + request_type=game_server_deployments.DeleteGameServerDeploymentRequest, +): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.DeleteGameServerDeploymentRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_deployment), "__call__" + type(client.transport.delete_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1309,12 +1435,17 @@ async def test_delete_game_server_deployment_async(transport: str = "grpc_asynci assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_deployments.DeleteGameServerDeploymentRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_delete_game_server_deployment_async_from_dict(): + await test_delete_game_server_deployment_async(request_type=dict) + + def test_delete_game_server_deployment_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1327,7 +1458,7 @@ def test_delete_game_server_deployment_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_deployment), "__call__" + type(client.transport.delete_game_server_deployment), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -1356,7 +1487,7 @@ async def test_delete_game_server_deployment_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_deployment), "__call__" + type(client.transport.delete_game_server_deployment), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -1381,7 +1512,7 @@ def test_delete_game_server_deployment_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.delete_game_server_deployment), "__call__" + type(client.transport.delete_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1420,7 +1551,7 @@ async def test_delete_game_server_deployment_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.delete_game_server_deployment), "__call__" + type(client.transport.delete_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1469,7 +1600,7 @@ def test_update_game_server_deployment( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_deployment), "__call__" + type(client.transport.update_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1491,18 +1622,21 @@ def test_update_game_server_deployment_from_dict(): @pytest.mark.asyncio -async def test_update_game_server_deployment_async(transport: str = "grpc_asyncio"): +async def test_update_game_server_deployment_async( + transport: str = "grpc_asyncio", + request_type=game_server_deployments.UpdateGameServerDeploymentRequest, +): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.UpdateGameServerDeploymentRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_deployment), "__call__" + type(client.transport.update_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1515,12 +1649,17 @@ async def test_update_game_server_deployment_async(transport: str = "grpc_asynci assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_deployments.UpdateGameServerDeploymentRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_update_game_server_deployment_async_from_dict(): + await test_update_game_server_deployment_async(request_type=dict) + + def test_update_game_server_deployment_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1533,7 +1672,7 @@ def test_update_game_server_deployment_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_deployment), "__call__" + type(client.transport.update_game_server_deployment), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -1565,7 +1704,7 @@ async def test_update_game_server_deployment_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_deployment), "__call__" + type(client.transport.update_game_server_deployment), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -1593,7 +1732,7 @@ def test_update_game_server_deployment_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_deployment), "__call__" + type(client.transport.update_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1646,7 +1785,7 @@ async def test_update_game_server_deployment_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_deployment), "__call__" + type(client.transport.update_game_server_deployment), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1709,7 +1848,7 @@ def test_get_game_server_deployment_rollout( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_deployment_rollout), "__call__" + type(client.transport.get_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.GameServerDeploymentRollout( @@ -1729,6 +1868,7 @@ def test_get_game_server_deployment_rollout( ) # Establish that the response is the type that we expect. + assert isinstance(response, game_server_deployments.GameServerDeploymentRollout) assert response.name == "name_value" @@ -1745,6 +1885,7 @@ def test_get_game_server_deployment_rollout_from_dict(): @pytest.mark.asyncio async def test_get_game_server_deployment_rollout_async( transport: str = "grpc_asyncio", + request_type=game_server_deployments.GetGameServerDeploymentRolloutRequest, ): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, @@ -1752,11 +1893,11 @@ async def test_get_game_server_deployment_rollout_async( # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.GetGameServerDeploymentRolloutRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_deployment_rollout), "__call__" + type(client.transport.get_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1773,7 +1914,9 @@ async def test_get_game_server_deployment_rollout_async( assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert ( + args[0] == game_server_deployments.GetGameServerDeploymentRolloutRequest() + ) # Establish that the response is the type that we expect. assert isinstance(response, game_server_deployments.GameServerDeploymentRollout) @@ -1785,6 +1928,11 @@ async def test_get_game_server_deployment_rollout_async( assert response.etag == "etag_value" +@pytest.mark.asyncio +async def test_get_game_server_deployment_rollout_async_from_dict(): + await test_get_game_server_deployment_rollout_async(request_type=dict) + + def test_get_game_server_deployment_rollout_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -1797,7 +1945,7 @@ def test_get_game_server_deployment_rollout_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_deployment_rollout), "__call__" + type(client.transport.get_game_server_deployment_rollout), "__call__" ) as call: call.return_value = game_server_deployments.GameServerDeploymentRollout() @@ -1826,7 +1974,7 @@ async def test_get_game_server_deployment_rollout_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_deployment_rollout), "__call__" + type(client.transport.get_game_server_deployment_rollout), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_deployments.GameServerDeploymentRollout() @@ -1851,7 +1999,7 @@ def test_get_game_server_deployment_rollout_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.get_game_server_deployment_rollout), "__call__" + type(client.transport.get_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.GameServerDeploymentRollout() @@ -1890,7 +2038,7 @@ async def test_get_game_server_deployment_rollout_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.get_game_server_deployment_rollout), "__call__" + type(client.transport.get_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.GameServerDeploymentRollout() @@ -1939,7 +2087,7 @@ def test_update_game_server_deployment_rollout( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_deployment_rollout), "__call__" + type(client.transport.update_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1966,6 +2114,7 @@ def test_update_game_server_deployment_rollout_from_dict(): @pytest.mark.asyncio async def test_update_game_server_deployment_rollout_async( transport: str = "grpc_asyncio", + request_type=game_server_deployments.UpdateGameServerDeploymentRolloutRequest, ): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, @@ -1973,12 +2122,11 @@ async def test_update_game_server_deployment_rollout_async( # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.UpdateGameServerDeploymentRolloutRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_deployment_rollout), - "__call__", + type(client.transport.update_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1991,12 +2139,20 @@ async def test_update_game_server_deployment_rollout_async( assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert ( + args[0] + == game_server_deployments.UpdateGameServerDeploymentRolloutRequest() + ) # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_update_game_server_deployment_rollout_async_from_dict(): + await test_update_game_server_deployment_rollout_async(request_type=dict) + + def test_update_game_server_deployment_rollout_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -2009,7 +2165,7 @@ def test_update_game_server_deployment_rollout_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_deployment_rollout), "__call__" + type(client.transport.update_game_server_deployment_rollout), "__call__" ) as call: call.return_value = operations_pb2.Operation(name="operations/op") @@ -2040,8 +2196,7 @@ async def test_update_game_server_deployment_rollout_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_deployment_rollout), - "__call__", + type(client.transport.update_game_server_deployment_rollout), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") @@ -2068,7 +2223,7 @@ def test_update_game_server_deployment_rollout_flattened(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.update_game_server_deployment_rollout), "__call__" + type(client.transport.update_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -2119,8 +2274,7 @@ async def test_update_game_server_deployment_rollout_flattened_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.update_game_server_deployment_rollout), - "__call__", + type(client.transport.update_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -2181,7 +2335,7 @@ def test_preview_game_server_deployment_rollout( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_game_server_deployment_rollout), "__call__" + type(client.transport.preview_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.PreviewGameServerDeploymentRolloutResponse( @@ -2200,6 +2354,7 @@ def test_preview_game_server_deployment_rollout( ) # Establish that the response is the type that we expect. + assert isinstance( response, game_server_deployments.PreviewGameServerDeploymentRolloutResponse ) @@ -2216,6 +2371,7 @@ def test_preview_game_server_deployment_rollout_from_dict(): @pytest.mark.asyncio async def test_preview_game_server_deployment_rollout_async( transport: str = "grpc_asyncio", + request_type=game_server_deployments.PreviewGameServerDeploymentRolloutRequest, ): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, @@ -2223,12 +2379,11 @@ async def test_preview_game_server_deployment_rollout_async( # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.PreviewGameServerDeploymentRolloutRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_game_server_deployment_rollout), - "__call__", + type(client.transport.preview_game_server_deployment_rollout), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -2243,7 +2398,10 @@ async def test_preview_game_server_deployment_rollout_async( assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert ( + args[0] + == game_server_deployments.PreviewGameServerDeploymentRolloutRequest() + ) # Establish that the response is the type that we expect. assert isinstance( @@ -2255,6 +2413,11 @@ async def test_preview_game_server_deployment_rollout_async( assert response.etag == "etag_value" +@pytest.mark.asyncio +async def test_preview_game_server_deployment_rollout_async_from_dict(): + await test_preview_game_server_deployment_rollout_async(request_type=dict) + + def test_preview_game_server_deployment_rollout_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -2267,7 +2430,7 @@ def test_preview_game_server_deployment_rollout_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_game_server_deployment_rollout), "__call__" + type(client.transport.preview_game_server_deployment_rollout), "__call__" ) as call: call.return_value = ( game_server_deployments.PreviewGameServerDeploymentRolloutResponse() @@ -2300,8 +2463,7 @@ async def test_preview_game_server_deployment_rollout_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_game_server_deployment_rollout), - "__call__", + type(client.transport.preview_game_server_deployment_rollout), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_deployments.PreviewGameServerDeploymentRolloutResponse() @@ -2335,7 +2497,7 @@ def test_fetch_deployment_state( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.fetch_deployment_state), "__call__" + type(client.transport.fetch_deployment_state), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = game_server_deployments.FetchDeploymentStateResponse( @@ -2351,6 +2513,7 @@ def test_fetch_deployment_state( assert args[0] == game_server_deployments.FetchDeploymentStateRequest() # Establish that the response is the type that we expect. + assert isinstance(response, game_server_deployments.FetchDeploymentStateResponse) assert response.unavailable == ["unavailable_value"] @@ -2361,18 +2524,21 @@ def test_fetch_deployment_state_from_dict(): @pytest.mark.asyncio -async def test_fetch_deployment_state_async(transport: str = "grpc_asyncio"): +async def test_fetch_deployment_state_async( + transport: str = "grpc_asyncio", + request_type=game_server_deployments.FetchDeploymentStateRequest, +): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = game_server_deployments.FetchDeploymentStateRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.fetch_deployment_state), "__call__" + type(client.transport.fetch_deployment_state), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -2387,7 +2553,7 @@ async def test_fetch_deployment_state_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == game_server_deployments.FetchDeploymentStateRequest() # Establish that the response is the type that we expect. assert isinstance(response, game_server_deployments.FetchDeploymentStateResponse) @@ -2395,6 +2561,11 @@ async def test_fetch_deployment_state_async(transport: str = "grpc_asyncio"): assert response.unavailable == ["unavailable_value"] +@pytest.mark.asyncio +async def test_fetch_deployment_state_async_from_dict(): + await test_fetch_deployment_state_async(request_type=dict) + + def test_fetch_deployment_state_field_headers(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), @@ -2407,7 +2578,7 @@ def test_fetch_deployment_state_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.fetch_deployment_state), "__call__" + type(client.transport.fetch_deployment_state), "__call__" ) as call: call.return_value = game_server_deployments.FetchDeploymentStateResponse() @@ -2436,7 +2607,7 @@ async def test_fetch_deployment_state_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.fetch_deployment_state), "__call__" + type(client.transport.fetch_deployment_state), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( game_server_deployments.FetchDeploymentStateResponse() @@ -2490,7 +2661,7 @@ def test_transport_instance(): credentials=credentials.AnonymousCredentials(), ) client = GameServerDeploymentsServiceClient(transport=transport) - assert client._transport is transport + assert client.transport is transport def test_transport_get_channel(): @@ -2508,13 +2679,28 @@ def test_transport_get_channel(): assert channel +@pytest.mark.parametrize( + "transport_class", + [ + transports.GameServerDeploymentsServiceGrpcTransport, + transports.GameServerDeploymentsServiceGrpcAsyncIOTransport, + ], +) +def test_transport_adc(transport_class): + # Test default credentials are used if not provided. + with mock.patch.object(auth, "default") as adc: + adc.return_value = (credentials.AnonymousCredentials(), None) + transport_class() + adc.assert_called_once() + + def test_transport_grpc_default(): # A client should use the gRPC transport by default. client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), ) assert isinstance( - client._transport, transports.GameServerDeploymentsServiceGrpcTransport, + client.transport, transports.GameServerDeploymentsServiceGrpcTransport, ) @@ -2579,6 +2765,17 @@ def test_game_server_deployments_service_base_transport_with_credentials_file(): ) +def test_game_server_deployments_service_base_transport_with_adc(): + # Test the default credentials are used if credentials and credentials_file are None. + with mock.patch.object(auth, "default") as adc, mock.patch( + "google.cloud.gaming_v1beta.services.game_server_deployments_service.transports.GameServerDeploymentsServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (credentials.AnonymousCredentials(), None) + transport = transports.GameServerDeploymentsServiceTransport() + adc.assert_called_once() + + def test_game_server_deployments_service_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(auth, "default") as adc: @@ -2611,7 +2808,7 @@ def test_game_server_deployments_service_host_no_port(): api_endpoint="gameservices.googleapis.com" ), ) - assert client._transport._host == "gameservices.googleapis.com:443" + assert client.transport._host == "gameservices.googleapis.com:443" def test_game_server_deployments_service_host_with_port(): @@ -2621,192 +2818,128 @@ def test_game_server_deployments_service_host_with_port(): api_endpoint="gameservices.googleapis.com:8000" ), ) - assert client._transport._host == "gameservices.googleapis.com:8000" + assert client.transport._host == "gameservices.googleapis.com:8000" def test_game_server_deployments_service_grpc_transport_channel(): channel = grpc.insecure_channel("http://localhost/") - # Check that if channel is provided, mtls endpoint and client_cert_source - # won't be used. - callback = mock.MagicMock() + # Check that channel is used if provided. transport = transports.GameServerDeploymentsServiceGrpcTransport( - host="squid.clam.whelk", - channel=channel, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=callback, + host="squid.clam.whelk", channel=channel, ) assert transport.grpc_channel == channel assert transport._host == "squid.clam.whelk:443" - assert not callback.called + assert transport._ssl_channel_credentials == None def test_game_server_deployments_service_grpc_asyncio_transport_channel(): channel = aio.insecure_channel("http://localhost/") - # Check that if channel is provided, mtls endpoint and client_cert_source - # won't be used. - callback = mock.MagicMock() + # Check that channel is used if provided. transport = transports.GameServerDeploymentsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - channel=channel, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=callback, + host="squid.clam.whelk", channel=channel, ) assert transport.grpc_channel == channel assert transport._host == "squid.clam.whelk:443" - assert not callback.called - - -@mock.patch("grpc.ssl_channel_credentials", autospec=True) -@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) -def test_game_server_deployments_service_grpc_transport_channel_mtls_with_client_cert_source( - grpc_create_channel, grpc_ssl_channel_cred -): - # Check that if channel is None, but api_mtls_endpoint and client_cert_source - # are provided, then a mTLS channel will be created. - mock_cred = mock.Mock() - - mock_ssl_cred = mock.Mock() - grpc_ssl_channel_cred.return_value = mock_ssl_cred - - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - transport = transports.GameServerDeploymentsServiceGrpcTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=client_cert_source_callback, - ) - grpc_ssl_channel_cred.assert_called_once_with( - certificate_chain=b"cert bytes", private_key=b"key bytes" - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel - - -@mock.patch("grpc.ssl_channel_credentials", autospec=True) -@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) -def test_game_server_deployments_service_grpc_asyncio_transport_channel_mtls_with_client_cert_source( - grpc_create_channel, grpc_ssl_channel_cred -): - # Check that if channel is None, but api_mtls_endpoint and client_cert_source - # are provided, then a mTLS channel will be created. - mock_cred = mock.Mock() - - mock_ssl_cred = mock.Mock() - grpc_ssl_channel_cred.return_value = mock_ssl_cred - - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - transport = transports.GameServerDeploymentsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=client_cert_source_callback, - ) - grpc_ssl_channel_cred.assert_called_once_with( - certificate_chain=b"cert bytes", private_key=b"key bytes" - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == None @pytest.mark.parametrize( - "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] + "transport_class", + [ + transports.GameServerDeploymentsServiceGrpcTransport, + transports.GameServerDeploymentsServiceGrpcAsyncIOTransport, + ], ) -@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) -def test_game_server_deployments_service_grpc_transport_channel_mtls_with_adc( - grpc_create_channel, api_mtls_endpoint +def test_game_server_deployments_service_transport_channel_mtls_with_client_cert_source( + transport_class, ): - # Check that if channel and client_cert_source are None, but api_mtls_endpoint - # is provided, then a mTLS channel will be created with SSL ADC. - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - # Mock google.auth.transport.grpc.SslCredentials class. - mock_ssl_cred = mock.Mock() - with mock.patch.multiple( - "google.auth.transport.grpc.SslCredentials", - __init__=mock.Mock(return_value=None), - ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), - ): - mock_cred = mock.Mock() - transport = transports.GameServerDeploymentsServiceGrpcTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint=api_mtls_endpoint, - client_cert_source=None, - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + with mock.patch( + "grpc.ssl_channel_credentials", autospec=True + ) as grpc_ssl_channel_cred: + with mock.patch.object( + transport_class, "create_channel", autospec=True + ) as grpc_create_channel: + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + cred = credentials.AnonymousCredentials() + with pytest.warns(DeprecationWarning): + with mock.patch.object(auth, "default") as adc: + adc.return_value = (cred, None) + transport = transport_class( + host="squid.clam.whelk", + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + adc.assert_called_once() + + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + ) + assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == mock_ssl_cred @pytest.mark.parametrize( - "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] + "transport_class", + [ + transports.GameServerDeploymentsServiceGrpcTransport, + transports.GameServerDeploymentsServiceGrpcAsyncIOTransport, + ], ) -@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) -def test_game_server_deployments_service_grpc_asyncio_transport_channel_mtls_with_adc( - grpc_create_channel, api_mtls_endpoint +def test_game_server_deployments_service_transport_channel_mtls_with_adc( + transport_class, ): - # Check that if channel and client_cert_source are None, but api_mtls_endpoint - # is provided, then a mTLS channel will be created with SSL ADC. - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - # Mock google.auth.transport.grpc.SslCredentials class. mock_ssl_cred = mock.Mock() with mock.patch.multiple( "google.auth.transport.grpc.SslCredentials", __init__=mock.Mock(return_value=None), ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), ): - mock_cred = mock.Mock() - transport = transports.GameServerDeploymentsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint=api_mtls_endpoint, - client_cert_source=None, - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + with mock.patch.object( + transport_class, "create_channel", autospec=True + ) as grpc_create_channel: + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + mock_cred = mock.Mock() + + with pytest.warns(DeprecationWarning): + transport = transport_class( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=None, + ) + + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + ) + assert transport.grpc_channel == mock_grpc_channel def test_game_server_deployments_service_grpc_lro_client(): client = GameServerDeploymentsServiceClient( credentials=credentials.AnonymousCredentials(), transport="grpc", ) - transport = client._transport + transport = client.transport # Ensure that we have a api-core operations client. assert isinstance(transport.operations_client, operations_v1.OperationsClient,) @@ -2819,7 +2952,7 @@ def test_game_server_deployments_service_grpc_lro_async_client(): client = GameServerDeploymentsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport="grpc_asyncio", ) - transport = client._client._transport + transport = client.transport # Ensure that we have a api-core operations client. assert isinstance(transport.operations_client, operations_v1.OperationsAsyncClient,) @@ -2856,9 +2989,9 @@ def test_parse_game_server_deployment_path(): def test_game_server_deployment_rollout_path(): - project = "squid" - location = "clam" - deployment = "whelk" + project = "cuttlefish" + location = "mussel" + deployment = "winkle" expected = "projects/{project}/locations/{location}/gameServerDeployments/{deployment}/rollout".format( project=project, location=location, deployment=deployment, @@ -2871,9 +3004,9 @@ def test_game_server_deployment_rollout_path(): def test_parse_game_server_deployment_rollout_path(): expected = { - "project": "octopus", - "location": "oyster", - "deployment": "nudibranch", + "project": "nautilus", + "location": "scallop", + "deployment": "abalone", } path = GameServerDeploymentsServiceClient.game_server_deployment_rollout_path( **expected @@ -2884,3 +3017,127 @@ def test_parse_game_server_deployment_rollout_path(): path ) assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "squid" + + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = GameServerDeploymentsServiceClient.common_billing_account_path( + billing_account + ) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "clam", + } + path = GameServerDeploymentsServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerDeploymentsServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "whelk" + + expected = "folders/{folder}".format(folder=folder,) + actual = GameServerDeploymentsServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "octopus", + } + path = GameServerDeploymentsServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerDeploymentsServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "oyster" + + expected = "organizations/{organization}".format(organization=organization,) + actual = GameServerDeploymentsServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "nudibranch", + } + path = GameServerDeploymentsServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerDeploymentsServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "cuttlefish" + + expected = "projects/{project}".format(project=project,) + actual = GameServerDeploymentsServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "mussel", + } + path = GameServerDeploymentsServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerDeploymentsServiceClient.parse_common_project_path(path) + assert expected == actual + + +def test_common_location_path(): + project = "winkle" + location = "nautilus" + + expected = "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + actual = GameServerDeploymentsServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "scallop", + "location": "abalone", + } + path = GameServerDeploymentsServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = GameServerDeploymentsServiceClient.parse_common_location_path(path) + assert expected == actual + + +def test_client_withDEFAULT_CLIENT_INFO(): + client_info = gapic_v1.client_info.ClientInfo() + + with mock.patch.object( + transports.GameServerDeploymentsServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = GameServerDeploymentsServiceClient( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.GameServerDeploymentsServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = GameServerDeploymentsServiceClient.get_transport_class() + transport = transport_class( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) diff --git a/tests/unit/gapic/gaming_v1beta/test_realms_service.py b/tests/unit/gapic/gaming_v1beta/test_realms_service.py index 3a120bd1..c018403e 100644 --- a/tests/unit/gapic/gaming_v1beta/test_realms_service.py +++ b/tests/unit/gapic/gaming_v1beta/test_realms_service.py @@ -31,7 +31,7 @@ from google.api_core import gapic_v1 from google.api_core import grpc_helpers from google.api_core import grpc_helpers_async -from google.api_core import operation_async +from google.api_core import operation_async # type: ignore from google.api_core import operations_v1 from google.auth import credentials from google.auth.exceptions import MutualTLSChannelError @@ -101,12 +101,12 @@ def test_realms_service_client_from_service_account_file(client_class): ) as factory: factory.return_value = creds client = client_class.from_service_account_file("dummy/file/path.json") - assert client._transport._credentials == creds + assert client.transport._credentials == creds client = client_class.from_service_account_json("dummy/file/path.json") - assert client._transport._credentials == creds + assert client.transport._credentials == creds - assert client._transport._host == "gameservices.googleapis.com:443" + assert client.transport._host == "gameservices.googleapis.com:443" def test_realms_service_client_get_transport_class(): @@ -162,14 +162,14 @@ def test_realms_service_client_client_options( credentials_file=None, host="squid.clam.whelk", scopes=None, - api_mtls_endpoint="squid.clam.whelk", - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is # "never". - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "never"}): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None client = client_class() @@ -178,14 +178,14 @@ def test_realms_service_client_client_options( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS is + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is # "always". - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "always"}): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): with mock.patch.object(transport_class, "__init__") as patched: patched.return_value = None client = client_class() @@ -194,90 +194,175 @@ def test_realms_service_client_client_options( credentials_file=None, host=client.DEFAULT_MTLS_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", and client_cert_source is provided. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError): + client = client_class() + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError): + client = client_class() + + # Check the case quota_project_id is provided + options = client_options.ClientOptions(quota_project_id="octopus") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + ssl_channel_credentials=None, + quota_project_id="octopus", + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,use_client_cert_env", + [ + (RealmsServiceClient, transports.RealmsServiceGrpcTransport, "grpc", "true"), + ( + RealmsServiceAsyncClient, + transports.RealmsServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + (RealmsServiceClient, transports.RealmsServiceGrpcTransport, "grpc", "false"), + ( + RealmsServiceAsyncClient, + transports.RealmsServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ], +) +@mock.patch.object( + RealmsServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(RealmsServiceClient), +) +@mock.patch.object( + RealmsServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(RealmsServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_realms_service_client_mtls_env_auto( + client_class, transport_class, transport_name, use_client_cert_env +): + # This tests the endpoint autoswitch behavior. Endpoint is autoswitched to the default + # mtls endpoint, if GOOGLE_API_USE_CLIENT_CERTIFICATE is "true" and client cert exists. + + # Check the case client_cert_source is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): options = client_options.ClientOptions( client_cert_source=client_cert_source_callback ) with mock.patch.object(transport_class, "__init__") as patched: - patched.return_value = None - client = client_class(client_options=options) - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_MTLS_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=client_cert_source_callback, - quota_project_id=None, - ) - - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", and default_client_cert_source is provided. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): - with mock.patch.object(transport_class, "__init__") as patched: + ssl_channel_creds = mock.Mock() with mock.patch( - "google.auth.transport.mtls.has_default_client_cert_source", - return_value=True, + "grpc.ssl_channel_credentials", return_value=ssl_channel_creds ): patched.return_value = None - client = client_class() + 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 + patched.assert_called_once_with( credentials=None, credentials_file=None, - host=client.DEFAULT_MTLS_ENDPOINT, + host=expected_host, scopes=None, - api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=expected_ssl_channel_creds, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) - # Check the case api_endpoint is not provided, GOOGLE_API_USE_MTLS is - # "auto", but client_cert_source and default_client_cert_source are None. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "auto"}): + # Check the case ADC client cert is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + 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, + "google.auth.transport.grpc.SslCredentials.__init__", return_value=None ): - patched.return_value = None - client = client_class() - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, - quota_project_id=None, - ) - - # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS has - # unsupported value. - with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS": "Unsupported"}): - with pytest.raises(MutualTLSChannelError): - client = client_class() - - # Check the case quota_project_id is provided - options = client_options.ClientOptions(quota_project_id="octopus") - with mock.patch.object(transport_class, "__init__") as patched: - patched.return_value = None - client = client_class(client_options=options) - patched.assert_called_once_with( - credentials=None, - credentials_file=None, - host=client.DEFAULT_ENDPOINT, - scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, - quota_project_id="octopus", - ) + 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, + ) + + # 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, + scopes=None, + ssl_channel_credentials=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) @pytest.mark.parametrize( @@ -304,9 +389,9 @@ def test_realms_service_client_client_options_scopes( credentials_file=None, host=client.DEFAULT_ENDPOINT, scopes=["1", "2"], - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -334,9 +419,9 @@ def test_realms_service_client_client_options_credentials_file( credentials_file="credentials.json", host=client.DEFAULT_ENDPOINT, scopes=None, - api_mtls_endpoint=client.DEFAULT_ENDPOINT, - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -353,9 +438,9 @@ def test_realms_service_client_client_options_from_dict(): credentials_file=None, host="squid.clam.whelk", scopes=None, - api_mtls_endpoint="squid.clam.whelk", - client_cert_source=None, + ssl_channel_credentials=None, quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, ) @@ -369,7 +454,7 @@ def test_list_realms(transport: str = "grpc", request_type=realms.ListRealmsRequ request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.list_realms), "__call__") as call: + with mock.patch.object(type(client.transport.list_realms), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = realms.ListRealmsResponse( next_page_token="next_page_token_value", unreachable=["unreachable_value"], @@ -384,6 +469,7 @@ def test_list_realms(transport: str = "grpc", request_type=realms.ListRealmsRequ assert args[0] == realms.ListRealmsRequest() # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListRealmsPager) assert response.next_page_token == "next_page_token_value" @@ -396,19 +482,19 @@ def test_list_realms_from_dict(): @pytest.mark.asyncio -async def test_list_realms_async(transport: str = "grpc_asyncio"): +async def test_list_realms_async( + transport: str = "grpc_asyncio", request_type=realms.ListRealmsRequest +): client = RealmsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = realms.ListRealmsRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.list_realms), "__call__" - ) as call: + with mock.patch.object(type(client.transport.list_realms), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( realms.ListRealmsResponse( @@ -423,7 +509,7 @@ async def test_list_realms_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == realms.ListRealmsRequest() # Establish that the response is the type that we expect. assert isinstance(response, pagers.ListRealmsAsyncPager) @@ -433,6 +519,11 @@ async def test_list_realms_async(transport: str = "grpc_asyncio"): assert response.unreachable == ["unreachable_value"] +@pytest.mark.asyncio +async def test_list_realms_async_from_dict(): + await test_list_realms_async(request_type=dict) + + def test_list_realms_field_headers(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) @@ -442,7 +533,7 @@ def test_list_realms_field_headers(): request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.list_realms), "__call__") as call: + with mock.patch.object(type(client.transport.list_realms), "__call__") as call: call.return_value = realms.ListRealmsResponse() client.list_realms(request) @@ -467,9 +558,7 @@ async def test_list_realms_field_headers_async(): request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.list_realms), "__call__" - ) as call: + with mock.patch.object(type(client.transport.list_realms), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( realms.ListRealmsResponse() ) @@ -490,7 +579,7 @@ def test_list_realms_flattened(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.list_realms), "__call__") as call: + with mock.patch.object(type(client.transport.list_realms), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = realms.ListRealmsResponse() @@ -522,9 +611,7 @@ async def test_list_realms_flattened_async(): client = RealmsServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.list_realms), "__call__" - ) as call: + with mock.patch.object(type(client.transport.list_realms), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = realms.ListRealmsResponse() @@ -559,7 +646,7 @@ def test_list_realms_pager(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials,) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.list_realms), "__call__") as call: + with mock.patch.object(type(client.transport.list_realms), "__call__") as call: # Set the response to a series of pages. call.side_effect = ( realms.ListRealmsResponse( @@ -589,7 +676,7 @@ def test_list_realms_pages(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials,) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.list_realms), "__call__") as call: + with mock.patch.object(type(client.transport.list_realms), "__call__") as call: # Set the response to a series of pages. call.side_effect = ( realms.ListRealmsResponse( @@ -602,8 +689,8 @@ def test_list_realms_pages(): RuntimeError, ) pages = list(client.list_realms(request={}).pages) - for page, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page.raw_page.next_page_token == token + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token @pytest.mark.asyncio @@ -612,9 +699,7 @@ async def test_list_realms_async_pager(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_realms), - "__call__", - new_callable=mock.AsyncMock, + type(client.transport.list_realms), "__call__", new_callable=mock.AsyncMock ) as call: # Set the response to a series of pages. call.side_effect = ( @@ -643,9 +728,7 @@ async def test_list_realms_async_pages(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.list_realms), - "__call__", - new_callable=mock.AsyncMock, + type(client.transport.list_realms), "__call__", new_callable=mock.AsyncMock ) as call: # Set the response to a series of pages. call.side_effect = ( @@ -659,10 +742,10 @@ async def test_list_realms_async_pages(): RuntimeError, ) pages = [] - async for page in (await client.list_realms(request={})).pages: - pages.append(page) - for page, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page.raw_page.next_page_token == token + async for page_ in (await client.list_realms(request={})).pages: + pages.append(page_) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token def test_get_realm(transport: str = "grpc", request_type=realms.GetRealmRequest): @@ -675,7 +758,7 @@ def test_get_realm(transport: str = "grpc", request_type=realms.GetRealmRequest) request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.get_realm), "__call__") as call: + with mock.patch.object(type(client.transport.get_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = realms.Realm( name="name_value", @@ -693,6 +776,7 @@ def test_get_realm(transport: str = "grpc", request_type=realms.GetRealmRequest) assert args[0] == realms.GetRealmRequest() # Establish that the response is the type that we expect. + assert isinstance(response, realms.Realm) assert response.name == "name_value" @@ -709,19 +793,19 @@ def test_get_realm_from_dict(): @pytest.mark.asyncio -async def test_get_realm_async(transport: str = "grpc_asyncio"): +async def test_get_realm_async( + transport: str = "grpc_asyncio", request_type=realms.GetRealmRequest +): client = RealmsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = realms.GetRealmRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.get_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.get_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( realms.Realm( @@ -738,7 +822,7 @@ async def test_get_realm_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == realms.GetRealmRequest() # Establish that the response is the type that we expect. assert isinstance(response, realms.Realm) @@ -752,6 +836,11 @@ async def test_get_realm_async(transport: str = "grpc_asyncio"): assert response.description == "description_value" +@pytest.mark.asyncio +async def test_get_realm_async_from_dict(): + await test_get_realm_async(request_type=dict) + + def test_get_realm_field_headers(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) @@ -761,7 +850,7 @@ def test_get_realm_field_headers(): request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.get_realm), "__call__") as call: + with mock.patch.object(type(client.transport.get_realm), "__call__") as call: call.return_value = realms.Realm() client.get_realm(request) @@ -786,9 +875,7 @@ async def test_get_realm_field_headers_async(): request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.get_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.get_realm), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(realms.Realm()) await client.get_realm(request) @@ -807,7 +894,7 @@ def test_get_realm_flattened(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.get_realm), "__call__") as call: + with mock.patch.object(type(client.transport.get_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = realms.Realm() @@ -839,9 +926,7 @@ async def test_get_realm_flattened_async(): client = RealmsServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.get_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.get_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = realms.Realm() @@ -880,7 +965,7 @@ def test_create_realm(transport: str = "grpc", request_type=realms.CreateRealmRe request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.create_realm), "__call__") as call: + with mock.patch.object(type(client.transport.create_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -901,19 +986,19 @@ def test_create_realm_from_dict(): @pytest.mark.asyncio -async def test_create_realm_async(transport: str = "grpc_asyncio"): +async def test_create_realm_async( + transport: str = "grpc_asyncio", request_type=realms.CreateRealmRequest +): client = RealmsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = realms.CreateRealmRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.create_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.create_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/spam") @@ -925,12 +1010,17 @@ async def test_create_realm_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == realms.CreateRealmRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_create_realm_async_from_dict(): + await test_create_realm_async(request_type=dict) + + def test_create_realm_field_headers(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) @@ -940,7 +1030,7 @@ def test_create_realm_field_headers(): request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.create_realm), "__call__") as call: + with mock.patch.object(type(client.transport.create_realm), "__call__") as call: call.return_value = operations_pb2.Operation(name="operations/op") client.create_realm(request) @@ -965,9 +1055,7 @@ async def test_create_realm_field_headers_async(): request.parent = "parent/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.create_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.create_realm), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") ) @@ -988,7 +1076,7 @@ def test_create_realm_flattened(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.create_realm), "__call__") as call: + with mock.patch.object(type(client.transport.create_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1031,9 +1119,7 @@ async def test_create_realm_flattened_async(): client = RealmsServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.create_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.create_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1085,7 +1171,7 @@ def test_delete_realm(transport: str = "grpc", request_type=realms.DeleteRealmRe request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.delete_realm), "__call__") as call: + with mock.patch.object(type(client.transport.delete_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1106,19 +1192,19 @@ def test_delete_realm_from_dict(): @pytest.mark.asyncio -async def test_delete_realm_async(transport: str = "grpc_asyncio"): +async def test_delete_realm_async( + transport: str = "grpc_asyncio", request_type=realms.DeleteRealmRequest +): client = RealmsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = realms.DeleteRealmRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.delete_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.delete_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/spam") @@ -1130,12 +1216,17 @@ async def test_delete_realm_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == realms.DeleteRealmRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_delete_realm_async_from_dict(): + await test_delete_realm_async(request_type=dict) + + def test_delete_realm_field_headers(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) @@ -1145,7 +1236,7 @@ def test_delete_realm_field_headers(): request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.delete_realm), "__call__") as call: + with mock.patch.object(type(client.transport.delete_realm), "__call__") as call: call.return_value = operations_pb2.Operation(name="operations/op") client.delete_realm(request) @@ -1170,9 +1261,7 @@ async def test_delete_realm_field_headers_async(): request.name = "name/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.delete_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.delete_realm), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") ) @@ -1193,7 +1282,7 @@ def test_delete_realm_flattened(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.delete_realm), "__call__") as call: + with mock.patch.object(type(client.transport.delete_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1225,9 +1314,7 @@ async def test_delete_realm_flattened_async(): client = RealmsServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.delete_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.delete_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1268,7 +1355,7 @@ def test_update_realm(transport: str = "grpc", request_type=realms.UpdateRealmRe request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.update_realm), "__call__") as call: + with mock.patch.object(type(client.transport.update_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/spam") @@ -1289,19 +1376,19 @@ def test_update_realm_from_dict(): @pytest.mark.asyncio -async def test_update_realm_async(transport: str = "grpc_asyncio"): +async def test_update_realm_async( + transport: str = "grpc_asyncio", request_type=realms.UpdateRealmRequest +): client = RealmsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = realms.UpdateRealmRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.update_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.update_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/spam") @@ -1313,12 +1400,17 @@ async def test_update_realm_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == realms.UpdateRealmRequest() # Establish that the response is the type that we expect. assert isinstance(response, future.Future) +@pytest.mark.asyncio +async def test_update_realm_async_from_dict(): + await test_update_realm_async(request_type=dict) + + def test_update_realm_field_headers(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) @@ -1328,7 +1420,7 @@ def test_update_realm_field_headers(): request.realm.name = "realm.name/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.update_realm), "__call__") as call: + with mock.patch.object(type(client.transport.update_realm), "__call__") as call: call.return_value = operations_pb2.Operation(name="operations/op") client.update_realm(request) @@ -1353,9 +1445,7 @@ async def test_update_realm_field_headers_async(): request.realm.name = "realm.name/value" # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.update_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.update_realm), "__call__") as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( operations_pb2.Operation(name="operations/op") ) @@ -1376,7 +1466,7 @@ def test_update_realm_flattened(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object(type(client._transport.update_realm), "__call__") as call: + with mock.patch.object(type(client.transport.update_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1415,9 +1505,7 @@ async def test_update_realm_flattened_async(): client = RealmsServiceAsyncClient(credentials=credentials.AnonymousCredentials(),) # Mock the actual call within the gRPC stub, and fake the request. - with mock.patch.object( - type(client._client._transport.update_realm), "__call__" - ) as call: + with mock.patch.object(type(client.transport.update_realm), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = operations_pb2.Operation(name="operations/op") @@ -1468,7 +1556,7 @@ def test_preview_realm_update( # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_realm_update), "__call__" + type(client.transport.preview_realm_update), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = realms.PreviewRealmUpdateResponse(etag="etag_value",) @@ -1482,6 +1570,7 @@ def test_preview_realm_update( assert args[0] == realms.PreviewRealmUpdateRequest() # Establish that the response is the type that we expect. + assert isinstance(response, realms.PreviewRealmUpdateResponse) assert response.etag == "etag_value" @@ -1492,18 +1581,20 @@ def test_preview_realm_update_from_dict(): @pytest.mark.asyncio -async def test_preview_realm_update_async(transport: str = "grpc_asyncio"): +async def test_preview_realm_update_async( + transport: str = "grpc_asyncio", request_type=realms.PreviewRealmUpdateRequest +): client = RealmsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport=transport, ) # Everything is optional in proto3 as far as the runtime is concerned, # and we are mocking out the actual API, so just send an empty request. - request = realms.PreviewRealmUpdateRequest() + request = request_type() # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_realm_update), "__call__" + type(client.transport.preview_realm_update), "__call__" ) as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( @@ -1516,7 +1607,7 @@ async def test_preview_realm_update_async(transport: str = "grpc_asyncio"): assert len(call.mock_calls) _, args, _ = call.mock_calls[0] - assert args[0] == request + assert args[0] == realms.PreviewRealmUpdateRequest() # Establish that the response is the type that we expect. assert isinstance(response, realms.PreviewRealmUpdateResponse) @@ -1524,6 +1615,11 @@ async def test_preview_realm_update_async(transport: str = "grpc_asyncio"): assert response.etag == "etag_value" +@pytest.mark.asyncio +async def test_preview_realm_update_async_from_dict(): + await test_preview_realm_update_async(request_type=dict) + + def test_preview_realm_update_field_headers(): client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) @@ -1534,7 +1630,7 @@ def test_preview_realm_update_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._transport.preview_realm_update), "__call__" + type(client.transport.preview_realm_update), "__call__" ) as call: call.return_value = realms.PreviewRealmUpdateResponse() @@ -1561,7 +1657,7 @@ async def test_preview_realm_update_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object( - type(client._client._transport.preview_realm_update), "__call__" + type(client.transport.preview_realm_update), "__call__" ) as call: call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( realms.PreviewRealmUpdateResponse() @@ -1615,7 +1711,7 @@ def test_transport_instance(): credentials=credentials.AnonymousCredentials(), ) client = RealmsServiceClient(transport=transport) - assert client._transport is transport + assert client.transport is transport def test_transport_get_channel(): @@ -1633,10 +1729,25 @@ def test_transport_get_channel(): assert channel +@pytest.mark.parametrize( + "transport_class", + [ + transports.RealmsServiceGrpcTransport, + transports.RealmsServiceGrpcAsyncIOTransport, + ], +) +def test_transport_adc(transport_class): + # Test default credentials are used if not provided. + with mock.patch.object(auth, "default") as adc: + adc.return_value = (credentials.AnonymousCredentials(), None) + transport_class() + adc.assert_called_once() + + def test_transport_grpc_default(): # A client should use the gRPC transport by default. client = RealmsServiceClient(credentials=credentials.AnonymousCredentials(),) - assert isinstance(client._transport, transports.RealmsServiceGrpcTransport,) + assert isinstance(client.transport, transports.RealmsServiceGrpcTransport,) def test_realms_service_base_transport_error(): @@ -1697,6 +1808,17 @@ def test_realms_service_base_transport_with_credentials_file(): ) +def test_realms_service_base_transport_with_adc(): + # Test the default credentials are used if credentials and credentials_file are None. + with mock.patch.object(auth, "default") as adc, mock.patch( + "google.cloud.gaming_v1beta.services.realms_service.transports.RealmsServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (credentials.AnonymousCredentials(), None) + transport = transports.RealmsServiceTransport() + adc.assert_called_once() + + def test_realms_service_auth_adc(): # If no credentials are provided, we should use ADC credentials. with mock.patch.object(auth, "default") as adc: @@ -1729,7 +1851,7 @@ def test_realms_service_host_no_port(): api_endpoint="gameservices.googleapis.com" ), ) - assert client._transport._host == "gameservices.googleapis.com:443" + assert client.transport._host == "gameservices.googleapis.com:443" def test_realms_service_host_with_port(): @@ -1739,192 +1861,124 @@ def test_realms_service_host_with_port(): api_endpoint="gameservices.googleapis.com:8000" ), ) - assert client._transport._host == "gameservices.googleapis.com:8000" + assert client.transport._host == "gameservices.googleapis.com:8000" def test_realms_service_grpc_transport_channel(): channel = grpc.insecure_channel("http://localhost/") - # Check that if channel is provided, mtls endpoint and client_cert_source - # won't be used. - callback = mock.MagicMock() + # Check that channel is used if provided. transport = transports.RealmsServiceGrpcTransport( - host="squid.clam.whelk", - channel=channel, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=callback, + host="squid.clam.whelk", channel=channel, ) assert transport.grpc_channel == channel assert transport._host == "squid.clam.whelk:443" - assert not callback.called + assert transport._ssl_channel_credentials == None def test_realms_service_grpc_asyncio_transport_channel(): channel = aio.insecure_channel("http://localhost/") - # Check that if channel is provided, mtls endpoint and client_cert_source - # won't be used. - callback = mock.MagicMock() + # Check that channel is used if provided. transport = transports.RealmsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - channel=channel, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=callback, + host="squid.clam.whelk", channel=channel, ) assert transport.grpc_channel == channel assert transport._host == "squid.clam.whelk:443" - assert not callback.called - - -@mock.patch("grpc.ssl_channel_credentials", autospec=True) -@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) -def test_realms_service_grpc_transport_channel_mtls_with_client_cert_source( - grpc_create_channel, grpc_ssl_channel_cred -): - # Check that if channel is None, but api_mtls_endpoint and client_cert_source - # are provided, then a mTLS channel will be created. - mock_cred = mock.Mock() - - mock_ssl_cred = mock.Mock() - grpc_ssl_channel_cred.return_value = mock_ssl_cred - - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - transport = transports.RealmsServiceGrpcTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=client_cert_source_callback, - ) - grpc_ssl_channel_cred.assert_called_once_with( - certificate_chain=b"cert bytes", private_key=b"key bytes" - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel - - -@mock.patch("grpc.ssl_channel_credentials", autospec=True) -@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) -def test_realms_service_grpc_asyncio_transport_channel_mtls_with_client_cert_source( - grpc_create_channel, grpc_ssl_channel_cred -): - # Check that if channel is None, but api_mtls_endpoint and client_cert_source - # are provided, then a mTLS channel will be created. - mock_cred = mock.Mock() - - mock_ssl_cred = mock.Mock() - grpc_ssl_channel_cred.return_value = mock_ssl_cred - - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - transport = transports.RealmsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint="mtls.squid.clam.whelk", - client_cert_source=client_cert_source_callback, - ) - grpc_ssl_channel_cred.assert_called_once_with( - certificate_chain=b"cert bytes", private_key=b"key bytes" - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == None @pytest.mark.parametrize( - "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] + "transport_class", + [ + transports.RealmsServiceGrpcTransport, + transports.RealmsServiceGrpcAsyncIOTransport, + ], ) -@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True) -def test_realms_service_grpc_transport_channel_mtls_with_adc( - grpc_create_channel, api_mtls_endpoint -): - # Check that if channel and client_cert_source are None, but api_mtls_endpoint - # is provided, then a mTLS channel will be created with SSL ADC. - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - # Mock google.auth.transport.grpc.SslCredentials class. - mock_ssl_cred = mock.Mock() - with mock.patch.multiple( - "google.auth.transport.grpc.SslCredentials", - __init__=mock.Mock(return_value=None), - ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), - ): - mock_cred = mock.Mock() - transport = transports.RealmsServiceGrpcTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint=api_mtls_endpoint, - client_cert_source=None, - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel +def test_realms_service_transport_channel_mtls_with_client_cert_source(transport_class): + with mock.patch( + "grpc.ssl_channel_credentials", autospec=True + ) as grpc_ssl_channel_cred: + with mock.patch.object( + transport_class, "create_channel", autospec=True + ) as grpc_create_channel: + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + cred = credentials.AnonymousCredentials() + with pytest.warns(DeprecationWarning): + with mock.patch.object(auth, "default") as adc: + adc.return_value = (cred, None) + transport = transport_class( + host="squid.clam.whelk", + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + adc.assert_called_once() + + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + ) + assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == mock_ssl_cred @pytest.mark.parametrize( - "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"] + "transport_class", + [ + transports.RealmsServiceGrpcTransport, + transports.RealmsServiceGrpcAsyncIOTransport, + ], ) -@mock.patch("google.api_core.grpc_helpers_async.create_channel", autospec=True) -def test_realms_service_grpc_asyncio_transport_channel_mtls_with_adc( - grpc_create_channel, api_mtls_endpoint -): - # Check that if channel and client_cert_source are None, but api_mtls_endpoint - # is provided, then a mTLS channel will be created with SSL ADC. - mock_grpc_channel = mock.Mock() - grpc_create_channel.return_value = mock_grpc_channel - - # Mock google.auth.transport.grpc.SslCredentials class. +def test_realms_service_transport_channel_mtls_with_adc(transport_class): mock_ssl_cred = mock.Mock() with mock.patch.multiple( "google.auth.transport.grpc.SslCredentials", __init__=mock.Mock(return_value=None), ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), ): - mock_cred = mock.Mock() - transport = transports.RealmsServiceGrpcAsyncIOTransport( - host="squid.clam.whelk", - credentials=mock_cred, - api_mtls_endpoint=api_mtls_endpoint, - client_cert_source=None, - ) - grpc_create_channel.assert_called_once_with( - "mtls.squid.clam.whelk:443", - credentials=mock_cred, - credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=mock_ssl_cred, - quota_project_id=None, - ) - assert transport.grpc_channel == mock_grpc_channel + with mock.patch.object( + transport_class, "create_channel", autospec=True + ) as grpc_create_channel: + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + mock_cred = mock.Mock() + + with pytest.warns(DeprecationWarning): + transport = transport_class( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=None, + ) + + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=("https://www.googleapis.com/auth/cloud-platform",), + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + ) + assert transport.grpc_channel == mock_grpc_channel def test_realms_service_grpc_lro_client(): client = RealmsServiceClient( credentials=credentials.AnonymousCredentials(), transport="grpc", ) - transport = client._transport + transport = client.transport # Ensure that we have a api-core operations client. assert isinstance(transport.operations_client, operations_v1.OperationsClient,) @@ -1937,7 +1991,7 @@ def test_realms_service_grpc_lro_async_client(): client = RealmsServiceAsyncClient( credentials=credentials.AnonymousCredentials(), transport="grpc_asyncio", ) - transport = client._client._transport + transport = client.transport # Ensure that we have a api-core operations client. assert isinstance(transport.operations_client, operations_v1.OperationsAsyncClient,) @@ -1969,3 +2023,125 @@ def test_parse_realm_path(): # Check that the path construction is reversible. actual = RealmsServiceClient.parse_realm_path(path) assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "cuttlefish" + + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = RealmsServiceClient.common_billing_account_path(billing_account) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "mussel", + } + path = RealmsServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = RealmsServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "winkle" + + expected = "folders/{folder}".format(folder=folder,) + actual = RealmsServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "nautilus", + } + path = RealmsServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = RealmsServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "scallop" + + expected = "organizations/{organization}".format(organization=organization,) + actual = RealmsServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "abalone", + } + path = RealmsServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = RealmsServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "squid" + + expected = "projects/{project}".format(project=project,) + actual = RealmsServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "clam", + } + path = RealmsServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = RealmsServiceClient.parse_common_project_path(path) + assert expected == actual + + +def test_common_location_path(): + project = "whelk" + location = "octopus" + + expected = "projects/{project}/locations/{location}".format( + project=project, location=location, + ) + actual = RealmsServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "oyster", + "location": "nudibranch", + } + path = RealmsServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = RealmsServiceClient.parse_common_location_path(path) + assert expected == actual + + +def test_client_withDEFAULT_CLIENT_INFO(): + client_info = gapic_v1.client_info.ClientInfo() + + with mock.patch.object( + transports.RealmsServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = RealmsServiceClient( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.RealmsServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = RealmsServiceClient.get_transport_class() + transport = transport_class( + credentials=credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info)