From aa11f20976aab30d4ca34605afc1532db4b94628 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Thu, 17 Jun 2021 10:58:05 +0000 Subject: [PATCH 01/15] chore: new owl bot post processor docker image (#39) Post-Processor: gcr.io/repo-automation-bots/owlbot-python:latest@sha256:58c7342b0bccf85028100adaa3d856cb4a871c22ca9c01960d996e66c40548ce --- .github/.OwlBot.lock.yaml | 2 +- docs/conf.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 4ef4414..ea06d39 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/repo-automation-bots/owlbot-python:latest - digest: sha256:c66ba3c8d7bc8566f47df841f98cd0097b28fff0b1864c86f5817f4c8c3e8600 \ No newline at end of file + digest: sha256:58c7342b0bccf85028100adaa3d856cb4a871c22ca9c01960d996e66c40548ce diff --git a/docs/conf.py b/docs/conf.py index 7268757..c32dc0a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -80,9 +80,9 @@ master_doc = "index" # General information about the project. -project = u"google-cloud-gke-hub" -copyright = u"2019, Google" -author = u"Google APIs" +project = "google-cloud-gke-hub" +copyright = "2019, Google" +author = "Google APIs" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -281,7 +281,7 @@ ( master_doc, "google-cloud-gke-hub.tex", - u"google-cloud-gke-hub Documentation", + "google-cloud-gke-hub Documentation", author, "manual", ) @@ -316,7 +316,7 @@ ( master_doc, "google-cloud-gke-hub", - u"google-cloud-gke-hub Documentation", + "google-cloud-gke-hub Documentation", [author], 1, ) @@ -335,7 +335,7 @@ ( master_doc, "google-cloud-gke-hub", - u"google-cloud-gke-hub Documentation", + "google-cloud-gke-hub Documentation", author, "google-cloud-gke-hub", "google-cloud-gke-hub Library", From 8f703d74ad3d9b3ea31b2136ed4e97594b52f832 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Sat, 19 Jun 2021 01:38:26 +0000 Subject: [PATCH 02/15] docs: omit mention of Python 2.7 in 'CONTRIBUTING.rst' (#1127) (#40) Closes #1126 Source-Link: https://github.com/googleapis/synthtool/commit/b91f129527853d5b756146a0b5044481fb4e09a8 Post-Processor: gcr.io/repo-automation-bots/owlbot-python:latest@sha256:b6169fc6a5207b11800a7c002d0c5c2bc6d82697185ca12e666f44031468cfcd --- .github/.OwlBot.lock.yaml | 2 +- CONTRIBUTING.rst | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index ea06d39..cc49c6a 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/repo-automation-bots/owlbot-python:latest - digest: sha256:58c7342b0bccf85028100adaa3d856cb4a871c22ca9c01960d996e66c40548ce + digest: sha256:b6169fc6a5207b11800a7c002d0c5c2bc6d82697185ca12e666f44031468cfcd diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index e9a37b9..6953ee0 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -69,7 +69,6 @@ We use `nox `__ to instrument our tests. - To test your changes, run unit tests with ``nox``:: - $ nox -s unit-2.7 $ nox -s unit-3.8 $ ... @@ -144,7 +143,6 @@ Running System Tests # Run all system tests $ nox -s system-3.8 - $ nox -s system-2.7 # Run a single system test $ nox -s system-3.8 -- -k @@ -152,9 +150,8 @@ Running System Tests .. note:: - System tests are only configured to run under Python 2.7 and - Python 3.8. For expediency, we do not run them in older versions - of Python 3. + System tests are only configured to run under Python 3.8. + For expediency, we do not run them in older versions of Python 3. This alone will not run the tests. You'll need to change some local auth settings and change some configuration in your project to From 749349108f0d5cfd211a3ff9dc99613178f733e4 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Sun, 20 Jun 2021 01:06:17 +0000 Subject: [PATCH 03/15] chore: update precommit hook pre-commit/pre-commit-hooks to v4 (#1083) (#42) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [pre-commit/pre-commit-hooks](https://togithub.com/pre-commit/pre-commit-hooks) | repository | major | `v3.4.0` -> `v4.0.1` | --- ### Release Notes
pre-commit/pre-commit-hooks ### [`v4.0.1`](https://togithub.com/pre-commit/pre-commit-hooks/releases/v4.0.1) [Compare Source](https://togithub.com/pre-commit/pre-commit-hooks/compare/v4.0.0...v4.0.1) ##### Fixes - `check-shebang-scripts-are-executable` fix entry point. - [#​602](https://togithub.com/pre-commit/pre-commit-hooks/issues/602) issue by [@​Person-93](https://togithub.com/Person-93). - [#​603](https://togithub.com/pre-commit/pre-commit-hooks/issues/603) PR by [@​scop](https://togithub.com/scop). ### [`v4.0.0`](https://togithub.com/pre-commit/pre-commit-hooks/releases/v4.0.0) [Compare Source](https://togithub.com/pre-commit/pre-commit-hooks/compare/v3.4.0...v4.0.0) ##### Features - `check-json`: report duplicate keys. - [#​558](https://togithub.com/pre-commit/pre-commit-hooks/issues/558) PR by [@​AdityaKhursale](https://togithub.com/AdityaKhursale). - [#​554](https://togithub.com/pre-commit/pre-commit-hooks/issues/554) issue by [@​adamchainz](https://togithub.com/adamchainz). - `no-commit-to-branch`: add `main` to default blocked branches. - [#​565](https://togithub.com/pre-commit/pre-commit-hooks/issues/565) PR by [@​ndevenish](https://togithub.com/ndevenish). - `check-case-conflict`: check conflicts in directory names as well. - [#​575](https://togithub.com/pre-commit/pre-commit-hooks/issues/575) PR by [@​slsyy](https://togithub.com/slsyy). - [#​70](https://togithub.com/pre-commit/pre-commit-hooks/issues/70) issue by [@​andyjack](https://togithub.com/andyjack). - `check-vcs-permalinks`: forbid other branch names. - [#​582](https://togithub.com/pre-commit/pre-commit-hooks/issues/582) PR by [@​jack1142](https://togithub.com/jack1142). - [#​581](https://togithub.com/pre-commit/pre-commit-hooks/issues/581) issue by [@​jack1142](https://togithub.com/jack1142). - `check-shebang-scripts-are-executable`: new hook which ensures shebang'd scripts are executable. - [#​545](https://togithub.com/pre-commit/pre-commit-hooks/issues/545) PR by [@​scop](https://togithub.com/scop). ##### Fixes - `check-executables-have-shebangs`: Short circuit shebang lookup on windows. - [#​544](https://togithub.com/pre-commit/pre-commit-hooks/issues/544) PR by [@​scop](https://togithub.com/scop). - `requirements-txt-fixer`: Fix comments which have indentation - [#​549](https://togithub.com/pre-commit/pre-commit-hooks/issues/549) PR by [@​greshilov](https://togithub.com/greshilov). - [#​548](https://togithub.com/pre-commit/pre-commit-hooks/issues/548) issue by [@​greshilov](https://togithub.com/greshilov). - `pretty-format-json`: write to stdout using UTF-8 encoding. - [#​571](https://togithub.com/pre-commit/pre-commit-hooks/issues/571) PR by [@​jack1142](https://togithub.com/jack1142). - [#​570](https://togithub.com/pre-commit/pre-commit-hooks/issues/570) issue by [@​jack1142](https://togithub.com/jack1142). - Use more inclusive language. - [#​599](https://togithub.com/pre-commit/pre-commit-hooks/issues/599) PR by [@​asottile](https://togithub.com/asottile). ##### Breaking changes - Remove deprecated hooks: `flake8`, `pyflakes`, `autopep8-wrapper`. - [#​597](https://togithub.com/pre-commit/pre-commit-hooks/issues/597) PR by [@​asottile](https://togithub.com/asottile).
--- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻️ **Rebasing**: Renovate will not automatically rebase this PR, because other commits have been found. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/synthtool). Source-Link: https://github.com/googleapis/synthtool/commit/333fd90856f1454380514bc59fc0936cdaf1c202 Post-Processor: gcr.io/repo-automation-bots/owlbot-python:latest@sha256:b8c131c558606d3cea6e18f8e87befbd448c1482319b0db3c5d5388fa6ea72e3 --- .github/.OwlBot.lock.yaml | 2 +- .pre-commit-config.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index cc49c6a..9602d54 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/repo-automation-bots/owlbot-python:latest - digest: sha256:b6169fc6a5207b11800a7c002d0c5c2bc6d82697185ca12e666f44031468cfcd + digest: sha256:b8c131c558606d3cea6e18f8e87befbd448c1482319b0db3c5d5388fa6ea72e3 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4f00c7c..62eb5a7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.4.0 + rev: v4.0.1 hooks: - id: trailing-whitespace - id: end-of-file-fixer From 80a396125c6d55208483d3d1eb19ee7e38a32023 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 22 Jun 2021 20:10:21 +0000 Subject: [PATCH 04/15] chore: add kokoro 3.9 config templates (#1128) (#44) Source-Link: https://github.com/googleapis/synthtool/commit/b0eb8a8b30b46a3c98d23c23107acb748c6601a1 Post-Processor: gcr.io/repo-automation-bots/owlbot-python:latest@sha256:df50e8d462f86d6bcb42f27ecad55bb12c404f1c65de9c6fe4c4d25120080bd6 --- .github/.OwlBot.lock.yaml | 2 +- .kokoro/samples/python3.9/common.cfg | 40 +++++++++++++++++++++ .kokoro/samples/python3.9/continuous.cfg | 6 ++++ .kokoro/samples/python3.9/periodic-head.cfg | 11 ++++++ .kokoro/samples/python3.9/periodic.cfg | 6 ++++ .kokoro/samples/python3.9/presubmit.cfg | 6 ++++ 6 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 .kokoro/samples/python3.9/common.cfg create mode 100644 .kokoro/samples/python3.9/continuous.cfg create mode 100644 .kokoro/samples/python3.9/periodic-head.cfg create mode 100644 .kokoro/samples/python3.9/periodic.cfg create mode 100644 .kokoro/samples/python3.9/presubmit.cfg diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 9602d54..0954585 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/repo-automation-bots/owlbot-python:latest - digest: sha256:b8c131c558606d3cea6e18f8e87befbd448c1482319b0db3c5d5388fa6ea72e3 + digest: sha256:df50e8d462f86d6bcb42f27ecad55bb12c404f1c65de9c6fe4c4d25120080bd6 diff --git a/.kokoro/samples/python3.9/common.cfg b/.kokoro/samples/python3.9/common.cfg new file mode 100644 index 0000000..9e9ccca --- /dev/null +++ b/.kokoro/samples/python3.9/common.cfg @@ -0,0 +1,40 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Build logs will be here +action { + define_artifacts { + regex: "**/*sponge_log.xml" + } +} + +# Specify which tests to run +env_vars: { + key: "RUN_TESTS_SESSION" + value: "py-3.9" +} + +# Declare build specific Cloud project. +env_vars: { + key: "BUILD_SPECIFIC_GCLOUD_PROJECT" + value: "python-docs-samples-tests-py39" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-gke-hub/.kokoro/test-samples.sh" +} + +# Configure the docker image for kokoro-trampoline. +env_vars: { + key: "TRAMPOLINE_IMAGE" + value: "gcr.io/cloud-devrel-kokoro-resources/python-samples-testing-docker" +} + +# Download secrets for samples +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples" + +# Download trampoline resources. +gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" + +# Use the trampoline script to run in docker. +build_file: "python-gke-hub/.kokoro/trampoline.sh" \ No newline at end of file diff --git a/.kokoro/samples/python3.9/continuous.cfg b/.kokoro/samples/python3.9/continuous.cfg new file mode 100644 index 0000000..a1c8d97 --- /dev/null +++ b/.kokoro/samples/python3.9/continuous.cfg @@ -0,0 +1,6 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} \ No newline at end of file diff --git a/.kokoro/samples/python3.9/periodic-head.cfg b/.kokoro/samples/python3.9/periodic-head.cfg new file mode 100644 index 0000000..f9cfcd3 --- /dev/null +++ b/.kokoro/samples/python3.9/periodic-head.cfg @@ -0,0 +1,11 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-pubsub/.kokoro/test-samples-against-head.sh" +} diff --git a/.kokoro/samples/python3.9/periodic.cfg b/.kokoro/samples/python3.9/periodic.cfg new file mode 100644 index 0000000..50fec96 --- /dev/null +++ b/.kokoro/samples/python3.9/periodic.cfg @@ -0,0 +1,6 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "False" +} \ No newline at end of file diff --git a/.kokoro/samples/python3.9/presubmit.cfg b/.kokoro/samples/python3.9/presubmit.cfg new file mode 100644 index 0000000..a1c8d97 --- /dev/null +++ b/.kokoro/samples/python3.9/presubmit.cfg @@ -0,0 +1,6 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} \ No newline at end of file From 225d13235789a5d778658c2938e2c07df847a0cd Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Thu, 24 Jun 2021 15:00:17 +0000 Subject: [PATCH 05/15] feat: add always_use_jwt_access (#45) ... chore: update gapic-generator-ruby to the latest commit chore: release gapic-generator-typescript 1.5.0 Committer: @miraleung PiperOrigin-RevId: 380641501 Source-Link: https://github.com/googleapis/googleapis/commit/076f7e9f0b258bdb54338895d7251b202e8f0de3 Source-Link: https://github.com/googleapis/googleapis-gen/commit/27e4c88b4048e5f56508d4e1aa417d60a3380892 --- .coveragerc | 1 - .../transports/base.py | 40 +++---- .../transports/grpc.py | 7 +- .../transports/grpc_asyncio.py | 7 +- setup.py | 2 +- testing/constraints-3.6.txt | 2 +- .../test_gke_hub_membership_service.py | 104 +++--------------- 7 files changed, 39 insertions(+), 124 deletions(-) diff --git a/.coveragerc b/.coveragerc index d3f6f56..2b3ad0f 100644 --- a/.coveragerc +++ b/.coveragerc @@ -2,7 +2,6 @@ branch = True [report] -fail_under = 100 show_missing = True omit = google/cloud/gkehub/__init__.py diff --git a/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/base.py b/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/base.py index 9e6c9ff..97da42a 100644 --- a/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/base.py +++ b/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/base.py @@ -25,6 +25,7 @@ from google.api_core import retry as retries # type: ignore from google.api_core import operations_v1 # type: ignore from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore from google.cloud.gkehub_v1beta1.types import membership from google.longrunning import operations_pb2 # type: ignore @@ -45,8 +46,6 @@ except pkg_resources.DistributionNotFound: # pragma: NO COVER _GOOGLE_AUTH_VERSION = None -_API_CORE_VERSION = google.api_core.__version__ - class GkeHubMembershipServiceTransport(abc.ABC): """Abstract transport class for GkeHubMembershipService.""" @@ -64,6 +63,7 @@ def __init__( scopes: Optional[Sequence[str]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, **kwargs, ) -> None: """Instantiate the transport. @@ -87,6 +87,8 @@ def __init__( 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. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. """ # Save the hostname. Default to port 443 (HTTPS) if none is specified. if ":" not in host: @@ -115,13 +117,20 @@ def __init__( **scopes_kwargs, quota_project_id=quota_project_id ) + # If the credentials is service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + # Save the credentials. self._credentials = credentials - # TODO(busunkim): These two class methods are in the base transport + # TODO(busunkim): This method is in the base transport # to avoid duplicating code across the transport classes. These functions - # should be deleted once the minimum required versions of google-api-core - # and google-auth are increased. + # should be deleted once the minimum required versions of google-auth is increased. # TODO: Remove this function once google-auth >= 1.25.0 is required @classmethod @@ -142,27 +151,6 @@ def _get_scopes_kwargs( return scopes_kwargs - # TODO: Remove this function once google-api-core >= 1.26.0 is required - @classmethod - def _get_self_signed_jwt_kwargs( - cls, host: str, scopes: Optional[Sequence[str]] - ) -> Dict[str, Union[Optional[Sequence[str]], str]]: - """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version""" - - self_signed_jwt_kwargs: Dict[str, Union[Optional[Sequence[str]], str]] = {} - - if _API_CORE_VERSION and ( - packaging.version.parse(_API_CORE_VERSION) - >= packaging.version.parse("1.26.0") - ): - self_signed_jwt_kwargs["default_scopes"] = cls.AUTH_SCOPES - self_signed_jwt_kwargs["scopes"] = scopes - self_signed_jwt_kwargs["default_host"] = cls.DEFAULT_HOST - else: - self_signed_jwt_kwargs["scopes"] = scopes or cls.AUTH_SCOPES - - return self_signed_jwt_kwargs - def _prep_wrapped_messages(self, client_info): # Precompute the wrapped methods. self._wrapped_methods = { diff --git a/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/grpc.py b/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/grpc.py index bd0a6c6..dec0aa3 100644 --- a/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/grpc.py +++ b/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/grpc.py @@ -154,6 +154,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=True, ) if not self._grpc_channel: @@ -209,14 +210,14 @@ def create_channel( and ``credentials_file`` are passed. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) diff --git a/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/grpc_asyncio.py b/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/grpc_asyncio.py index abd6fca..5102138 100644 --- a/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/grpc_asyncio.py +++ b/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/grpc_asyncio.py @@ -82,14 +82,14 @@ def create_channel( aio.Channel: A gRPC AsyncIO channel object. """ - self_signed_jwt_kwargs = cls._get_self_signed_jwt_kwargs(host, scopes) - return grpc_helpers_async.create_channel( host, credentials=credentials, credentials_file=credentials_file, quota_project_id=quota_project_id, - **self_signed_jwt_kwargs, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, **kwargs, ) @@ -200,6 +200,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, + always_use_jwt_access=True, ) if not self._grpc_channel: diff --git a/setup.py b/setup.py index cc71898..080e576 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,7 @@ release_status = "Development Status :: 4 - Beta" url = "https://github.com/googleapis/python-gke-hub" dependencies = [ - "google-api-core[grpc] >= 1.22.2, < 2.0.0dev", + "google-api-core[grpc] >= 1.26.0, <2.0.0dev", "proto-plus >= 1.4.0", "packaging >= 14.3", ] diff --git a/testing/constraints-3.6.txt b/testing/constraints-3.6.txt index a85c4a1..2955fcf 100644 --- a/testing/constraints-3.6.txt +++ b/testing/constraints-3.6.txt @@ -19,6 +19,6 @@ # # e.g., if setup.py has "foo >= 1.14.0, < 2.0.0dev", # Then this file should have foo==1.14.0 -google-api-core==1.22.2 +google-api-core==1.26.0 proto-plus==1.4.0 packaging==14.3 diff --git a/tests/unit/gapic/gkehub_v1beta1/test_gke_hub_membership_service.py b/tests/unit/gapic/gkehub_v1beta1/test_gke_hub_membership_service.py index 3629ec2..f6b3ec4 100644 --- a/tests/unit/gapic/gkehub_v1beta1/test_gke_hub_membership_service.py +++ b/tests/unit/gapic/gkehub_v1beta1/test_gke_hub_membership_service.py @@ -42,9 +42,6 @@ ) from google.cloud.gkehub_v1beta1.services.gke_hub_membership_service import pagers from google.cloud.gkehub_v1beta1.services.gke_hub_membership_service import transports -from google.cloud.gkehub_v1beta1.services.gke_hub_membership_service.transports.base import ( - _API_CORE_VERSION, -) from google.cloud.gkehub_v1beta1.services.gke_hub_membership_service.transports.base import ( _GOOGLE_AUTH_VERSION, ) @@ -57,8 +54,9 @@ import google.auth -# TODO(busunkim): Once google-api-core >= 1.26.0 is required: -# - Delete all the api-core and auth "less than" test cases +# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively +# through google-api-core: +# - Delete the auth "less than" test cases # - Delete these pytest markers (Make the "greater than or equal to" tests the default). requires_google_auth_lt_1_25_0 = pytest.mark.skipif( packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), @@ -69,16 +67,6 @@ reason="This test requires google-auth >= 1.25.0", ) -requires_api_core_lt_1_26_0 = pytest.mark.skipif( - packaging.version.parse(_API_CORE_VERSION) >= packaging.version.parse("1.26.0"), - reason="This test requires google-api-core < 1.26.0", -) - -requires_api_core_gte_1_26_0 = pytest.mark.skipif( - packaging.version.parse(_API_CORE_VERSION) < packaging.version.parse("1.26.0"), - reason="This test requires google-api-core >= 1.26.0", -) - def client_cert_source_callback(): return b"cert bytes", b"key bytes" @@ -142,6 +130,18 @@ def test_gke_hub_membership_service_client_from_service_account_info(client_clas assert client.transport._host == "gkehub.googleapis.com:443" +@pytest.mark.parametrize( + "client_class", [GkeHubMembershipServiceClient, GkeHubMembershipServiceAsyncClient,] +) +def test_gke_hub_membership_service_client_service_account_always_use_jwt(client_class): + with mock.patch.object( + service_account.Credentials, "with_always_use_jwt_access", create=True + ) as use_jwt: + creds = service_account.Credentials(None, None, None) + client = client_class(credentials=creds) + use_jwt.assert_called_with(True) + + @pytest.mark.parametrize( "client_class", [GkeHubMembershipServiceClient, GkeHubMembershipServiceAsyncClient,] ) @@ -2484,7 +2484,6 @@ def test_gke_hub_membership_service_transport_auth_adc_old_google_auth(transport (transports.GkeHubMembershipServiceGrpcAsyncIOTransport, grpc_helpers_async), ], ) -@requires_api_core_gte_1_26_0 def test_gke_hub_membership_service_transport_create_channel( transport_class, grpc_helpers ): @@ -2515,79 +2514,6 @@ def test_gke_hub_membership_service_transport_create_channel( ) -@pytest.mark.parametrize( - "transport_class,grpc_helpers", - [ - (transports.GkeHubMembershipServiceGrpcTransport, grpc_helpers), - (transports.GkeHubMembershipServiceGrpcAsyncIOTransport, grpc_helpers_async), - ], -) -@requires_api_core_lt_1_26_0 -def test_gke_hub_membership_service_transport_create_channel_old_api_core( - transport_class, grpc_helpers -): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object( - google.auth, "default", autospec=True - ) as adc, mock.patch.object( - grpc_helpers, "create_channel", autospec=True - ) as create_channel: - creds = ga_credentials.AnonymousCredentials() - adc.return_value = (creds, None) - transport_class(quota_project_id="octopus") - - create_channel.assert_called_with( - "gkehub.googleapis.com:443", - credentials=creds, - credentials_file=None, - quota_project_id="octopus", - scopes=("https://www.googleapis.com/auth/cloud-platform",), - ssl_credentials=None, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - - -@pytest.mark.parametrize( - "transport_class,grpc_helpers", - [ - (transports.GkeHubMembershipServiceGrpcTransport, grpc_helpers), - (transports.GkeHubMembershipServiceGrpcAsyncIOTransport, grpc_helpers_async), - ], -) -@requires_api_core_lt_1_26_0 -def test_gke_hub_membership_service_transport_create_channel_user_scopes( - transport_class, grpc_helpers -): - # If credentials and host are not provided, the transport class should use - # ADC credentials. - with mock.patch.object( - google.auth, "default", autospec=True - ) as adc, mock.patch.object( - grpc_helpers, "create_channel", autospec=True - ) as create_channel: - creds = ga_credentials.AnonymousCredentials() - adc.return_value = (creds, None) - - transport_class(quota_project_id="octopus", scopes=["1", "2"]) - - create_channel.assert_called_with( - "gkehub.googleapis.com:443", - credentials=creds, - credentials_file=None, - quota_project_id="octopus", - scopes=["1", "2"], - ssl_credentials=None, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - - @pytest.mark.parametrize( "transport_class", [ From 5dfc9cef38bf4e21ba5b5588156da97e2eec898c Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Sat, 26 Jun 2021 11:34:10 +0000 Subject: [PATCH 06/15] chore(python): simplify nox steps in CONTRIBUTING.rst (#48) Source-Link: https://github.com/googleapis/synthtool/commit/26558bae8976a985d73c2d98c31d8612273f907d Post-Processor: gcr.io/repo-automation-bots/owlbot-python:latest@sha256:99d90d097e4a4710cc8658ee0b5b963f4426d0e424819787c3ac1405c9a26719 --- .github/.OwlBot.lock.yaml | 2 +- CONTRIBUTING.rst | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 0954585..e2b39f9 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/repo-automation-bots/owlbot-python:latest - digest: sha256:df50e8d462f86d6bcb42f27ecad55bb12c404f1c65de9c6fe4c4d25120080bd6 + digest: sha256:99d90d097e4a4710cc8658ee0b5b963f4426d0e424819787c3ac1405c9a26719 diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 6953ee0..1ddbdb7 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -68,14 +68,12 @@ Using ``nox`` We use `nox `__ to instrument our tests. - To test your changes, run unit tests with ``nox``:: + $ nox -s unit - $ nox -s unit-3.8 - $ ... +- To run a single unit test:: -- Args to pytest can be passed through the nox command separated by a `--`. For - example, to run a single test:: + $ nox -s unit-3.9 -- -k - $ nox -s unit-3.8 -- -k .. note:: @@ -142,7 +140,7 @@ Running System Tests - To run system tests, you can execute:: # Run all system tests - $ nox -s system-3.8 + $ nox -s system # Run a single system test $ nox -s system-3.8 -- -k @@ -215,8 +213,8 @@ Supported versions can be found in our ``noxfile.py`` `config`_. .. _config: https://github.com/googleapis/python-gke-hub/blob/master/noxfile.py -We also explicitly decided to support Python 3 beginning with version -3.6. Reasons for this include: +We also explicitly decided to support Python 3 beginning with version 3.6. +Reasons for this include: - Encouraging use of newest versions of Python 3 - Taking the lead of `prominent`_ open-source `projects`_ From f11dcfdf34ce4fa26de2fc4779b5b4f46a5c52bd Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Fri, 2 Jul 2021 14:12:26 +0000 Subject: [PATCH 07/15] feat: add v1 (#51) Committer: @parthea PiperOrigin-RevId: 381971413 Source-Link: https://github.com/googleapis/googleapis/commit/b6b4b89cae9b4734b7810c65a4fa69b5e9083cdc Source-Link: https://github.com/googleapis/googleapis-gen/commit/7519297e25de9b9fb3a6d22dc59f55d5e3382472 feat: add always_use_jwt_access --- .coveragerc | 2 +- .github/.OwlBot.yaml | 5 + docs/configmanagement_v1/services.rst | 4 + docs/configmanagement_v1/types.rst | 7 + docs/gkehub_v1/gke_hub.rst | 10 + docs/gkehub_v1/services.rst | 6 + docs/gkehub_v1/types.rst | 7 + docs/index.rst | 13 + docs/multiclusteringress_v1/services.rst | 4 + docs/multiclusteringress_v1/types.rst | 7 + google/cloud/gkehub/__init__.py | 82 - .../cloud/gkehub/configmanagement/__init__.py | 94 + google/cloud/gkehub/configmanagement/py.typed | 2 + .../gkehub/configmanagement_v1/__init__.py | 64 + .../configmanagement_v1/gapic_metadata.json | 7 + .../cloud/gkehub/configmanagement_v1/py.typed | 2 + .../configmanagement_v1/services/__init__.py | 15 + .../configmanagement_v1/types/__init__.py | 64 + .../types/configmanagement.py | 549 +++ .../gkehub/multiclusteringress/__init__.py | 22 + .../cloud/gkehub/multiclusteringress/py.typed | 2 + .../gkehub/multiclusteringress_v1/__init__.py | 20 + .../gapic_metadata.json | 7 + .../gkehub/multiclusteringress_v1/py.typed | 2 + .../services/__init__.py | 15 + .../multiclusteringress_v1/types/__init__.py | 18 + .../types/multiclusteringress.py | 38 + google/cloud/gkehub_v1/__init__.py | 84 + google/cloud/gkehub_v1/gapic_metadata.json | 133 + google/cloud/gkehub_v1/py.typed | 2 + google/cloud/gkehub_v1/services/__init__.py | 15 + .../gkehub_v1/services/gke_hub/__init__.py | 22 + .../services/gke_hub/async_client.py | 1159 ++++++ .../gkehub_v1/services/gke_hub/client.py | 1369 +++++++ .../gkehub_v1/services/gke_hub/pagers.py | 285 ++ .../services/gke_hub/transports/__init__.py | 33 + .../services/gke_hub/transports/base.py | 305 ++ .../services/gke_hub/transports/grpc.py | 560 +++ .../gke_hub/transports/grpc_asyncio.py | 577 +++ google/cloud/gkehub_v1/types/__init__.py | 84 + google/cloud/gkehub_v1/types/feature.py | 241 ++ google/cloud/gkehub_v1/types/membership.py | 270 ++ google/cloud/gkehub_v1/types/service.py | 597 +++ .../transports/base.py | 2 +- owlbot.py | 62 +- scripts/fixup_configmanagement_v1_keywords.py | 175 + scripts/fixup_gkehub_v1_keywords.py | 186 + .../fixup_multiclusteringress_v1_keywords.py | 175 + .../gapic/configmanagement_v1/__init__.py | 15 + tests/unit/gapic/gkehub_v1/__init__.py | 15 + tests/unit/gapic/gkehub_v1/test_gke_hub.py | 3641 +++++++++++++++++ .../test_gke_hub_membership_service.py | 6 +- .../gapic/multiclusteringress_v1/__init__.py | 15 + 53 files changed, 11007 insertions(+), 89 deletions(-) create mode 100644 docs/configmanagement_v1/services.rst create mode 100644 docs/configmanagement_v1/types.rst create mode 100644 docs/gkehub_v1/gke_hub.rst create mode 100644 docs/gkehub_v1/services.rst create mode 100644 docs/gkehub_v1/types.rst create mode 100644 docs/multiclusteringress_v1/services.rst create mode 100644 docs/multiclusteringress_v1/types.rst delete mode 100644 google/cloud/gkehub/__init__.py create mode 100644 google/cloud/gkehub/configmanagement/__init__.py create mode 100644 google/cloud/gkehub/configmanagement/py.typed create mode 100644 google/cloud/gkehub/configmanagement_v1/__init__.py create mode 100644 google/cloud/gkehub/configmanagement_v1/gapic_metadata.json create mode 100644 google/cloud/gkehub/configmanagement_v1/py.typed create mode 100644 google/cloud/gkehub/configmanagement_v1/services/__init__.py create mode 100644 google/cloud/gkehub/configmanagement_v1/types/__init__.py create mode 100644 google/cloud/gkehub/configmanagement_v1/types/configmanagement.py create mode 100644 google/cloud/gkehub/multiclusteringress/__init__.py create mode 100644 google/cloud/gkehub/multiclusteringress/py.typed create mode 100644 google/cloud/gkehub/multiclusteringress_v1/__init__.py create mode 100644 google/cloud/gkehub/multiclusteringress_v1/gapic_metadata.json create mode 100644 google/cloud/gkehub/multiclusteringress_v1/py.typed create mode 100644 google/cloud/gkehub/multiclusteringress_v1/services/__init__.py create mode 100644 google/cloud/gkehub/multiclusteringress_v1/types/__init__.py create mode 100644 google/cloud/gkehub/multiclusteringress_v1/types/multiclusteringress.py create mode 100644 google/cloud/gkehub_v1/__init__.py create mode 100644 google/cloud/gkehub_v1/gapic_metadata.json create mode 100644 google/cloud/gkehub_v1/py.typed create mode 100644 google/cloud/gkehub_v1/services/__init__.py create mode 100644 google/cloud/gkehub_v1/services/gke_hub/__init__.py create mode 100644 google/cloud/gkehub_v1/services/gke_hub/async_client.py create mode 100644 google/cloud/gkehub_v1/services/gke_hub/client.py create mode 100644 google/cloud/gkehub_v1/services/gke_hub/pagers.py create mode 100644 google/cloud/gkehub_v1/services/gke_hub/transports/__init__.py create mode 100644 google/cloud/gkehub_v1/services/gke_hub/transports/base.py create mode 100644 google/cloud/gkehub_v1/services/gke_hub/transports/grpc.py create mode 100644 google/cloud/gkehub_v1/services/gke_hub/transports/grpc_asyncio.py create mode 100644 google/cloud/gkehub_v1/types/__init__.py create mode 100644 google/cloud/gkehub_v1/types/feature.py create mode 100644 google/cloud/gkehub_v1/types/membership.py create mode 100644 google/cloud/gkehub_v1/types/service.py create mode 100644 scripts/fixup_configmanagement_v1_keywords.py create mode 100644 scripts/fixup_gkehub_v1_keywords.py create mode 100644 scripts/fixup_multiclusteringress_v1_keywords.py create mode 100644 tests/unit/gapic/configmanagement_v1/__init__.py create mode 100644 tests/unit/gapic/gkehub_v1/__init__.py create mode 100644 tests/unit/gapic/gkehub_v1/test_gke_hub.py create mode 100644 tests/unit/gapic/multiclusteringress_v1/__init__.py diff --git a/.coveragerc b/.coveragerc index 2b3ad0f..3cef77b 100644 --- a/.coveragerc +++ b/.coveragerc @@ -4,7 +4,7 @@ branch = True [report] show_missing = True omit = - google/cloud/gkehub/__init__.py + google/cloud/gkehub/multiclusteringress/__init__.py exclude_lines = # Re-enable the standard pragma pragma: NO COVER diff --git a/.github/.OwlBot.yaml b/.github/.OwlBot.yaml index 50bf7a0..c902419 100644 --- a/.github/.OwlBot.yaml +++ b/.github/.OwlBot.yaml @@ -18,6 +18,11 @@ docker: deep-remove-regex: - /owl-bot-staging +deep-preserve-regex: + - /owl-bot-staging/v1alpha + - /owl-bot-staging/v1alpha2 + - /owl-bot-staging/v1beta + deep-copy-regex: - source: /google/cloud/gkehub/(v.*)/.*-py/(.*) dest: /owl-bot-staging/$1/$2 diff --git a/docs/configmanagement_v1/services.rst b/docs/configmanagement_v1/services.rst new file mode 100644 index 0000000..6e2fc7d --- /dev/null +++ b/docs/configmanagement_v1/services.rst @@ -0,0 +1,4 @@ +Services for Google Cloud Gkehub Configmanagement v1 API +======================================================== +.. toctree:: + :maxdepth: 2 diff --git a/docs/configmanagement_v1/types.rst b/docs/configmanagement_v1/types.rst new file mode 100644 index 0000000..a002aa5 --- /dev/null +++ b/docs/configmanagement_v1/types.rst @@ -0,0 +1,7 @@ +Types for Google Cloud Gkehub Configmanagement v1 API +===================================================== + +.. automodule:: google.cloud.gkehub.configmanagement_v1.types + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/gkehub_v1/gke_hub.rst b/docs/gkehub_v1/gke_hub.rst new file mode 100644 index 0000000..198ae72 --- /dev/null +++ b/docs/gkehub_v1/gke_hub.rst @@ -0,0 +1,10 @@ +GkeHub +------------------------ + +.. automodule:: google.cloud.gkehub_v1.services.gke_hub + :members: + :inherited-members: + +.. automodule:: google.cloud.gkehub_v1.services.gke_hub.pagers + :members: + :inherited-members: diff --git a/docs/gkehub_v1/services.rst b/docs/gkehub_v1/services.rst new file mode 100644 index 0000000..ff81f05 --- /dev/null +++ b/docs/gkehub_v1/services.rst @@ -0,0 +1,6 @@ +Services for Google Cloud Gkehub v1 API +======================================= +.. toctree:: + :maxdepth: 2 + + gke_hub diff --git a/docs/gkehub_v1/types.rst b/docs/gkehub_v1/types.rst new file mode 100644 index 0000000..47a4a0d --- /dev/null +++ b/docs/gkehub_v1/types.rst @@ -0,0 +1,7 @@ +Types for Google Cloud Gkehub v1 API +==================================== + +.. automodule:: google.cloud.gkehub_v1.types + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/index.rst b/docs/index.rst index 04d2ea9..58d3d03 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -2,6 +2,18 @@ .. include:: multiprocessing.rst +API Reference +------------- +.. toctree:: + :maxdepth: 2 + + gkehub_v1/services + gkehub_v1/types + configmanagement_v1/services + configmanagement_v1/types + multiclusteringress_v1/services + multiclusteringress_v1/types + API Reference ------------- .. toctree:: @@ -10,6 +22,7 @@ API Reference gkehub_v1beta1/services gkehub_v1beta1/types + Changelog --------- diff --git a/docs/multiclusteringress_v1/services.rst b/docs/multiclusteringress_v1/services.rst new file mode 100644 index 0000000..9c56c78 --- /dev/null +++ b/docs/multiclusteringress_v1/services.rst @@ -0,0 +1,4 @@ +Services for Google Cloud Gkehub Multiclusteringress v1 API +=========================================================== +.. toctree:: + :maxdepth: 2 diff --git a/docs/multiclusteringress_v1/types.rst b/docs/multiclusteringress_v1/types.rst new file mode 100644 index 0000000..03d088d --- /dev/null +++ b/docs/multiclusteringress_v1/types.rst @@ -0,0 +1,7 @@ +Types for Google Cloud Gkehub Multiclusteringress v1 API +======================================================== + +.. automodule:: google.cloud.gkehub.multiclusteringress_v1.types + :members: + :undoc-members: + :show-inheritance: diff --git a/google/cloud/gkehub/__init__.py b/google/cloud/gkehub/__init__.py deleted file mode 100644 index 39cf698..0000000 --- a/google/cloud/gkehub/__init__.py +++ /dev/null @@ -1,82 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -from google.cloud.gkehub_v1beta1.services.gke_hub_membership_service.client import ( - GkeHubMembershipServiceClient, -) -from google.cloud.gkehub_v1beta1.services.gke_hub_membership_service.async_client import ( - GkeHubMembershipServiceAsyncClient, -) - -from google.cloud.gkehub_v1beta1.types.membership import Authority -from google.cloud.gkehub_v1beta1.types.membership import ConnectAgent -from google.cloud.gkehub_v1beta1.types.membership import ConnectAgentResource -from google.cloud.gkehub_v1beta1.types.membership import CreateMembershipRequest -from google.cloud.gkehub_v1beta1.types.membership import DeleteMembershipRequest -from google.cloud.gkehub_v1beta1.types.membership import GenerateConnectManifestRequest -from google.cloud.gkehub_v1beta1.types.membership import GenerateConnectManifestResponse -from google.cloud.gkehub_v1beta1.types.membership import ( - GenerateExclusivityManifestRequest, -) -from google.cloud.gkehub_v1beta1.types.membership import ( - GenerateExclusivityManifestResponse, -) -from google.cloud.gkehub_v1beta1.types.membership import GetMembershipRequest -from google.cloud.gkehub_v1beta1.types.membership import GkeCluster -from google.cloud.gkehub_v1beta1.types.membership import KubernetesMetadata -from google.cloud.gkehub_v1beta1.types.membership import KubernetesResource -from google.cloud.gkehub_v1beta1.types.membership import ListMembershipsRequest -from google.cloud.gkehub_v1beta1.types.membership import ListMembershipsResponse -from google.cloud.gkehub_v1beta1.types.membership import Membership -from google.cloud.gkehub_v1beta1.types.membership import MembershipEndpoint -from google.cloud.gkehub_v1beta1.types.membership import MembershipState -from google.cloud.gkehub_v1beta1.types.membership import OperationMetadata -from google.cloud.gkehub_v1beta1.types.membership import ResourceManifest -from google.cloud.gkehub_v1beta1.types.membership import ResourceOptions -from google.cloud.gkehub_v1beta1.types.membership import TypeMeta -from google.cloud.gkehub_v1beta1.types.membership import UpdateMembershipRequest -from google.cloud.gkehub_v1beta1.types.membership import ValidateExclusivityRequest -from google.cloud.gkehub_v1beta1.types.membership import ValidateExclusivityResponse - -__all__ = ( - "GkeHubMembershipServiceClient", - "GkeHubMembershipServiceAsyncClient", - "Authority", - "ConnectAgent", - "ConnectAgentResource", - "CreateMembershipRequest", - "DeleteMembershipRequest", - "GenerateConnectManifestRequest", - "GenerateConnectManifestResponse", - "GenerateExclusivityManifestRequest", - "GenerateExclusivityManifestResponse", - "GetMembershipRequest", - "GkeCluster", - "KubernetesMetadata", - "KubernetesResource", - "ListMembershipsRequest", - "ListMembershipsResponse", - "Membership", - "MembershipEndpoint", - "MembershipState", - "OperationMetadata", - "ResourceManifest", - "ResourceOptions", - "TypeMeta", - "UpdateMembershipRequest", - "ValidateExclusivityRequest", - "ValidateExclusivityResponse", -) diff --git a/google/cloud/gkehub/configmanagement/__init__.py b/google/cloud/gkehub/configmanagement/__init__.py new file mode 100644 index 0000000..f170446 --- /dev/null +++ b/google/cloud/gkehub/configmanagement/__init__.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ConfigSync +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( + ConfigSyncDeploymentState, +) +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( + ConfigSyncState, +) +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( + ConfigSyncVersion, +) +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ErrorResource +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( + GatekeeperDeploymentState, +) +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import GitConfig +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( + GroupVersionKind, +) +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( + HierarchyControllerConfig, +) +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( + HierarchyControllerDeploymentState, +) +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( + HierarchyControllerState, +) +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( + HierarchyControllerVersion, +) +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import InstallError +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( + MembershipSpec, +) +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( + MembershipState, +) +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import OperatorState +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( + PolicyController, +) +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( + PolicyControllerState, +) +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( + PolicyControllerVersion, +) +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import SyncError +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import SyncState +from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( + DeploymentState, +) + +__all__ = ( + "ConfigSync", + "ConfigSyncDeploymentState", + "ConfigSyncState", + "ConfigSyncVersion", + "ErrorResource", + "GatekeeperDeploymentState", + "GitConfig", + "GroupVersionKind", + "HierarchyControllerConfig", + "HierarchyControllerDeploymentState", + "HierarchyControllerState", + "HierarchyControllerVersion", + "InstallError", + "MembershipSpec", + "MembershipState", + "OperatorState", + "PolicyController", + "PolicyControllerState", + "PolicyControllerVersion", + "SyncError", + "SyncState", + "DeploymentState", +) diff --git a/google/cloud/gkehub/configmanagement/py.typed b/google/cloud/gkehub/configmanagement/py.typed new file mode 100644 index 0000000..5d21684 --- /dev/null +++ b/google/cloud/gkehub/configmanagement/py.typed @@ -0,0 +1,2 @@ +# Marker file for PEP 561. +# The google-cloud-gkehub-configmanagement package uses inline types. diff --git a/google/cloud/gkehub/configmanagement_v1/__init__.py b/google/cloud/gkehub/configmanagement_v1/__init__.py new file mode 100644 index 0000000..511def9 --- /dev/null +++ b/google/cloud/gkehub/configmanagement_v1/__init__.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +from .types.configmanagement import ConfigSync +from .types.configmanagement import ConfigSyncDeploymentState +from .types.configmanagement import ConfigSyncState +from .types.configmanagement import ConfigSyncVersion +from .types.configmanagement import ErrorResource +from .types.configmanagement import GatekeeperDeploymentState +from .types.configmanagement import GitConfig +from .types.configmanagement import GroupVersionKind +from .types.configmanagement import HierarchyControllerConfig +from .types.configmanagement import HierarchyControllerDeploymentState +from .types.configmanagement import HierarchyControllerState +from .types.configmanagement import HierarchyControllerVersion +from .types.configmanagement import InstallError +from .types.configmanagement import MembershipSpec +from .types.configmanagement import MembershipState +from .types.configmanagement import OperatorState +from .types.configmanagement import PolicyController +from .types.configmanagement import PolicyControllerState +from .types.configmanagement import PolicyControllerVersion +from .types.configmanagement import SyncError +from .types.configmanagement import SyncState +from .types.configmanagement import DeploymentState + +__all__ = ( + "ConfigSync", + "ConfigSyncDeploymentState", + "ConfigSyncState", + "ConfigSyncVersion", + "DeploymentState", + "ErrorResource", + "GatekeeperDeploymentState", + "GitConfig", + "GroupVersionKind", + "HierarchyControllerConfig", + "HierarchyControllerDeploymentState", + "HierarchyControllerState", + "HierarchyControllerVersion", + "InstallError", + "MembershipSpec", + "MembershipState", + "OperatorState", + "PolicyController", + "PolicyControllerState", + "PolicyControllerVersion", + "SyncError", + "SyncState", +) diff --git a/google/cloud/gkehub/configmanagement_v1/gapic_metadata.json b/google/cloud/gkehub/configmanagement_v1/gapic_metadata.json new file mode 100644 index 0000000..4cbd386 --- /dev/null +++ b/google/cloud/gkehub/configmanagement_v1/gapic_metadata.json @@ -0,0 +1,7 @@ + { + "comment": "This file maps proto services/RPCs to the corresponding library clients/methods", + "language": "python", + "libraryPackage": "google.cloud.gkehub.configmanagement_v1", + "protoPackage": "google.cloud.gkehub.configmanagement.v1", + "schema": "1.0" +} diff --git a/google/cloud/gkehub/configmanagement_v1/py.typed b/google/cloud/gkehub/configmanagement_v1/py.typed new file mode 100644 index 0000000..5d21684 --- /dev/null +++ b/google/cloud/gkehub/configmanagement_v1/py.typed @@ -0,0 +1,2 @@ +# Marker file for PEP 561. +# The google-cloud-gkehub-configmanagement package uses inline types. diff --git a/google/cloud/gkehub/configmanagement_v1/services/__init__.py b/google/cloud/gkehub/configmanagement_v1/services/__init__.py new file mode 100644 index 0000000..4de6597 --- /dev/null +++ b/google/cloud/gkehub/configmanagement_v1/services/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/google/cloud/gkehub/configmanagement_v1/types/__init__.py b/google/cloud/gkehub/configmanagement_v1/types/__init__.py new file mode 100644 index 0000000..d6d417c --- /dev/null +++ b/google/cloud/gkehub/configmanagement_v1/types/__init__.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from .configmanagement import ( + ConfigSync, + ConfigSyncDeploymentState, + ConfigSyncState, + ConfigSyncVersion, + ErrorResource, + GatekeeperDeploymentState, + GitConfig, + GroupVersionKind, + HierarchyControllerConfig, + HierarchyControllerDeploymentState, + HierarchyControllerState, + HierarchyControllerVersion, + InstallError, + MembershipSpec, + MembershipState, + OperatorState, + PolicyController, + PolicyControllerState, + PolicyControllerVersion, + SyncError, + SyncState, + DeploymentState, +) + +__all__ = ( + "ConfigSync", + "ConfigSyncDeploymentState", + "ConfigSyncState", + "ConfigSyncVersion", + "ErrorResource", + "GatekeeperDeploymentState", + "GitConfig", + "GroupVersionKind", + "HierarchyControllerConfig", + "HierarchyControllerDeploymentState", + "HierarchyControllerState", + "HierarchyControllerVersion", + "InstallError", + "MembershipSpec", + "MembershipState", + "OperatorState", + "PolicyController", + "PolicyControllerState", + "PolicyControllerVersion", + "SyncError", + "SyncState", + "DeploymentState", +) diff --git a/google/cloud/gkehub/configmanagement_v1/types/configmanagement.py b/google/cloud/gkehub/configmanagement_v1/types/configmanagement.py new file mode 100644 index 0000000..2e80137 --- /dev/null +++ b/google/cloud/gkehub/configmanagement_v1/types/configmanagement.py @@ -0,0 +1,549 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import proto # type: ignore + +from google.protobuf import timestamp_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.cloud.gkehub.configmanagement_v1", + manifest={ + "DeploymentState", + "MembershipState", + "MembershipSpec", + "ConfigSync", + "GitConfig", + "PolicyController", + "HierarchyControllerConfig", + "HierarchyControllerDeploymentState", + "HierarchyControllerVersion", + "HierarchyControllerState", + "OperatorState", + "InstallError", + "ConfigSyncState", + "ConfigSyncVersion", + "ConfigSyncDeploymentState", + "SyncState", + "SyncError", + "ErrorResource", + "GroupVersionKind", + "PolicyControllerState", + "PolicyControllerVersion", + "GatekeeperDeploymentState", + }, +) + + +class DeploymentState(proto.Enum): + r"""Enum representing the state of an ACM's deployment on a + cluster + """ + DEPLOYMENT_STATE_UNSPECIFIED = 0 + NOT_INSTALLED = 1 + INSTALLED = 2 + ERROR = 3 + + +class MembershipState(proto.Message): + r"""**Anthos Config Management**: State for a single cluster. + + Attributes: + cluster_name (str): + The user-defined name for the cluster used by + ClusterSelectors to group clusters together. This should + match Membership's membership_name, unless the user + installed ACM on the cluster manually prior to enabling the + ACM hub feature. Unique within a Anthos Config Management + installation. + membership_spec (google.cloud.gkehub.configmanagement_v1.types.MembershipSpec): + Membership configuration in the cluster. This + represents the actual state in the cluster, + while the MembershipSpec in the FeatureSpec + represents the intended state + operator_state (google.cloud.gkehub.configmanagement_v1.types.OperatorState): + Current install status of ACM's Operator + config_sync_state (google.cloud.gkehub.configmanagement_v1.types.ConfigSyncState): + Current sync status + policy_controller_state (google.cloud.gkehub.configmanagement_v1.types.PolicyControllerState): + PolicyController status + hierarchy_controller_state (google.cloud.gkehub.configmanagement_v1.types.HierarchyControllerState): + Hierarchy Controller status + """ + + cluster_name = proto.Field(proto.STRING, number=1,) + membership_spec = proto.Field(proto.MESSAGE, number=2, message="MembershipSpec",) + operator_state = proto.Field(proto.MESSAGE, number=3, message="OperatorState",) + config_sync_state = proto.Field(proto.MESSAGE, number=4, message="ConfigSyncState",) + policy_controller_state = proto.Field( + proto.MESSAGE, number=5, message="PolicyControllerState", + ) + hierarchy_controller_state = proto.Field( + proto.MESSAGE, number=7, message="HierarchyControllerState", + ) + + +class MembershipSpec(proto.Message): + r"""**Anthos Config Management**: Configuration for a single cluster. + Intended to parallel the ConfigManagement CR. + + Attributes: + config_sync (google.cloud.gkehub.configmanagement_v1.types.ConfigSync): + Config Sync configuration for the cluster. + policy_controller (google.cloud.gkehub.configmanagement_v1.types.PolicyController): + Policy Controller configuration for the + cluster. + hierarchy_controller (google.cloud.gkehub.configmanagement_v1.types.HierarchyControllerConfig): + Hierarchy Controller configuration for the + cluster. + version (str): + Version of ACM installed. + """ + + config_sync = proto.Field(proto.MESSAGE, number=1, message="ConfigSync",) + policy_controller = proto.Field( + proto.MESSAGE, number=2, message="PolicyController", + ) + hierarchy_controller = proto.Field( + proto.MESSAGE, number=4, message="HierarchyControllerConfig", + ) + version = proto.Field(proto.STRING, number=10,) + + +class ConfigSync(proto.Message): + r"""Configuration for Config Syn. + + Attributes: + git (google.cloud.gkehub.configmanagement_v1.types.GitConfig): + Git repo configuration for the cluster. + source_format (str): + Specifies whether the Config Sync Repo is + in “hierarchical” or “unstructured” mode. + """ + + git = proto.Field(proto.MESSAGE, number=7, message="GitConfig",) + source_format = proto.Field(proto.STRING, number=8,) + + +class GitConfig(proto.Message): + r"""Git repo configuration for a single cluster. + + Attributes: + sync_repo (str): + The URL of the Git repository to use as the + source of truth. + sync_branch (str): + The branch of the repository to sync from. + Default: master. + policy_dir (str): + The path within the Git repository that + represents the top level of the repo to sync. + Default: the root directory of the repository. + sync_wait_secs (int): + Period in seconds between consecutive syncs. + Default: 15. + sync_rev (str): + Git revision (tag or hash) to check out. + Default HEAD. + secret_type (str): + Type of secret configured for access to the + Git repo. + https_proxy (str): + URL for the HTTPS proxy to be used when + communicating with the Git repo. + gcp_service_account_email (str): + The GCP Service Account Email used for auth when secret_type + is gcpServiceAccount. + """ + + sync_repo = proto.Field(proto.STRING, number=1,) + sync_branch = proto.Field(proto.STRING, number=2,) + policy_dir = proto.Field(proto.STRING, number=3,) + sync_wait_secs = proto.Field(proto.INT64, number=4,) + sync_rev = proto.Field(proto.STRING, number=5,) + secret_type = proto.Field(proto.STRING, number=6,) + https_proxy = proto.Field(proto.STRING, number=7,) + gcp_service_account_email = proto.Field(proto.STRING, number=8,) + + +class PolicyController(proto.Message): + r"""Configuration for Policy Controlle. + + Attributes: + enabled (bool): + Enables the installation of Policy + Controller. If false, the rest of + PolicyController fields take no effect. + template_library_installed (bool): + Installs the default template library along + with Policy Controller. + audit_interval_seconds (int): + Sets the interval for Policy Controller Audit + Scans (in seconds). When set to 0, this disables + audit functionality altogether. + exemptable_namespaces (Sequence[str]): + The set of namespaces that are excluded from + Policy Controller checks. Namespaces do not need + to currently exist on the cluster. + referential_rules_enabled (bool): + Enables the ability to use Constraint + Templates that reference to objects other than + the object currently being evaluated. + log_denies_enabled (bool): + Logs all denies and dry run failures. + """ + + enabled = proto.Field(proto.BOOL, number=1,) + template_library_installed = proto.Field(proto.BOOL, number=2, optional=True,) + audit_interval_seconds = proto.Field(proto.INT64, number=3, optional=True,) + exemptable_namespaces = proto.RepeatedField(proto.STRING, number=4,) + referential_rules_enabled = proto.Field(proto.BOOL, number=5,) + log_denies_enabled = proto.Field(proto.BOOL, number=6,) + + +class HierarchyControllerConfig(proto.Message): + r"""Configuration for Hierarchy Controlle. + + Attributes: + enabled (bool): + Whether Hierarchy Controller is enabled in + this cluster. + enable_pod_tree_labels (bool): + Whether pod tree labels are enabled in this + cluster. + enable_hierarchical_resource_quota (bool): + Whether hierarchical resource quota is + enabled in this cluster. + """ + + enabled = proto.Field(proto.BOOL, number=1,) + enable_pod_tree_labels = proto.Field(proto.BOOL, number=2,) + enable_hierarchical_resource_quota = proto.Field(proto.BOOL, number=3,) + + +class HierarchyControllerDeploymentState(proto.Message): + r"""Deployment state for Hierarchy Controlle. + + Attributes: + hnc (google.cloud.gkehub.configmanagement_v1.types.DeploymentState): + The deployment state for open source HNC + (e.g. v0.7.0-hc.0) + extension (google.cloud.gkehub.configmanagement_v1.types.DeploymentState): + The deployment state for Hierarchy Controller + extension (e.g. v0.7.0-hc.1) + """ + + hnc = proto.Field(proto.ENUM, number=1, enum="DeploymentState",) + extension = proto.Field(proto.ENUM, number=2, enum="DeploymentState",) + + +class HierarchyControllerVersion(proto.Message): + r"""Version for Hierarchy Controlle. + + Attributes: + hnc (str): + Version for open source HNC + extension (str): + Version for Hierarchy Controller extension + """ + + hnc = proto.Field(proto.STRING, number=1,) + extension = proto.Field(proto.STRING, number=2,) + + +class HierarchyControllerState(proto.Message): + r"""State for Hierarchy Controlle. + + Attributes: + version (google.cloud.gkehub.configmanagement_v1.types.HierarchyControllerVersion): + The version for Hierarchy Controller + state (google.cloud.gkehub.configmanagement_v1.types.HierarchyControllerDeploymentState): + The deployment state for Hierarchy Controller + """ + + version = proto.Field( + proto.MESSAGE, number=1, message="HierarchyControllerVersion", + ) + state = proto.Field( + proto.MESSAGE, number=2, message="HierarchyControllerDeploymentState", + ) + + +class OperatorState(proto.Message): + r"""State information for an ACM's Operato. + + Attributes: + version (str): + The semenatic version number of the operator + deployment_state (google.cloud.gkehub.configmanagement_v1.types.DeploymentState): + The state of the Operator's deployment + errors (Sequence[google.cloud.gkehub.configmanagement_v1.types.InstallError]): + Install errors. + """ + + version = proto.Field(proto.STRING, number=1,) + deployment_state = proto.Field(proto.ENUM, number=2, enum="DeploymentState",) + errors = proto.RepeatedField(proto.MESSAGE, number=3, message="InstallError",) + + +class InstallError(proto.Message): + r"""Errors pertaining to the installation of AC. + + Attributes: + error_message (str): + A string representing the user facing error + message + """ + + error_message = proto.Field(proto.STRING, number=1,) + + +class ConfigSyncState(proto.Message): + r"""State information for ConfigSyn. + + Attributes: + version (google.cloud.gkehub.configmanagement_v1.types.ConfigSyncVersion): + The version of ConfigSync deployed + deployment_state (google.cloud.gkehub.configmanagement_v1.types.ConfigSyncDeploymentState): + Information about the deployment of + ConfigSync, including the version of the various + Pods deployed + sync_state (google.cloud.gkehub.configmanagement_v1.types.SyncState): + The state of ConfigSync's process to sync + configs to a cluster + """ + + version = proto.Field(proto.MESSAGE, number=1, message="ConfigSyncVersion",) + deployment_state = proto.Field( + proto.MESSAGE, number=2, message="ConfigSyncDeploymentState", + ) + sync_state = proto.Field(proto.MESSAGE, number=3, message="SyncState",) + + +class ConfigSyncVersion(proto.Message): + r"""Specific versioning information pertaining to ConfigSync's + Pods + + Attributes: + importer (str): + Version of the deployed importer pod + syncer (str): + Version of the deployed syncer pod + git_sync (str): + Version of the deployed git-sync pod + monitor (str): + Version of the deployed monitor pod + reconciler_manager (str): + Version of the deployed reconciler-manager + pod + root_reconciler (str): + Version of the deployed reconciler container + in root-reconciler pod + """ + + importer = proto.Field(proto.STRING, number=1,) + syncer = proto.Field(proto.STRING, number=2,) + git_sync = proto.Field(proto.STRING, number=3,) + monitor = proto.Field(proto.STRING, number=4,) + reconciler_manager = proto.Field(proto.STRING, number=5,) + root_reconciler = proto.Field(proto.STRING, number=6,) + + +class ConfigSyncDeploymentState(proto.Message): + r"""The state of ConfigSync's deployment on a cluste. + + Attributes: + importer (google.cloud.gkehub.configmanagement_v1.types.DeploymentState): + Deployment state of the importer pod + syncer (google.cloud.gkehub.configmanagement_v1.types.DeploymentState): + Deployment state of the syncer pod + git_sync (google.cloud.gkehub.configmanagement_v1.types.DeploymentState): + Deployment state of the git-sync pod + monitor (google.cloud.gkehub.configmanagement_v1.types.DeploymentState): + Deployment state of the monitor pod + reconciler_manager (google.cloud.gkehub.configmanagement_v1.types.DeploymentState): + Deployment state of reconciler-manager pod + root_reconciler (google.cloud.gkehub.configmanagement_v1.types.DeploymentState): + Deployment state of root-reconciler + """ + + importer = proto.Field(proto.ENUM, number=1, enum="DeploymentState",) + syncer = proto.Field(proto.ENUM, number=2, enum="DeploymentState",) + git_sync = proto.Field(proto.ENUM, number=3, enum="DeploymentState",) + monitor = proto.Field(proto.ENUM, number=4, enum="DeploymentState",) + reconciler_manager = proto.Field(proto.ENUM, number=5, enum="DeploymentState",) + root_reconciler = proto.Field(proto.ENUM, number=6, enum="DeploymentState",) + + +class SyncState(proto.Message): + r"""State indicating an ACM's progress syncing configurations to + a cluster + + Attributes: + source_token (str): + Token indicating the state of the repo. + import_token (str): + Token indicating the state of the importer. + sync_token (str): + Token indicating the state of the syncer. + last_sync (str): + Deprecated: use last_sync_time instead. Timestamp of when + ACM last successfully synced the repo The time format is + specified in https://golang.org/pkg/time/#Time.String + last_sync_time (google.protobuf.timestamp_pb2.Timestamp): + Timestamp type of when ACM last successfully + synced the repo + code (google.cloud.gkehub.configmanagement_v1.types.SyncState.SyncCode): + Sync status code + errors (Sequence[google.cloud.gkehub.configmanagement_v1.types.SyncError]): + A list of errors resulting from problematic + configs. This list will be truncated after 100 + errors, although it is unlikely for that many + errors to simultaneously exist. + """ + + class SyncCode(proto.Enum): + r"""An enum representing an ACM's status syncing configs to a + cluster + """ + SYNC_CODE_UNSPECIFIED = 0 + SYNCED = 1 + PENDING = 2 + ERROR = 3 + NOT_CONFIGURED = 4 + NOT_INSTALLED = 5 + UNAUTHORIZED = 6 + UNREACHABLE = 7 + + source_token = proto.Field(proto.STRING, number=1,) + import_token = proto.Field(proto.STRING, number=2,) + sync_token = proto.Field(proto.STRING, number=3,) + last_sync = proto.Field(proto.STRING, number=4,) + last_sync_time = proto.Field( + proto.MESSAGE, number=7, message=timestamp_pb2.Timestamp, + ) + code = proto.Field(proto.ENUM, number=5, enum=SyncCode,) + errors = proto.RepeatedField(proto.MESSAGE, number=6, message="SyncError",) + + +class SyncError(proto.Message): + r"""An ACM created error representing a problem syncing + configurations + + Attributes: + code (str): + An ACM defined error code + error_message (str): + A description of the error + error_resources (Sequence[google.cloud.gkehub.configmanagement_v1.types.ErrorResource]): + A list of config(s) associated with the + error, if any + """ + + code = proto.Field(proto.STRING, number=1,) + error_message = proto.Field(proto.STRING, number=2,) + error_resources = proto.RepeatedField( + proto.MESSAGE, number=3, message="ErrorResource", + ) + + +class ErrorResource(proto.Message): + r"""Model for a config file in the git repo with an associated + Sync error + + Attributes: + source_path (str): + Path in the git repo of the erroneous config + resource_name (str): + Metadata name of the resource that is causing + an error + resource_namespace (str): + Namespace of the resource that is causing an + error + resource_gvk (google.cloud.gkehub.configmanagement_v1.types.GroupVersionKind): + Group/version/kind of the resource that is + causing an error + """ + + source_path = proto.Field(proto.STRING, number=1,) + resource_name = proto.Field(proto.STRING, number=2,) + resource_namespace = proto.Field(proto.STRING, number=3,) + resource_gvk = proto.Field(proto.MESSAGE, number=4, message="GroupVersionKind",) + + +class GroupVersionKind(proto.Message): + r"""A Kubernetes object's GV. + + Attributes: + group (str): + Kubernetes Group + version (str): + Kubernetes Version + kind (str): + Kubernetes Kind + """ + + group = proto.Field(proto.STRING, number=1,) + version = proto.Field(proto.STRING, number=2,) + kind = proto.Field(proto.STRING, number=3,) + + +class PolicyControllerState(proto.Message): + r"""State for PolicyControllerState. + + Attributes: + version (google.cloud.gkehub.configmanagement_v1.types.PolicyControllerVersion): + The version of Gatekeeper Policy Controller + deployed. + deployment_state (google.cloud.gkehub.configmanagement_v1.types.GatekeeperDeploymentState): + The state about the policy controller + installation. + """ + + version = proto.Field(proto.MESSAGE, number=1, message="PolicyControllerVersion",) + deployment_state = proto.Field( + proto.MESSAGE, number=2, message="GatekeeperDeploymentState", + ) + + +class PolicyControllerVersion(proto.Message): + r"""The build version of Gatekeeper Policy Controller is using. + + Attributes: + version (str): + The gatekeeper image tag that is composed of + ACM version, git tag, build number. + """ + + version = proto.Field(proto.STRING, number=1,) + + +class GatekeeperDeploymentState(proto.Message): + r"""State of Policy Controller installation. + + Attributes: + gatekeeper_controller_manager_state (google.cloud.gkehub.configmanagement_v1.types.DeploymentState): + Status of gatekeeper-controller-manager pod. + gatekeeper_audit (google.cloud.gkehub.configmanagement_v1.types.DeploymentState): + Status of gatekeeper-audit deployment. + """ + + gatekeeper_controller_manager_state = proto.Field( + proto.ENUM, number=1, enum="DeploymentState", + ) + gatekeeper_audit = proto.Field(proto.ENUM, number=2, enum="DeploymentState",) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/gkehub/multiclusteringress/__init__.py b/google/cloud/gkehub/multiclusteringress/__init__.py new file mode 100644 index 0000000..a05e215 --- /dev/null +++ b/google/cloud/gkehub/multiclusteringress/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +from google.cloud.gkehub.multiclusteringress_v1.types.multiclusteringress import ( + FeatureSpec, +) + +__all__ = ("FeatureSpec",) diff --git a/google/cloud/gkehub/multiclusteringress/py.typed b/google/cloud/gkehub/multiclusteringress/py.typed new file mode 100644 index 0000000..298daf2 --- /dev/null +++ b/google/cloud/gkehub/multiclusteringress/py.typed @@ -0,0 +1,2 @@ +# Marker file for PEP 561. +# The google-cloud-gkehub-multiclusteringress package uses inline types. diff --git a/google/cloud/gkehub/multiclusteringress_v1/__init__.py b/google/cloud/gkehub/multiclusteringress_v1/__init__.py new file mode 100644 index 0000000..3870c5b --- /dev/null +++ b/google/cloud/gkehub/multiclusteringress_v1/__init__.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +from .types.multiclusteringress import FeatureSpec + +__all__ = ("FeatureSpec",) diff --git a/google/cloud/gkehub/multiclusteringress_v1/gapic_metadata.json b/google/cloud/gkehub/multiclusteringress_v1/gapic_metadata.json new file mode 100644 index 0000000..ad06970 --- /dev/null +++ b/google/cloud/gkehub/multiclusteringress_v1/gapic_metadata.json @@ -0,0 +1,7 @@ + { + "comment": "This file maps proto services/RPCs to the corresponding library clients/methods", + "language": "python", + "libraryPackage": "google.cloud.gkehub.multiclusteringress_v1", + "protoPackage": "google.cloud.gkehub.multiclusteringress.v1", + "schema": "1.0" +} diff --git a/google/cloud/gkehub/multiclusteringress_v1/py.typed b/google/cloud/gkehub/multiclusteringress_v1/py.typed new file mode 100644 index 0000000..298daf2 --- /dev/null +++ b/google/cloud/gkehub/multiclusteringress_v1/py.typed @@ -0,0 +1,2 @@ +# Marker file for PEP 561. +# The google-cloud-gkehub-multiclusteringress package uses inline types. diff --git a/google/cloud/gkehub/multiclusteringress_v1/services/__init__.py b/google/cloud/gkehub/multiclusteringress_v1/services/__init__.py new file mode 100644 index 0000000..4de6597 --- /dev/null +++ b/google/cloud/gkehub/multiclusteringress_v1/services/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/google/cloud/gkehub/multiclusteringress_v1/types/__init__.py b/google/cloud/gkehub/multiclusteringress_v1/types/__init__.py new file mode 100644 index 0000000..be71b4a --- /dev/null +++ b/google/cloud/gkehub/multiclusteringress_v1/types/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from .multiclusteringress import FeatureSpec + +__all__ = ("FeatureSpec",) diff --git a/google/cloud/gkehub/multiclusteringress_v1/types/multiclusteringress.py b/google/cloud/gkehub/multiclusteringress_v1/types/multiclusteringress.py new file mode 100644 index 0000000..ef30a0b --- /dev/null +++ b/google/cloud/gkehub/multiclusteringress_v1/types/multiclusteringress.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import proto # type: ignore + + +__protobuf__ = proto.module( + package="google.cloud.gkehub.multiclusteringress_v1", manifest={"FeatureSpec",}, +) + + +class FeatureSpec(proto.Message): + r"""**Multi-cluster Ingress**: The configuration for the + MultiClusterIngress feature. + + Attributes: + config_membership (str): + Fully-qualified Membership name which hosts the + MultiClusterIngress CRD. Example: + ``projects/foo-proj/locations/global/memberships/bar`` + """ + + config_membership = proto.Field(proto.STRING, number=1,) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/gkehub_v1/__init__.py b/google/cloud/gkehub_v1/__init__.py new file mode 100644 index 0000000..e233c40 --- /dev/null +++ b/google/cloud/gkehub_v1/__init__.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from .services.gke_hub import GkeHubClient +from .services.gke_hub import GkeHubAsyncClient + +from .types.feature import CommonFeatureSpec +from .types.feature import CommonFeatureState +from .types.feature import Feature +from .types.feature import FeatureResourceState +from .types.feature import FeatureState +from .types.feature import MembershipFeatureSpec +from .types.feature import MembershipFeatureState +from .types.membership import Authority +from .types.membership import GkeCluster +from .types.membership import KubernetesMetadata +from .types.membership import Membership +from .types.membership import MembershipEndpoint +from .types.membership import MembershipState +from .types.service import ConnectAgentResource +from .types.service import CreateFeatureRequest +from .types.service import CreateMembershipRequest +from .types.service import DeleteFeatureRequest +from .types.service import DeleteMembershipRequest +from .types.service import GenerateConnectManifestRequest +from .types.service import GenerateConnectManifestResponse +from .types.service import GetFeatureRequest +from .types.service import GetMembershipRequest +from .types.service import ListFeaturesRequest +from .types.service import ListFeaturesResponse +from .types.service import ListMembershipsRequest +from .types.service import ListMembershipsResponse +from .types.service import OperationMetadata +from .types.service import TypeMeta +from .types.service import UpdateFeatureRequest +from .types.service import UpdateMembershipRequest + +__all__ = ( + "GkeHubAsyncClient", + "Authority", + "CommonFeatureSpec", + "CommonFeatureState", + "ConnectAgentResource", + "CreateFeatureRequest", + "CreateMembershipRequest", + "DeleteFeatureRequest", + "DeleteMembershipRequest", + "Feature", + "FeatureResourceState", + "FeatureState", + "GenerateConnectManifestRequest", + "GenerateConnectManifestResponse", + "GetFeatureRequest", + "GetMembershipRequest", + "GkeCluster", + "GkeHubClient", + "KubernetesMetadata", + "ListFeaturesRequest", + "ListFeaturesResponse", + "ListMembershipsRequest", + "ListMembershipsResponse", + "Membership", + "MembershipEndpoint", + "MembershipFeatureSpec", + "MembershipFeatureState", + "MembershipState", + "OperationMetadata", + "TypeMeta", + "UpdateFeatureRequest", + "UpdateMembershipRequest", +) diff --git a/google/cloud/gkehub_v1/gapic_metadata.json b/google/cloud/gkehub_v1/gapic_metadata.json new file mode 100644 index 0000000..5086eae --- /dev/null +++ b/google/cloud/gkehub_v1/gapic_metadata.json @@ -0,0 +1,133 @@ + { + "comment": "This file maps proto services/RPCs to the corresponding library clients/methods", + "language": "python", + "libraryPackage": "google.cloud.gkehub_v1", + "protoPackage": "google.cloud.gkehub.v1", + "schema": "1.0", + "services": { + "GkeHub": { + "clients": { + "grpc": { + "libraryClient": "GkeHubClient", + "rpcs": { + "CreateFeature": { + "methods": [ + "create_feature" + ] + }, + "CreateMembership": { + "methods": [ + "create_membership" + ] + }, + "DeleteFeature": { + "methods": [ + "delete_feature" + ] + }, + "DeleteMembership": { + "methods": [ + "delete_membership" + ] + }, + "GenerateConnectManifest": { + "methods": [ + "generate_connect_manifest" + ] + }, + "GetFeature": { + "methods": [ + "get_feature" + ] + }, + "GetMembership": { + "methods": [ + "get_membership" + ] + }, + "ListFeatures": { + "methods": [ + "list_features" + ] + }, + "ListMemberships": { + "methods": [ + "list_memberships" + ] + }, + "UpdateFeature": { + "methods": [ + "update_feature" + ] + }, + "UpdateMembership": { + "methods": [ + "update_membership" + ] + } + } + }, + "grpc-async": { + "libraryClient": "GkeHubAsyncClient", + "rpcs": { + "CreateFeature": { + "methods": [ + "create_feature" + ] + }, + "CreateMembership": { + "methods": [ + "create_membership" + ] + }, + "DeleteFeature": { + "methods": [ + "delete_feature" + ] + }, + "DeleteMembership": { + "methods": [ + "delete_membership" + ] + }, + "GenerateConnectManifest": { + "methods": [ + "generate_connect_manifest" + ] + }, + "GetFeature": { + "methods": [ + "get_feature" + ] + }, + "GetMembership": { + "methods": [ + "get_membership" + ] + }, + "ListFeatures": { + "methods": [ + "list_features" + ] + }, + "ListMemberships": { + "methods": [ + "list_memberships" + ] + }, + "UpdateFeature": { + "methods": [ + "update_feature" + ] + }, + "UpdateMembership": { + "methods": [ + "update_membership" + ] + } + } + } + } + } + } +} diff --git a/google/cloud/gkehub_v1/py.typed b/google/cloud/gkehub_v1/py.typed new file mode 100644 index 0000000..7a6a6d0 --- /dev/null +++ b/google/cloud/gkehub_v1/py.typed @@ -0,0 +1,2 @@ +# Marker file for PEP 561. +# The google-cloud-gke-hub package uses inline types. diff --git a/google/cloud/gkehub_v1/services/__init__.py b/google/cloud/gkehub_v1/services/__init__.py new file mode 100644 index 0000000..4de6597 --- /dev/null +++ b/google/cloud/gkehub_v1/services/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/google/cloud/gkehub_v1/services/gke_hub/__init__.py b/google/cloud/gkehub_v1/services/gke_hub/__init__.py new file mode 100644 index 0000000..73e44b4 --- /dev/null +++ b/google/cloud/gkehub_v1/services/gke_hub/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from .client import GkeHubClient +from .async_client import GkeHubAsyncClient + +__all__ = ( + "GkeHubClient", + "GkeHubAsyncClient", +) diff --git a/google/cloud/gkehub_v1/services/gke_hub/async_client.py b/google/cloud/gkehub_v1/services/gke_hub/async_client.py new file mode 100644 index 0000000..d56e4b5 --- /dev/null +++ b/google/cloud/gkehub_v1/services/gke_hub/async_client.py @@ -0,0 +1,1159 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import functools +import re +from typing import Dict, Sequence, Tuple, Type, Union +import pkg_resources + +import google.api_core.client_options as ClientOptions # type: ignore +from google.api_core import exceptions as core_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 as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore +from google.cloud.gkehub_v1.services.gke_hub import pagers +from google.cloud.gkehub_v1.types import feature +from google.cloud.gkehub_v1.types import membership +from google.cloud.gkehub_v1.types import service +from google.protobuf import empty_pb2 # type: ignore +from google.protobuf import field_mask_pb2 # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore +from .transports.base import GkeHubTransport, DEFAULT_CLIENT_INFO +from .transports.grpc_asyncio import GkeHubGrpcAsyncIOTransport +from .client import GkeHubClient + + +class GkeHubAsyncClient: + """The GKE Hub service handles the registration of many Kubernetes + clusters to Google Cloud, and the management of multi-cluster + features over those clusters. + + The GKE Hub service operates on the following resources: + + - [Membership][google.cloud.gkehub_v1.Membership] + - [Feature][google.cloud.gkehub_v1.Feature] + + GKE Hub is currently only available in the global region. + + **Membership management may be non-trivial:** it is recommended to + use one of the Google-provided client libraries or tools where + possible when working with Membership resources. + """ + + _client: GkeHubClient + + DEFAULT_ENDPOINT = GkeHubClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = GkeHubClient.DEFAULT_MTLS_ENDPOINT + + feature_path = staticmethod(GkeHubClient.feature_path) + parse_feature_path = staticmethod(GkeHubClient.parse_feature_path) + membership_path = staticmethod(GkeHubClient.membership_path) + parse_membership_path = staticmethod(GkeHubClient.parse_membership_path) + common_billing_account_path = staticmethod(GkeHubClient.common_billing_account_path) + parse_common_billing_account_path = staticmethod( + GkeHubClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(GkeHubClient.common_folder_path) + parse_common_folder_path = staticmethod(GkeHubClient.parse_common_folder_path) + common_organization_path = staticmethod(GkeHubClient.common_organization_path) + parse_common_organization_path = staticmethod( + GkeHubClient.parse_common_organization_path + ) + common_project_path = staticmethod(GkeHubClient.common_project_path) + parse_common_project_path = staticmethod(GkeHubClient.parse_common_project_path) + common_location_path = staticmethod(GkeHubClient.common_location_path) + parse_common_location_path = staticmethod(GkeHubClient.parse_common_location_path) + + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials + info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GkeHubAsyncClient: The constructed client. + """ + return GkeHubClient.from_service_account_info.__func__(GkeHubAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GkeHubAsyncClient: The constructed client. + """ + return GkeHubClient.from_service_account_file.__func__(GkeHubAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @property + def transport(self) -> GkeHubTransport: + """Returns the transport used by the client instance. + + Returns: + GkeHubTransport: The transport used by the client instance. + """ + return self._client.transport + + get_transport_class = functools.partial( + type(GkeHubClient).get_transport_class, type(GkeHubClient) + ) + + def __init__( + self, + *, + credentials: ga_credentials.Credentials = None, + transport: Union[str, GkeHubTransport] = "grpc_asyncio", + client_options: ClientOptions = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the gke hub client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Union[str, ~.GkeHubTransport]): 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. + (1) The ``api_endpoint`` property can be used to override the + 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) 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 + creation failed for any reason. + """ + self._client = GkeHubClient( + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, + ) + + async def list_memberships( + self, + request: service.ListMembershipsRequest = None, + *, + parent: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> pagers.ListMembershipsAsyncPager: + r"""Lists Memberships in a given project and location. + + Args: + request (:class:`google.cloud.gkehub_v1.types.ListMembershipsRequest`): + The request object. Request message for + `GkeHub.ListMemberships` method. + parent (:class:`str`): + Required. The parent (project and location) where the + Memberships will be listed. Specified in the format + ``projects/*/locations/*``. + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.gkehub_v1.services.gke_hub.pagers.ListMembershipsAsyncPager: + Response message for the GkeHub.ListMemberships method. + + Iterating over this object will yield results and + resolve additional pages automatically. + + """ + # 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. + 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." + ) + + request = service.ListMembershipsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.list_memberships, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # This method is paged; wrap the response in a pager, which provides + # an `__aiter__` convenience method. + response = pagers.ListMembershipsAsyncPager( + method=rpc, request=request, response=response, metadata=metadata, + ) + + # Done; return the response. + return response + + async def list_features( + self, + request: service.ListFeaturesRequest = None, + *, + parent: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> pagers.ListFeaturesAsyncPager: + r"""Lists Features in a given project and location. + + Args: + request (:class:`google.cloud.gkehub_v1.types.ListFeaturesRequest`): + The request object. Request message for + `GkeHub.ListFeatures` method. + parent (:class:`str`): + The parent (project and location) where the Features + will be listed. Specified in the format + ``projects/*/locations/*``. + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.gkehub_v1.services.gke_hub.pagers.ListFeaturesAsyncPager: + Response message for the GkeHub.ListFeatures method. + + Iterating over this object will yield results and + resolve additional pages automatically. + + """ + # 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. + 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." + ) + + request = service.ListFeaturesRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.list_features, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # This method is paged; wrap the response in a pager, which provides + # an `__aiter__` convenience method. + response = pagers.ListFeaturesAsyncPager( + method=rpc, request=request, response=response, metadata=metadata, + ) + + # Done; return the response. + return response + + async def get_membership( + self, + request: service.GetMembershipRequest = None, + *, + name: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> membership.Membership: + r"""Gets the details of a Membership. + + Args: + request (:class:`google.cloud.gkehub_v1.types.GetMembershipRequest`): + The request object. Request message for + `GkeHub.GetMembership` method. + name (:class:`str`): + Required. The Membership resource name in the format + ``projects/*/locations/*/memberships/*``. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.gkehub_v1.types.Membership: + Membership contains information about + a member 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. + 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." + ) + + request = service.GetMembershipRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.get_membership, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Done; return the response. + return response + + async def get_feature( + self, + request: service.GetFeatureRequest = None, + *, + name: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> feature.Feature: + r"""Gets details of a single Feature. + + Args: + request (:class:`google.cloud.gkehub_v1.types.GetFeatureRequest`): + The request object. Request message for + `GkeHub.GetFeature` method. + name (:class:`str`): + The Feature resource name in the format + ``projects/*/locations/*/features/*`` + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.gkehub_v1.types.Feature: + Feature represents the settings and + status of any Hub Feature. + + """ + # 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. + 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." + ) + + request = service.GetFeatureRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.get_feature, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Done; return the response. + return response + + async def create_membership( + self, + request: service.CreateMembershipRequest = None, + *, + parent: str = None, + resource: membership.Membership = None, + membership_id: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation_async.AsyncOperation: + r"""Creates a new Membership. + + **This is currently only supported for GKE clusters on Google + Cloud**. To register other clusters, follow the instructions at + https://cloud.google.com/anthos/multicluster-management/connect/registering-a-cluster. + + Args: + request (:class:`google.cloud.gkehub_v1.types.CreateMembershipRequest`): + The request object. Request message for the + `GkeHub.CreateMembership` method. + parent (:class:`str`): + Required. The parent (project and location) where the + Memberships will be created. Specified in the format + ``projects/*/locations/*``. + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource (:class:`google.cloud.gkehub_v1.types.Membership`): + Required. The membership to create. + This corresponds to the ``resource`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + membership_id (:class:`str`): + Required. Client chosen ID for the membership. + ``membership_id`` must be a valid RFC 1123 compliant DNS + label: + + 1. At most 63 characters in length + 2. It must consist of lower case alphanumeric characters + or ``-`` + 3. It must start and end with an alphanumeric character + + Which can be expressed as the regex: + ``[a-z0-9]([-a-z0-9]*[a-z0-9])?``, with a maximum length + of 63 characters. + + This corresponds to the ``membership_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation_async.AsyncOperation: + An object representing a long-running operation. + + The result type for the operation will be + :class:`google.cloud.gkehub_v1.types.Membership` + Membership contains information about a member 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. + has_flattened_params = any([parent, resource, membership_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." + ) + + request = service.CreateMembershipRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if resource is not None: + request.resource = resource + if membership_id is not None: + request.membership_id = membership_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.create_membership, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Wrap the response in an operation future. + response = operation_async.from_gapic( + response, + self._client._transport.operations_client, + membership.Membership, + metadata_type=service.OperationMetadata, + ) + + # Done; return the response. + return response + + async def create_feature( + self, + request: service.CreateFeatureRequest = None, + *, + parent: str = None, + resource: feature.Feature = None, + feature_id: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation_async.AsyncOperation: + r"""Adds a new Feature. + + Args: + request (:class:`google.cloud.gkehub_v1.types.CreateFeatureRequest`): + The request object. Request message for the + `GkeHub.CreateFeature` method. + parent (:class:`str`): + The parent (project and location) where the Feature will + be created. Specified in the format + ``projects/*/locations/*``. + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource (:class:`google.cloud.gkehub_v1.types.Feature`): + The Feature resource to create. + This corresponds to the ``resource`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + feature_id (:class:`str`): + The ID of the feature to create. + This corresponds to the ``feature_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation_async.AsyncOperation: + An object representing a long-running operation. + + The result type for the operation will be + :class:`google.cloud.gkehub_v1.types.Feature` Feature + represents the settings and status of any Hub Feature. + + """ + # 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. + has_flattened_params = any([parent, resource, feature_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." + ) + + request = service.CreateFeatureRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if resource is not None: + request.resource = resource + if feature_id is not None: + request.feature_id = feature_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.create_feature, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Wrap the response in an operation future. + response = operation_async.from_gapic( + response, + self._client._transport.operations_client, + feature.Feature, + metadata_type=service.OperationMetadata, + ) + + # Done; return the response. + return response + + async def delete_membership( + self, + request: service.DeleteMembershipRequest = None, + *, + name: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation_async.AsyncOperation: + r"""Removes a Membership. + + **This is currently only supported for GKE clusters on Google + Cloud**. To unregister other clusters, follow the instructions + at + https://cloud.google.com/anthos/multicluster-management/connect/unregistering-a-cluster. + + Args: + request (:class:`google.cloud.gkehub_v1.types.DeleteMembershipRequest`): + The request object. Request message for + `GkeHub.DeleteMembership` method. + name (:class:`str`): + Required. The Membership resource name in the format + ``projects/*/locations/*/memberships/*``. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation_async.AsyncOperation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.protobuf.empty_pb2.Empty` A generic empty message that you can re-use to avoid defining duplicated + empty messages in your APIs. A typical example is to + use it as the request or the response type of an API + method. For instance: + + service Foo { + rpc Bar(google.protobuf.Empty) returns + (google.protobuf.Empty); + + } + + The JSON representation for Empty is empty JSON + object {}. + + """ + # 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. + 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." + ) + + request = service.DeleteMembershipRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.delete_membership, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Wrap the response in an operation future. + response = operation_async.from_gapic( + response, + self._client._transport.operations_client, + empty_pb2.Empty, + metadata_type=service.OperationMetadata, + ) + + # Done; return the response. + return response + + async def delete_feature( + self, + request: service.DeleteFeatureRequest = None, + *, + name: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation_async.AsyncOperation: + r"""Removes a Feature. + + Args: + request (:class:`google.cloud.gkehub_v1.types.DeleteFeatureRequest`): + The request object. Request message for + `GkeHub.DeleteFeature` method. + name (:class:`str`): + The Feature resource name in the format + ``projects/*/locations/*/features/*``. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation_async.AsyncOperation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.protobuf.empty_pb2.Empty` A generic empty message that you can re-use to avoid defining duplicated + empty messages in your APIs. A typical example is to + use it as the request or the response type of an API + method. For instance: + + service Foo { + rpc Bar(google.protobuf.Empty) returns + (google.protobuf.Empty); + + } + + The JSON representation for Empty is empty JSON + object {}. + + """ + # 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. + 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." + ) + + request = service.DeleteFeatureRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.delete_feature, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Wrap the response in an operation future. + response = operation_async.from_gapic( + response, + self._client._transport.operations_client, + empty_pb2.Empty, + metadata_type=service.OperationMetadata, + ) + + # Done; return the response. + return response + + async def update_membership( + self, + request: service.UpdateMembershipRequest = None, + *, + name: str = None, + resource: membership.Membership = None, + update_mask: field_mask_pb2.FieldMask = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation_async.AsyncOperation: + r"""Updates an existing Membership. + + Args: + request (:class:`google.cloud.gkehub_v1.types.UpdateMembershipRequest`): + The request object. Request message for + `GkeHub.UpdateMembership` method. + name (:class:`str`): + Required. The Membership resource name in the format + ``projects/*/locations/*/memberships/*``. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource (:class:`google.cloud.gkehub_v1.types.Membership`): + Required. Only fields specified in update_mask are + updated. If you specify a field in the update_mask but + don't specify its value here that field will be deleted. + If you are updating a map field, set the value of a key + to null or empty string to delete the key from the map. + It's not possible to update a key's value to the empty + string. If you specify the update_mask to be a special + path "*", fully replaces all user-modifiable fields to + match ``resource``. + + This corresponds to the ``resource`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (:class:`google.protobuf.field_mask_pb2.FieldMask`): + Required. Mask of fields to update. + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation_async.AsyncOperation: + An object representing a long-running operation. + + The result type for the operation will be + :class:`google.cloud.gkehub_v1.types.Membership` + Membership contains information about a member 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. + has_flattened_params = any([name, resource, 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." + ) + + request = service.UpdateMembershipRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + if resource is not None: + request.resource = resource + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.update_membership, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Wrap the response in an operation future. + response = operation_async.from_gapic( + response, + self._client._transport.operations_client, + membership.Membership, + metadata_type=service.OperationMetadata, + ) + + # Done; return the response. + return response + + async def update_feature( + self, + request: service.UpdateFeatureRequest = None, + *, + name: str = None, + resource: feature.Feature = None, + update_mask: field_mask_pb2.FieldMask = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation_async.AsyncOperation: + r"""Updates an existing Feature. + + Args: + request (:class:`google.cloud.gkehub_v1.types.UpdateFeatureRequest`): + The request object. Request message for + `GkeHub.UpdateFeature` method. + name (:class:`str`): + The Feature resource name in the format + ``projects/*/locations/*/features/*``. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource (:class:`google.cloud.gkehub_v1.types.Feature`): + Only fields specified in update_mask are updated. If you + specify a field in the update_mask but don't specify its + value here that field will be deleted. If you are + updating a map field, set the value of a key to null or + empty string to delete the key from the map. It's not + possible to update a key's value to the empty string. If + you specify the update_mask to be a special path "*", + fully replaces all user-modifiable fields to match + ``resource``. + + This corresponds to the ``resource`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (:class:`google.protobuf.field_mask_pb2.FieldMask`): + Mask of fields to update. + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation_async.AsyncOperation: + An object representing a long-running operation. + + The result type for the operation will be + :class:`google.cloud.gkehub_v1.types.Feature` Feature + represents the settings and status of any Hub Feature. + + """ + # 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. + has_flattened_params = any([name, resource, 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." + ) + + request = service.UpdateFeatureRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + if resource is not None: + request.resource = resource + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.update_feature, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Wrap the response in an operation future. + response = operation_async.from_gapic( + response, + self._client._transport.operations_client, + feature.Feature, + metadata_type=service.OperationMetadata, + ) + + # Done; return the response. + return response + + async def generate_connect_manifest( + self, + request: service.GenerateConnectManifestRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> service.GenerateConnectManifestResponse: + r"""Generates the manifest for deployment of the GKE connect agent. + + **This method is used internally by Google-provided libraries.** + Most clients should not need to call this method directly. + + Args: + request (:class:`google.cloud.gkehub_v1.types.GenerateConnectManifestRequest`): + The request object. Request message for + `GkeHub.GenerateConnectManifest` method. + . + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.gkehub_v1.types.GenerateConnectManifestResponse: + GenerateConnectManifestResponse + contains manifest information for + installing/upgrading a Connect agent. + + """ + # Create or coerce a protobuf request object. + request = service.GenerateConnectManifestRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.generate_connect_manifest, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution("google-cloud-gke-hub",).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("GkeHubAsyncClient",) diff --git a/google/cloud/gkehub_v1/services/gke_hub/client.py b/google/cloud/gkehub_v1/services/gke_hub/client.py new file mode 100644 index 0000000..59f4467 --- /dev/null +++ b/google/cloud/gkehub_v1/services/gke_hub/client.py @@ -0,0 +1,1369 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +from distutils import util +import os +import re +from typing import Callable, Dict, Optional, Sequence, Tuple, Type, Union +import pkg_resources + +from google.api_core import client_options as client_options_lib # type: ignore +from google.api_core import exceptions as core_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 as ga_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 # type: ignore +from google.api_core import operation_async # type: ignore +from google.cloud.gkehub_v1.services.gke_hub import pagers +from google.cloud.gkehub_v1.types import feature +from google.cloud.gkehub_v1.types import membership +from google.cloud.gkehub_v1.types import service +from google.protobuf import empty_pb2 # type: ignore +from google.protobuf import field_mask_pb2 # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore +from .transports.base import GkeHubTransport, DEFAULT_CLIENT_INFO +from .transports.grpc import GkeHubGrpcTransport +from .transports.grpc_asyncio import GkeHubGrpcAsyncIOTransport + + +class GkeHubClientMeta(type): + """Metaclass for the GkeHub client. + + This provides class-level methods for building and retrieving + support objects (e.g. transport) without polluting the client instance + objects. + """ + + _transport_registry = OrderedDict() # type: Dict[str, Type[GkeHubTransport]] + _transport_registry["grpc"] = GkeHubGrpcTransport + _transport_registry["grpc_asyncio"] = GkeHubGrpcAsyncIOTransport + + def get_transport_class(cls, label: str = None,) -> Type[GkeHubTransport]: + """Returns an appropriate transport class. + + Args: + label: The name of the desired transport. If none is + provided, then the first transport in the registry is used. + + Returns: + The transport class to use. + """ + # If a specific transport is requested, return that one. + if label: + return cls._transport_registry[label] + + # No transport is requested; return the default (that is, the first one + # in the dictionary). + return next(iter(cls._transport_registry.values())) + + +class GkeHubClient(metaclass=GkeHubClientMeta): + """The GKE Hub service handles the registration of many Kubernetes + clusters to Google Cloud, and the management of multi-cluster + features over those clusters. + + The GKE Hub service operates on the following resources: + + - [Membership][google.cloud.gkehub_v1.Membership] + - [Feature][google.cloud.gkehub_v1.Feature] + + GKE Hub is currently only available in the global region. + + **Membership management may be non-trivial:** it is recommended to + use one of the Google-provided client libraries or tools where + possible when working with Membership resources. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + DEFAULT_ENDPOINT = "gkehub.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials + info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GkeHubClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_info(info) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GkeHubClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_file(filename) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + from_service_account_json = from_service_account_file + + @property + def transport(self) -> GkeHubTransport: + """Returns the transport used by the client instance. + + Returns: + GkeHubTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def feature_path(project: str, location: str, feature: str,) -> str: + """Returns a fully-qualified feature string.""" + return "projects/{project}/locations/{location}/features/{feature}".format( + project=project, location=location, feature=feature, + ) + + @staticmethod + def parse_feature_path(path: str) -> Dict[str, str]: + """Parses a feature path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/features/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def membership_path(project: str, location: str, membership: str,) -> str: + """Returns a fully-qualified membership string.""" + return "projects/{project}/locations/{location}/memberships/{membership}".format( + project=project, location=location, membership=membership, + ) + + @staticmethod + def parse_membership_path(path: str) -> Dict[str, str]: + """Parses a membership path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/memberships/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def common_billing_account_path(billing_account: str,) -> str: + """Returns 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: + """Returns 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: + """Returns 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: + """Returns 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: + """Returns 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: Optional[ga_credentials.Credentials] = None, + transport: Union[str, GkeHubTransport, None] = None, + client_options: Optional[client_options_lib.ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the gke hub client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Union[str, GkeHubTransport]): The + transport to use. If set to None, a transport is chosen + automatically. + client_options (google.api_core.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_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) 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 = client_options_lib.from_dict(client_options) + if client_options is None: + 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")) + ) + + client_cert_source_func = None + is_mtls = False + if use_client_cert: + if client_options.client_cert_source: + is_mtls = True + client_cert_source_func = client_options.client_cert_source + else: + is_mtls = mtls.has_default_client_cert_source() + if is_mtls: + client_cert_source_func = mtls.default_client_cert_source() + else: + client_cert_source_func = 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": + api_endpoint = self.DEFAULT_ENDPOINT + elif use_mtls_env == "always": + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + elif use_mtls_env == "auto": + if is_mtls: + api_endpoint = self.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = self.DEFAULT_ENDPOINT + else: + raise MutualTLSChannelError( + "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted " + "values: never, auto, always" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + if isinstance(transport, GkeHubTransport): + # transport is a GkeHubTransport instance. + if credentials or client_options.credentials_file: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = transport + else: + Transport = type(self).get_transport_class(transport) + self._transport = Transport( + credentials=credentials, + credentials_file=client_options.credentials_file, + host=api_endpoint, + scopes=client_options.scopes, + client_cert_source_for_mtls=client_cert_source_func, + quota_project_id=client_options.quota_project_id, + client_info=client_info, + ) + + def list_memberships( + self, + request: service.ListMembershipsRequest = None, + *, + parent: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> pagers.ListMembershipsPager: + r"""Lists Memberships in a given project and location. + + Args: + request (google.cloud.gkehub_v1.types.ListMembershipsRequest): + The request object. Request message for + `GkeHub.ListMemberships` method. + parent (str): + Required. The parent (project and location) where the + Memberships will be listed. Specified in the format + ``projects/*/locations/*``. + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.gkehub_v1.services.gke_hub.pagers.ListMembershipsPager: + Response message for the GkeHub.ListMemberships method. + + Iterating over this object will yield results and + resolve additional pages automatically. + + """ + # 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. + 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a service.ListMembershipsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, service.ListMembershipsRequest): + request = service.ListMembershipsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.list_memberships] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # This method is paged; wrap the response in a pager, which provides + # an `__iter__` convenience method. + response = pagers.ListMembershipsPager( + method=rpc, request=request, response=response, metadata=metadata, + ) + + # Done; return the response. + return response + + def list_features( + self, + request: service.ListFeaturesRequest = None, + *, + parent: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> pagers.ListFeaturesPager: + r"""Lists Features in a given project and location. + + Args: + request (google.cloud.gkehub_v1.types.ListFeaturesRequest): + The request object. Request message for + `GkeHub.ListFeatures` method. + parent (str): + The parent (project and location) where the Features + will be listed. Specified in the format + ``projects/*/locations/*``. + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.gkehub_v1.services.gke_hub.pagers.ListFeaturesPager: + Response message for the GkeHub.ListFeatures method. + + Iterating over this object will yield results and + resolve additional pages automatically. + + """ + # 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. + 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a service.ListFeaturesRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, service.ListFeaturesRequest): + request = service.ListFeaturesRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.list_features] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # This method is paged; wrap the response in a pager, which provides + # an `__iter__` convenience method. + response = pagers.ListFeaturesPager( + method=rpc, request=request, response=response, metadata=metadata, + ) + + # Done; return the response. + return response + + def get_membership( + self, + request: service.GetMembershipRequest = None, + *, + name: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> membership.Membership: + r"""Gets the details of a Membership. + + Args: + request (google.cloud.gkehub_v1.types.GetMembershipRequest): + The request object. Request message for + `GkeHub.GetMembership` method. + name (str): + Required. The Membership resource name in the format + ``projects/*/locations/*/memberships/*``. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.gkehub_v1.types.Membership: + Membership contains information about + a member 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. + 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a service.GetMembershipRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, service.GetMembershipRequest): + request = service.GetMembershipRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.get_membership] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Done; return the response. + return response + + def get_feature( + self, + request: service.GetFeatureRequest = None, + *, + name: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> feature.Feature: + r"""Gets details of a single Feature. + + Args: + request (google.cloud.gkehub_v1.types.GetFeatureRequest): + The request object. Request message for + `GkeHub.GetFeature` method. + name (str): + The Feature resource name in the format + ``projects/*/locations/*/features/*`` + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.gkehub_v1.types.Feature: + Feature represents the settings and + status of any Hub Feature. + + """ + # 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. + 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a service.GetFeatureRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, service.GetFeatureRequest): + request = service.GetFeatureRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.get_feature] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Done; return the response. + return response + + def create_membership( + self, + request: service.CreateMembershipRequest = None, + *, + parent: str = None, + resource: membership.Membership = None, + membership_id: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation.Operation: + r"""Creates a new Membership. + + **This is currently only supported for GKE clusters on Google + Cloud**. To register other clusters, follow the instructions at + https://cloud.google.com/anthos/multicluster-management/connect/registering-a-cluster. + + Args: + request (google.cloud.gkehub_v1.types.CreateMembershipRequest): + The request object. Request message for the + `GkeHub.CreateMembership` method. + parent (str): + Required. The parent (project and location) where the + Memberships will be created. Specified in the format + ``projects/*/locations/*``. + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource (google.cloud.gkehub_v1.types.Membership): + Required. The membership to create. + This corresponds to the ``resource`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + membership_id (str): + Required. Client chosen ID for the membership. + ``membership_id`` must be a valid RFC 1123 compliant DNS + label: + + 1. At most 63 characters in length + 2. It must consist of lower case alphanumeric characters + or ``-`` + 3. It must start and end with an alphanumeric character + + Which can be expressed as the regex: + ``[a-z0-9]([-a-z0-9]*[a-z0-9])?``, with a maximum length + of 63 characters. + + This corresponds to the ``membership_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be + :class:`google.cloud.gkehub_v1.types.Membership` + Membership contains information about a member 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. + has_flattened_params = any([parent, resource, membership_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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a service.CreateMembershipRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, service.CreateMembershipRequest): + request = service.CreateMembershipRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if resource is not None: + request.resource = resource + if membership_id is not None: + request.membership_id = membership_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.create_membership] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Wrap the response in an operation future. + response = operation.from_gapic( + response, + self._transport.operations_client, + membership.Membership, + metadata_type=service.OperationMetadata, + ) + + # Done; return the response. + return response + + def create_feature( + self, + request: service.CreateFeatureRequest = None, + *, + parent: str = None, + resource: feature.Feature = None, + feature_id: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation.Operation: + r"""Adds a new Feature. + + Args: + request (google.cloud.gkehub_v1.types.CreateFeatureRequest): + The request object. Request message for the + `GkeHub.CreateFeature` method. + parent (str): + The parent (project and location) where the Feature will + be created. Specified in the format + ``projects/*/locations/*``. + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource (google.cloud.gkehub_v1.types.Feature): + The Feature resource to create. + This corresponds to the ``resource`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + feature_id (str): + The ID of the feature to create. + This corresponds to the ``feature_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be + :class:`google.cloud.gkehub_v1.types.Feature` Feature + represents the settings and status of any Hub Feature. + + """ + # 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. + has_flattened_params = any([parent, resource, feature_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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a service.CreateFeatureRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, service.CreateFeatureRequest): + request = service.CreateFeatureRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if resource is not None: + request.resource = resource + if feature_id is not None: + request.feature_id = feature_id + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.create_feature] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Wrap the response in an operation future. + response = operation.from_gapic( + response, + self._transport.operations_client, + feature.Feature, + metadata_type=service.OperationMetadata, + ) + + # Done; return the response. + return response + + def delete_membership( + self, + request: service.DeleteMembershipRequest = None, + *, + name: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation.Operation: + r"""Removes a Membership. + + **This is currently only supported for GKE clusters on Google + Cloud**. To unregister other clusters, follow the instructions + at + https://cloud.google.com/anthos/multicluster-management/connect/unregistering-a-cluster. + + Args: + request (google.cloud.gkehub_v1.types.DeleteMembershipRequest): + The request object. Request message for + `GkeHub.DeleteMembership` method. + name (str): + Required. The Membership resource name in the format + ``projects/*/locations/*/memberships/*``. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.protobuf.empty_pb2.Empty` A generic empty message that you can re-use to avoid defining duplicated + empty messages in your APIs. A typical example is to + use it as the request or the response type of an API + method. For instance: + + service Foo { + rpc Bar(google.protobuf.Empty) returns + (google.protobuf.Empty); + + } + + The JSON representation for Empty is empty JSON + object {}. + + """ + # 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. + 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a service.DeleteMembershipRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, service.DeleteMembershipRequest): + request = service.DeleteMembershipRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.delete_membership] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Wrap the response in an operation future. + response = operation.from_gapic( + response, + self._transport.operations_client, + empty_pb2.Empty, + metadata_type=service.OperationMetadata, + ) + + # Done; return the response. + return response + + def delete_feature( + self, + request: service.DeleteFeatureRequest = None, + *, + name: str = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation.Operation: + r"""Removes a Feature. + + Args: + request (google.cloud.gkehub_v1.types.DeleteFeatureRequest): + The request object. Request message for + `GkeHub.DeleteFeature` method. + name (str): + The Feature resource name in the format + ``projects/*/locations/*/features/*``. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.protobuf.empty_pb2.Empty` A generic empty message that you can re-use to avoid defining duplicated + empty messages in your APIs. A typical example is to + use it as the request or the response type of an API + method. For instance: + + service Foo { + rpc Bar(google.protobuf.Empty) returns + (google.protobuf.Empty); + + } + + The JSON representation for Empty is empty JSON + object {}. + + """ + # 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. + 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a service.DeleteFeatureRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, service.DeleteFeatureRequest): + request = service.DeleteFeatureRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.delete_feature] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Wrap the response in an operation future. + response = operation.from_gapic( + response, + self._transport.operations_client, + empty_pb2.Empty, + metadata_type=service.OperationMetadata, + ) + + # Done; return the response. + return response + + def update_membership( + self, + request: service.UpdateMembershipRequest = None, + *, + name: str = None, + resource: membership.Membership = None, + update_mask: field_mask_pb2.FieldMask = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation.Operation: + r"""Updates an existing Membership. + + Args: + request (google.cloud.gkehub_v1.types.UpdateMembershipRequest): + The request object. Request message for + `GkeHub.UpdateMembership` method. + name (str): + Required. The Membership resource name in the format + ``projects/*/locations/*/memberships/*``. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource (google.cloud.gkehub_v1.types.Membership): + Required. Only fields specified in update_mask are + updated. If you specify a field in the update_mask but + don't specify its value here that field will be deleted. + If you are updating a map field, set the value of a key + to null or empty string to delete the key from the map. + It's not possible to update a key's value to the empty + string. If you specify the update_mask to be a special + path "*", fully replaces all user-modifiable fields to + match ``resource``. + + This corresponds to the ``resource`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Required. Mask of fields to update. + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be + :class:`google.cloud.gkehub_v1.types.Membership` + Membership contains information about a member 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. + has_flattened_params = any([name, resource, 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a service.UpdateMembershipRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, service.UpdateMembershipRequest): + request = service.UpdateMembershipRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + if resource is not None: + request.resource = resource + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.update_membership] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Wrap the response in an operation future. + response = operation.from_gapic( + response, + self._transport.operations_client, + membership.Membership, + metadata_type=service.OperationMetadata, + ) + + # Done; return the response. + return response + + def update_feature( + self, + request: service.UpdateFeatureRequest = None, + *, + name: str = None, + resource: feature.Feature = None, + update_mask: field_mask_pb2.FieldMask = None, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation.Operation: + r"""Updates an existing Feature. + + Args: + request (google.cloud.gkehub_v1.types.UpdateFeatureRequest): + The request object. Request message for + `GkeHub.UpdateFeature` method. + name (str): + The Feature resource name in the format + ``projects/*/locations/*/features/*``. + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + resource (google.cloud.gkehub_v1.types.Feature): + Only fields specified in update_mask are updated. If you + specify a field in the update_mask but don't specify its + value here that field will be deleted. If you are + updating a map field, set the value of a key to null or + empty string to delete the key from the map. It's not + possible to update a key's value to the empty string. If + you specify the update_mask to be a special path "*", + fully replaces all user-modifiable fields to match + ``resource``. + + This corresponds to the ``resource`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Mask of fields to update. + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be + :class:`google.cloud.gkehub_v1.types.Feature` Feature + represents the settings and status of any Hub Feature. + + """ + # 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. + has_flattened_params = any([name, resource, 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a service.UpdateFeatureRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, service.UpdateFeatureRequest): + request = service.UpdateFeatureRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + if resource is not None: + request.resource = resource + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.update_feature] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Wrap the response in an operation future. + response = operation.from_gapic( + response, + self._transport.operations_client, + feature.Feature, + metadata_type=service.OperationMetadata, + ) + + # Done; return the response. + return response + + def generate_connect_manifest( + self, + request: service.GenerateConnectManifestRequest = None, + *, + retry: retries.Retry = gapic_v1.method.DEFAULT, + timeout: float = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> service.GenerateConnectManifestResponse: + r"""Generates the manifest for deployment of the GKE connect agent. + + **This method is used internally by Google-provided libraries.** + Most clients should not need to call this method directly. + + Args: + request (google.cloud.gkehub_v1.types.GenerateConnectManifestRequest): + The request object. Request message for + `GkeHub.GenerateConnectManifest` method. + . + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.gkehub_v1.types.GenerateConnectManifestResponse: + GenerateConnectManifestResponse + contains manifest information for + installing/upgrading a Connect agent. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a service.GenerateConnectManifestRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, service.GenerateConnectManifestRequest): + request = service.GenerateConnectManifestRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.generate_connect_manifest + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Send the request. + response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,) + + # Done; return the response. + return response + + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution("google-cloud-gke-hub",).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + + +__all__ = ("GkeHubClient",) diff --git a/google/cloud/gkehub_v1/services/gke_hub/pagers.py b/google/cloud/gkehub_v1/services/gke_hub/pagers.py new file mode 100644 index 0000000..72da7bd --- /dev/null +++ b/google/cloud/gkehub_v1/services/gke_hub/pagers.py @@ -0,0 +1,285 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from typing import ( + Any, + AsyncIterable, + Awaitable, + Callable, + Iterable, + Sequence, + Tuple, + Optional, +) + +from google.cloud.gkehub_v1.types import feature +from google.cloud.gkehub_v1.types import membership +from google.cloud.gkehub_v1.types import service + + +class ListMembershipsPager: + """A pager for iterating through ``list_memberships`` requests. + + This class thinly wraps an initial + :class:`google.cloud.gkehub_v1.types.ListMembershipsResponse` object, and + provides an ``__iter__`` method to iterate through its + ``resources`` field. + + If there are more pages, the ``__iter__`` method will make additional + ``ListMemberships`` requests and continue to iterate + through the ``resources`` field on the + corresponding responses. + + All the usual :class:`google.cloud.gkehub_v1.types.ListMembershipsResponse` + attributes are available on the pager. If multiple requests are made, only + the most recent response is retained, and thus used for attribute lookup. + """ + + def __init__( + self, + method: Callable[..., service.ListMembershipsResponse], + request: service.ListMembershipsRequest, + response: service.ListMembershipsResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.gkehub_v1.types.ListMembershipsRequest): + The initial request object. + response (google.cloud.gkehub_v1.types.ListMembershipsResponse): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = service.ListMembershipsRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + def pages(self) -> Iterable[service.ListMembershipsResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = self._method(self._request, metadata=self._metadata) + yield self._response + + def __iter__(self) -> Iterable[membership.Membership]: + for page in self.pages: + yield from page.resources + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class ListMembershipsAsyncPager: + """A pager for iterating through ``list_memberships`` requests. + + This class thinly wraps an initial + :class:`google.cloud.gkehub_v1.types.ListMembershipsResponse` object, and + provides an ``__aiter__`` method to iterate through its + ``resources`` field. + + If there are more pages, the ``__aiter__`` method will make additional + ``ListMemberships`` requests and continue to iterate + through the ``resources`` field on the + corresponding responses. + + All the usual :class:`google.cloud.gkehub_v1.types.ListMembershipsResponse` + attributes are available on the pager. If multiple requests are made, only + the most recent response is retained, and thus used for attribute lookup. + """ + + def __init__( + self, + method: Callable[..., Awaitable[service.ListMembershipsResponse]], + request: service.ListMembershipsRequest, + response: service.ListMembershipsResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiates the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.gkehub_v1.types.ListMembershipsRequest): + The initial request object. + response (google.cloud.gkehub_v1.types.ListMembershipsResponse): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = service.ListMembershipsRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + async def pages(self) -> AsyncIterable[service.ListMembershipsResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = await self._method(self._request, metadata=self._metadata) + yield self._response + + def __aiter__(self) -> AsyncIterable[membership.Membership]: + async def async_generator(): + async for page in self.pages: + for response in page.resources: + yield response + + return async_generator() + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class ListFeaturesPager: + """A pager for iterating through ``list_features`` requests. + + This class thinly wraps an initial + :class:`google.cloud.gkehub_v1.types.ListFeaturesResponse` object, and + provides an ``__iter__`` method to iterate through its + ``resources`` field. + + If there are more pages, the ``__iter__`` method will make additional + ``ListFeatures`` requests and continue to iterate + through the ``resources`` field on the + corresponding responses. + + All the usual :class:`google.cloud.gkehub_v1.types.ListFeaturesResponse` + attributes are available on the pager. If multiple requests are made, only + the most recent response is retained, and thus used for attribute lookup. + """ + + def __init__( + self, + method: Callable[..., service.ListFeaturesResponse], + request: service.ListFeaturesRequest, + response: service.ListFeaturesResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.gkehub_v1.types.ListFeaturesRequest): + The initial request object. + response (google.cloud.gkehub_v1.types.ListFeaturesResponse): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = service.ListFeaturesRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + def pages(self) -> Iterable[service.ListFeaturesResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = self._method(self._request, metadata=self._metadata) + yield self._response + + def __iter__(self) -> Iterable[feature.Feature]: + for page in self.pages: + yield from page.resources + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class ListFeaturesAsyncPager: + """A pager for iterating through ``list_features`` requests. + + This class thinly wraps an initial + :class:`google.cloud.gkehub_v1.types.ListFeaturesResponse` object, and + provides an ``__aiter__`` method to iterate through its + ``resources`` field. + + If there are more pages, the ``__aiter__`` method will make additional + ``ListFeatures`` requests and continue to iterate + through the ``resources`` field on the + corresponding responses. + + All the usual :class:`google.cloud.gkehub_v1.types.ListFeaturesResponse` + attributes are available on the pager. If multiple requests are made, only + the most recent response is retained, and thus used for attribute lookup. + """ + + def __init__( + self, + method: Callable[..., Awaitable[service.ListFeaturesResponse]], + request: service.ListFeaturesRequest, + response: service.ListFeaturesResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiates the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.gkehub_v1.types.ListFeaturesRequest): + The initial request object. + response (google.cloud.gkehub_v1.types.ListFeaturesResponse): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = service.ListFeaturesRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + async def pages(self) -> AsyncIterable[service.ListFeaturesResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = await self._method(self._request, metadata=self._metadata) + yield self._response + + def __aiter__(self) -> AsyncIterable[feature.Feature]: + async def async_generator(): + async for page in self.pages: + for response in page.resources: + yield response + + return async_generator() + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) diff --git a/google/cloud/gkehub_v1/services/gke_hub/transports/__init__.py b/google/cloud/gkehub_v1/services/gke_hub/transports/__init__.py new file mode 100644 index 0000000..50e3055 --- /dev/null +++ b/google/cloud/gkehub_v1/services/gke_hub/transports/__init__.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +from typing import Dict, Type + +from .base import GkeHubTransport +from .grpc import GkeHubGrpcTransport +from .grpc_asyncio import GkeHubGrpcAsyncIOTransport + + +# Compile a registry of transports. +_transport_registry = OrderedDict() # type: Dict[str, Type[GkeHubTransport]] +_transport_registry["grpc"] = GkeHubGrpcTransport +_transport_registry["grpc_asyncio"] = GkeHubGrpcAsyncIOTransport + +__all__ = ( + "GkeHubTransport", + "GkeHubGrpcTransport", + "GkeHubGrpcAsyncIOTransport", +) diff --git a/google/cloud/gkehub_v1/services/gke_hub/transports/base.py b/google/cloud/gkehub_v1/services/gke_hub/transports/base.py new file mode 100644 index 0000000..9b814e6 --- /dev/null +++ b/google/cloud/gkehub_v1/services/gke_hub/transports/base.py @@ -0,0 +1,305 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import abc +from typing import Awaitable, Callable, Dict, Optional, Sequence, Union +import packaging.version +import pkg_resources + +import google.auth # type: ignore +import google.api_core # type: ignore +from google.api_core import exceptions as core_exceptions # type: ignore +from google.api_core import gapic_v1 # type: ignore +from google.api_core import retry as retries # type: ignore +from google.api_core import operations_v1 # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.gkehub_v1.types import feature +from google.cloud.gkehub_v1.types import membership +from google.cloud.gkehub_v1.types import service +from google.longrunning import operations_pb2 # type: ignore + +try: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=pkg_resources.get_distribution("google-cloud-gke-hub",).version, + ) +except pkg_resources.DistributionNotFound: + DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo() + +try: + # google.auth.__version__ was added in 1.26.0 + _GOOGLE_AUTH_VERSION = google.auth.__version__ +except AttributeError: + try: # try pkg_resources if it is available + _GOOGLE_AUTH_VERSION = pkg_resources.get_distribution("google-auth").version + except pkg_resources.DistributionNotFound: # pragma: NO COVER + _GOOGLE_AUTH_VERSION = None + + +class GkeHubTransport(abc.ABC): + """Abstract transport class for GkeHub.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + + DEFAULT_HOST: str = "gkehub.googleapis.com" + + def __init__( + self, + *, + host: str = DEFAULT_HOST, + credentials: ga_credentials.Credentials = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (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. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) + + # Save the scopes. + self._scopes = scopes + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, **scopes_kwargs, quota_project_id=quota_project_id + ) + + elif credentials is None: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + + # If the credentials is service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # TODO(busunkim): This method is in the base transport + # to avoid duplicating code across the transport classes. These functions + # should be deleted once the minimum required versions of google-auth is increased. + + # TODO: Remove this function once google-auth >= 1.25.0 is required + @classmethod + def _get_scopes_kwargs( + cls, host: str, scopes: Optional[Sequence[str]] + ) -> Dict[str, Optional[Sequence[str]]]: + """Returns scopes kwargs to pass to google-auth methods depending on the google-auth version""" + + scopes_kwargs = {} + + if _GOOGLE_AUTH_VERSION and ( + packaging.version.parse(_GOOGLE_AUTH_VERSION) + >= packaging.version.parse("1.25.0") + ): + scopes_kwargs = {"scopes": scopes, "default_scopes": cls.AUTH_SCOPES} + else: + scopes_kwargs = {"scopes": scopes or cls.AUTH_SCOPES} + + return scopes_kwargs + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.list_memberships: gapic_v1.method.wrap_method( + self.list_memberships, default_timeout=None, client_info=client_info, + ), + self.list_features: gapic_v1.method.wrap_method( + self.list_features, default_timeout=None, client_info=client_info, + ), + self.get_membership: gapic_v1.method.wrap_method( + self.get_membership, default_timeout=None, client_info=client_info, + ), + self.get_feature: gapic_v1.method.wrap_method( + self.get_feature, default_timeout=None, client_info=client_info, + ), + self.create_membership: gapic_v1.method.wrap_method( + self.create_membership, default_timeout=None, client_info=client_info, + ), + self.create_feature: gapic_v1.method.wrap_method( + self.create_feature, default_timeout=None, client_info=client_info, + ), + self.delete_membership: gapic_v1.method.wrap_method( + self.delete_membership, default_timeout=None, client_info=client_info, + ), + self.delete_feature: gapic_v1.method.wrap_method( + self.delete_feature, default_timeout=None, client_info=client_info, + ), + self.update_membership: gapic_v1.method.wrap_method( + self.update_membership, default_timeout=None, client_info=client_info, + ), + self.update_feature: gapic_v1.method.wrap_method( + self.update_feature, default_timeout=None, client_info=client_info, + ), + self.generate_connect_manifest: gapic_v1.method.wrap_method( + self.generate_connect_manifest, + default_timeout=None, + client_info=client_info, + ), + } + + @property + def operations_client(self) -> operations_v1.OperationsClient: + """Return the client designed to process long-running operations.""" + raise NotImplementedError() + + @property + def list_memberships( + self, + ) -> Callable[ + [service.ListMembershipsRequest], + Union[ + service.ListMembershipsResponse, Awaitable[service.ListMembershipsResponse] + ], + ]: + raise NotImplementedError() + + @property + def list_features( + self, + ) -> Callable[ + [service.ListFeaturesRequest], + Union[service.ListFeaturesResponse, Awaitable[service.ListFeaturesResponse]], + ]: + raise NotImplementedError() + + @property + def get_membership( + self, + ) -> Callable[ + [service.GetMembershipRequest], + Union[membership.Membership, Awaitable[membership.Membership]], + ]: + raise NotImplementedError() + + @property + def get_feature( + self, + ) -> Callable[ + [service.GetFeatureRequest], Union[feature.Feature, Awaitable[feature.Feature]] + ]: + raise NotImplementedError() + + @property + def create_membership( + self, + ) -> Callable[ + [service.CreateMembershipRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def create_feature( + self, + ) -> Callable[ + [service.CreateFeatureRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def delete_membership( + self, + ) -> Callable[ + [service.DeleteMembershipRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def delete_feature( + self, + ) -> Callable[ + [service.DeleteFeatureRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def update_membership( + self, + ) -> Callable[ + [service.UpdateMembershipRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def update_feature( + self, + ) -> Callable[ + [service.UpdateFeatureRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def generate_connect_manifest( + self, + ) -> Callable[ + [service.GenerateConnectManifestRequest], + Union[ + service.GenerateConnectManifestResponse, + Awaitable[service.GenerateConnectManifestResponse], + ], + ]: + raise NotImplementedError() + + +__all__ = ("GkeHubTransport",) diff --git a/google/cloud/gkehub_v1/services/gke_hub/transports/grpc.py b/google/cloud/gkehub_v1/services/gke_hub/transports/grpc.py new file mode 100644 index 0000000..0614912 --- /dev/null +++ b/google/cloud/gkehub_v1/services/gke_hub/transports/grpc.py @@ -0,0 +1,560 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +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 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore + +import grpc # type: ignore + +from google.cloud.gkehub_v1.types import feature +from google.cloud.gkehub_v1.types import membership +from google.cloud.gkehub_v1.types import service +from google.longrunning import operations_pb2 # type: ignore +from .base import GkeHubTransport, DEFAULT_CLIENT_INFO + + +class GkeHubGrpcTransport(GkeHubTransport): + """gRPC backend transport for GkeHub. + + The GKE Hub service handles the registration of many Kubernetes + clusters to Google Cloud, and the management of multi-cluster + features over those clusters. + + The GKE Hub service operates on the following resources: + + - [Membership][google.cloud.gkehub_v1.Membership] + - [Feature][google.cloud.gkehub_v1.Feature] + + GKE Hub is currently only available in the global region. + + **Membership management may be non-trivial:** it is recommended to + use one of the Google-provided client libraries or tools where + possible when working with Membership resources. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _stubs: Dict[str, Callable] + + def __init__( + self, + *, + host: str = "gkehub.googleapis.com", + credentials: ga_credentials.Credentials = None, + credentials_file: str = None, + scopes: Sequence[str] = None, + channel: grpc.Channel = None, + api_mtls_endpoint: str = None, + client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, + ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + 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]]]): + 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. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + 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. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + credentials=self._credentials, + credentials_file=credentials_file, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "gkehub.googleapis.com", + credentials: ga_credentials.Credentials = None, + credentials_file: str = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + **kwargs, + ) -> grpc.Channel: + """Create and return a gRPC channel object. + Args: + host (Optional[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service. + """ + return self._grpc_channel + + @property + def operations_client(self) -> operations_v1.OperationsClient: + """Create the client designed to process long-running operations. + + This property caches on the instance; repeated calls return the same + client. + """ + # Sanity check: Only create a new client if we do not already have one. + if self._operations_client is None: + self._operations_client = operations_v1.OperationsClient(self.grpc_channel) + + # Return the client from cache. + return self._operations_client + + @property + def list_memberships( + self, + ) -> Callable[[service.ListMembershipsRequest], service.ListMembershipsResponse]: + r"""Return a callable for the list memberships method over gRPC. + + Lists Memberships in a given project and location. + + Returns: + Callable[[~.ListMembershipsRequest], + ~.ListMembershipsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_memberships" not in self._stubs: + self._stubs["list_memberships"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/ListMemberships", + request_serializer=service.ListMembershipsRequest.serialize, + response_deserializer=service.ListMembershipsResponse.deserialize, + ) + return self._stubs["list_memberships"] + + @property + def list_features( + self, + ) -> Callable[[service.ListFeaturesRequest], service.ListFeaturesResponse]: + r"""Return a callable for the list features method over gRPC. + + Lists Features in a given project and location. + + Returns: + Callable[[~.ListFeaturesRequest], + ~.ListFeaturesResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_features" not in self._stubs: + self._stubs["list_features"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/ListFeatures", + request_serializer=service.ListFeaturesRequest.serialize, + response_deserializer=service.ListFeaturesResponse.deserialize, + ) + return self._stubs["list_features"] + + @property + def get_membership( + self, + ) -> Callable[[service.GetMembershipRequest], membership.Membership]: + r"""Return a callable for the get membership method over gRPC. + + Gets the details of a Membership. + + Returns: + Callable[[~.GetMembershipRequest], + ~.Membership]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_membership" not in self._stubs: + self._stubs["get_membership"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/GetMembership", + request_serializer=service.GetMembershipRequest.serialize, + response_deserializer=membership.Membership.deserialize, + ) + return self._stubs["get_membership"] + + @property + def get_feature(self) -> Callable[[service.GetFeatureRequest], feature.Feature]: + r"""Return a callable for the get feature method over gRPC. + + Gets details of a single Feature. + + Returns: + Callable[[~.GetFeatureRequest], + ~.Feature]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_feature" not in self._stubs: + self._stubs["get_feature"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/GetFeature", + request_serializer=service.GetFeatureRequest.serialize, + response_deserializer=feature.Feature.deserialize, + ) + return self._stubs["get_feature"] + + @property + def create_membership( + self, + ) -> Callable[[service.CreateMembershipRequest], operations_pb2.Operation]: + r"""Return a callable for the create membership method over gRPC. + + Creates a new Membership. + + **This is currently only supported for GKE clusters on Google + Cloud**. To register other clusters, follow the instructions at + https://cloud.google.com/anthos/multicluster-management/connect/registering-a-cluster. + + Returns: + Callable[[~.CreateMembershipRequest], + ~.Operation]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_membership" not in self._stubs: + self._stubs["create_membership"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/CreateMembership", + request_serializer=service.CreateMembershipRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["create_membership"] + + @property + def create_feature( + self, + ) -> Callable[[service.CreateFeatureRequest], operations_pb2.Operation]: + r"""Return a callable for the create feature method over gRPC. + + Adds a new Feature. + + Returns: + Callable[[~.CreateFeatureRequest], + ~.Operation]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_feature" not in self._stubs: + self._stubs["create_feature"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/CreateFeature", + request_serializer=service.CreateFeatureRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["create_feature"] + + @property + def delete_membership( + self, + ) -> Callable[[service.DeleteMembershipRequest], operations_pb2.Operation]: + r"""Return a callable for the delete membership method over gRPC. + + Removes a Membership. + + **This is currently only supported for GKE clusters on Google + Cloud**. To unregister other clusters, follow the instructions + at + https://cloud.google.com/anthos/multicluster-management/connect/unregistering-a-cluster. + + Returns: + Callable[[~.DeleteMembershipRequest], + ~.Operation]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "delete_membership" not in self._stubs: + self._stubs["delete_membership"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/DeleteMembership", + request_serializer=service.DeleteMembershipRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["delete_membership"] + + @property + def delete_feature( + self, + ) -> Callable[[service.DeleteFeatureRequest], operations_pb2.Operation]: + r"""Return a callable for the delete feature method over gRPC. + + Removes a Feature. + + Returns: + Callable[[~.DeleteFeatureRequest], + ~.Operation]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "delete_feature" not in self._stubs: + self._stubs["delete_feature"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/DeleteFeature", + request_serializer=service.DeleteFeatureRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["delete_feature"] + + @property + def update_membership( + self, + ) -> Callable[[service.UpdateMembershipRequest], operations_pb2.Operation]: + r"""Return a callable for the update membership method over gRPC. + + Updates an existing Membership. + + Returns: + Callable[[~.UpdateMembershipRequest], + ~.Operation]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_membership" not in self._stubs: + self._stubs["update_membership"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/UpdateMembership", + request_serializer=service.UpdateMembershipRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["update_membership"] + + @property + def update_feature( + self, + ) -> Callable[[service.UpdateFeatureRequest], operations_pb2.Operation]: + r"""Return a callable for the update feature method over gRPC. + + Updates an existing Feature. + + Returns: + Callable[[~.UpdateFeatureRequest], + ~.Operation]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_feature" not in self._stubs: + self._stubs["update_feature"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/UpdateFeature", + request_serializer=service.UpdateFeatureRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["update_feature"] + + @property + def generate_connect_manifest( + self, + ) -> Callable[ + [service.GenerateConnectManifestRequest], + service.GenerateConnectManifestResponse, + ]: + r"""Return a callable for the generate connect manifest method over gRPC. + + Generates the manifest for deployment of the GKE connect agent. + + **This method is used internally by Google-provided libraries.** + Most clients should not need to call this method directly. + + Returns: + Callable[[~.GenerateConnectManifestRequest], + ~.GenerateConnectManifestResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "generate_connect_manifest" not in self._stubs: + self._stubs["generate_connect_manifest"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/GenerateConnectManifest", + request_serializer=service.GenerateConnectManifestRequest.serialize, + response_deserializer=service.GenerateConnectManifestResponse.deserialize, + ) + return self._stubs["generate_connect_manifest"] + + +__all__ = ("GkeHubGrpcTransport",) diff --git a/google/cloud/gkehub_v1/services/gke_hub/transports/grpc_asyncio.py b/google/cloud/gkehub_v1/services/gke_hub/transports/grpc_asyncio.py new file mode 100644 index 0000000..09e3173 --- /dev/null +++ b/google/cloud/gkehub_v1/services/gke_hub/transports/grpc_asyncio.py @@ -0,0 +1,577 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +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.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +import packaging.version + +import grpc # type: ignore +from grpc.experimental import aio # type: ignore + +from google.cloud.gkehub_v1.types import feature +from google.cloud.gkehub_v1.types import membership +from google.cloud.gkehub_v1.types import service +from google.longrunning import operations_pb2 # type: ignore +from .base import GkeHubTransport, DEFAULT_CLIENT_INFO +from .grpc import GkeHubGrpcTransport + + +class GkeHubGrpcAsyncIOTransport(GkeHubTransport): + """gRPC AsyncIO backend transport for GkeHub. + + The GKE Hub service handles the registration of many Kubernetes + clusters to Google Cloud, and the management of multi-cluster + features over those clusters. + + The GKE Hub service operates on the following resources: + + - [Membership][google.cloud.gkehub_v1.Membership] + - [Feature][google.cloud.gkehub_v1.Feature] + + GKE Hub is currently only available in the global region. + + **Membership management may be non-trivial:** it is recommended to + use one of the Google-provided client libraries or tools where + possible when working with Membership resources. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _grpc_channel: aio.Channel + _stubs: Dict[str, Callable] = {} + + @classmethod + def create_channel( + cls, + host: str = "gkehub.googleapis.com", + credentials: ga_credentials.Credentials = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + **kwargs, + ) -> aio.Channel: + """Create and return a gRPC AsyncIO channel object. + Args: + host (Optional[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + aio.Channel: A gRPC AsyncIO channel object. + """ + + return grpc_helpers_async.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + def __init__( + self, + *, + host: str = "gkehub.googleapis.com", + credentials: ga_credentials.Credentials = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: aio.Channel = None, + api_mtls_endpoint: str = None, + client_cert_source: Callable[[], Tuple[bytes, bytes]] = None, + ssl_channel_credentials: grpc.ChannelCredentials = None, + client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, + quota_project_id=None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to. + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if ``channel`` is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + channel (Optional[aio.Channel]): A ``Channel`` instance through + which to make calls. + 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]]]): + 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. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + 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. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + ) + + if not self._grpc_channel: + self._grpc_channel = type(self).create_channel( + self._host, + credentials=self._credentials, + credentials_file=credentials_file, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @property + def grpc_channel(self) -> aio.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 from cache. + return self._grpc_channel + + @property + def operations_client(self) -> operations_v1.OperationsAsyncClient: + """Create the client designed to process long-running operations. + + This property caches on the instance; repeated calls return the same + client. + """ + # Sanity check: Only create a new client if we do not already have one. + if self._operations_client is None: + self._operations_client = operations_v1.OperationsAsyncClient( + self.grpc_channel + ) + + # Return the client from cache. + return self._operations_client + + @property + def list_memberships( + self, + ) -> Callable[ + [service.ListMembershipsRequest], Awaitable[service.ListMembershipsResponse] + ]: + r"""Return a callable for the list memberships method over gRPC. + + Lists Memberships in a given project and location. + + Returns: + Callable[[~.ListMembershipsRequest], + Awaitable[~.ListMembershipsResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_memberships" not in self._stubs: + self._stubs["list_memberships"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/ListMemberships", + request_serializer=service.ListMembershipsRequest.serialize, + response_deserializer=service.ListMembershipsResponse.deserialize, + ) + return self._stubs["list_memberships"] + + @property + def list_features( + self, + ) -> Callable[ + [service.ListFeaturesRequest], Awaitable[service.ListFeaturesResponse] + ]: + r"""Return a callable for the list features method over gRPC. + + Lists Features in a given project and location. + + Returns: + Callable[[~.ListFeaturesRequest], + Awaitable[~.ListFeaturesResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_features" not in self._stubs: + self._stubs["list_features"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/ListFeatures", + request_serializer=service.ListFeaturesRequest.serialize, + response_deserializer=service.ListFeaturesResponse.deserialize, + ) + return self._stubs["list_features"] + + @property + def get_membership( + self, + ) -> Callable[[service.GetMembershipRequest], Awaitable[membership.Membership]]: + r"""Return a callable for the get membership method over gRPC. + + Gets the details of a Membership. + + Returns: + Callable[[~.GetMembershipRequest], + Awaitable[~.Membership]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_membership" not in self._stubs: + self._stubs["get_membership"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/GetMembership", + request_serializer=service.GetMembershipRequest.serialize, + response_deserializer=membership.Membership.deserialize, + ) + return self._stubs["get_membership"] + + @property + def get_feature( + self, + ) -> Callable[[service.GetFeatureRequest], Awaitable[feature.Feature]]: + r"""Return a callable for the get feature method over gRPC. + + Gets details of a single Feature. + + Returns: + Callable[[~.GetFeatureRequest], + Awaitable[~.Feature]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_feature" not in self._stubs: + self._stubs["get_feature"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/GetFeature", + request_serializer=service.GetFeatureRequest.serialize, + response_deserializer=feature.Feature.deserialize, + ) + return self._stubs["get_feature"] + + @property + def create_membership( + self, + ) -> Callable[ + [service.CreateMembershipRequest], Awaitable[operations_pb2.Operation] + ]: + r"""Return a callable for the create membership method over gRPC. + + Creates a new Membership. + + **This is currently only supported for GKE clusters on Google + Cloud**. To register other clusters, follow the instructions at + https://cloud.google.com/anthos/multicluster-management/connect/registering-a-cluster. + + Returns: + Callable[[~.CreateMembershipRequest], + Awaitable[~.Operation]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_membership" not in self._stubs: + self._stubs["create_membership"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/CreateMembership", + request_serializer=service.CreateMembershipRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["create_membership"] + + @property + def create_feature( + self, + ) -> Callable[[service.CreateFeatureRequest], Awaitable[operations_pb2.Operation]]: + r"""Return a callable for the create feature method over gRPC. + + Adds a new Feature. + + Returns: + Callable[[~.CreateFeatureRequest], + Awaitable[~.Operation]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "create_feature" not in self._stubs: + self._stubs["create_feature"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/CreateFeature", + request_serializer=service.CreateFeatureRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["create_feature"] + + @property + def delete_membership( + self, + ) -> Callable[ + [service.DeleteMembershipRequest], Awaitable[operations_pb2.Operation] + ]: + r"""Return a callable for the delete membership method over gRPC. + + Removes a Membership. + + **This is currently only supported for GKE clusters on Google + Cloud**. To unregister other clusters, follow the instructions + at + https://cloud.google.com/anthos/multicluster-management/connect/unregistering-a-cluster. + + Returns: + Callable[[~.DeleteMembershipRequest], + Awaitable[~.Operation]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "delete_membership" not in self._stubs: + self._stubs["delete_membership"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/DeleteMembership", + request_serializer=service.DeleteMembershipRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["delete_membership"] + + @property + def delete_feature( + self, + ) -> Callable[[service.DeleteFeatureRequest], Awaitable[operations_pb2.Operation]]: + r"""Return a callable for the delete feature method over gRPC. + + Removes a Feature. + + Returns: + Callable[[~.DeleteFeatureRequest], + Awaitable[~.Operation]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "delete_feature" not in self._stubs: + self._stubs["delete_feature"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/DeleteFeature", + request_serializer=service.DeleteFeatureRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["delete_feature"] + + @property + def update_membership( + self, + ) -> Callable[ + [service.UpdateMembershipRequest], Awaitable[operations_pb2.Operation] + ]: + r"""Return a callable for the update membership method over gRPC. + + Updates an existing Membership. + + Returns: + Callable[[~.UpdateMembershipRequest], + Awaitable[~.Operation]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_membership" not in self._stubs: + self._stubs["update_membership"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/UpdateMembership", + request_serializer=service.UpdateMembershipRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["update_membership"] + + @property + def update_feature( + self, + ) -> Callable[[service.UpdateFeatureRequest], Awaitable[operations_pb2.Operation]]: + r"""Return a callable for the update feature method over gRPC. + + Updates an existing Feature. + + Returns: + Callable[[~.UpdateFeatureRequest], + Awaitable[~.Operation]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_feature" not in self._stubs: + self._stubs["update_feature"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/UpdateFeature", + request_serializer=service.UpdateFeatureRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["update_feature"] + + @property + def generate_connect_manifest( + self, + ) -> Callable[ + [service.GenerateConnectManifestRequest], + Awaitable[service.GenerateConnectManifestResponse], + ]: + r"""Return a callable for the generate connect manifest method over gRPC. + + Generates the manifest for deployment of the GKE connect agent. + + **This method is used internally by Google-provided libraries.** + Most clients should not need to call this method directly. + + Returns: + Callable[[~.GenerateConnectManifestRequest], + Awaitable[~.GenerateConnectManifestResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "generate_connect_manifest" not in self._stubs: + self._stubs["generate_connect_manifest"] = self.grpc_channel.unary_unary( + "/google.cloud.gkehub_v1.GkeHub/GenerateConnectManifest", + request_serializer=service.GenerateConnectManifestRequest.serialize, + response_deserializer=service.GenerateConnectManifestResponse.deserialize, + ) + return self._stubs["generate_connect_manifest"] + + +__all__ = ("GkeHubGrpcAsyncIOTransport",) diff --git a/google/cloud/gkehub_v1/types/__init__.py b/google/cloud/gkehub_v1/types/__init__.py new file mode 100644 index 0000000..daf8db4 --- /dev/null +++ b/google/cloud/gkehub_v1/types/__init__.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from .feature import ( + CommonFeatureSpec, + CommonFeatureState, + Feature, + FeatureResourceState, + FeatureState, + MembershipFeatureSpec, + MembershipFeatureState, +) +from .membership import ( + Authority, + GkeCluster, + KubernetesMetadata, + Membership, + MembershipEndpoint, + MembershipState, +) +from .service import ( + ConnectAgentResource, + CreateFeatureRequest, + CreateMembershipRequest, + DeleteFeatureRequest, + DeleteMembershipRequest, + GenerateConnectManifestRequest, + GenerateConnectManifestResponse, + GetFeatureRequest, + GetMembershipRequest, + ListFeaturesRequest, + ListFeaturesResponse, + ListMembershipsRequest, + ListMembershipsResponse, + OperationMetadata, + TypeMeta, + UpdateFeatureRequest, + UpdateMembershipRequest, +) + +__all__ = ( + "CommonFeatureSpec", + "CommonFeatureState", + "Feature", + "FeatureResourceState", + "FeatureState", + "MembershipFeatureSpec", + "MembershipFeatureState", + "Authority", + "GkeCluster", + "KubernetesMetadata", + "Membership", + "MembershipEndpoint", + "MembershipState", + "ConnectAgentResource", + "CreateFeatureRequest", + "CreateMembershipRequest", + "DeleteFeatureRequest", + "DeleteMembershipRequest", + "GenerateConnectManifestRequest", + "GenerateConnectManifestResponse", + "GetFeatureRequest", + "GetMembershipRequest", + "ListFeaturesRequest", + "ListFeaturesResponse", + "ListMembershipsRequest", + "ListMembershipsResponse", + "OperationMetadata", + "TypeMeta", + "UpdateFeatureRequest", + "UpdateMembershipRequest", +) diff --git a/google/cloud/gkehub_v1/types/feature.py b/google/cloud/gkehub_v1/types/feature.py new file mode 100644 index 0000000..0f91981 --- /dev/null +++ b/google/cloud/gkehub_v1/types/feature.py @@ -0,0 +1,241 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import proto # type: ignore + +import google.cloud.gkehub.configmanagement_v1 as configmanagement_pb2 # type: ignore +import google.cloud.gkehub.multiclusteringress_v1 as multiclusteringress_pb2 # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.cloud.gkehub_v1", + manifest={ + "Feature", + "FeatureResourceState", + "FeatureState", + "CommonFeatureSpec", + "CommonFeatureState", + "MembershipFeatureSpec", + "MembershipFeatureState", + }, +) + + +class Feature(proto.Message): + r"""Feature represents the settings and status of any Hub + Feature. + + Attributes: + name (str): + Output only. The full, unique name of this Feature resource + in the format ``projects/*/locations/*/features/*``. + labels (Sequence[google.cloud.gkehub_v1.types.Feature.LabelsEntry]): + GCP labels for this Feature. + resource_state (google.cloud.gkehub_v1.types.FeatureResourceState): + Output only. State of the Feature resource + itself. + spec (google.cloud.gkehub_v1.types.CommonFeatureSpec): + Optional. Hub-wide Feature configuration. If + this Feature does not support any Hub-wide + configuration, this field may be unused. + membership_specs (Sequence[google.cloud.gkehub_v1.types.Feature.MembershipSpecsEntry]): + Optional. Membership-specific configuration + for this Feature. If this Feature does not + support any per-Membership configuration, this + field may be unused. + The keys indicate which Membership the + configuration is for, in the form: + `projects/{p}/locations/{l}/memberships/{m}` + Where {p} is the project, {l} is a valid + location and {m} is a valid Membership in this + project at that location. {p} WILL match the + Feature's project. + + {p} will always be returned as the project + number, but the project ID is also accepted + during input. If the same Membership is + specified in the map twice (using the project ID + form, and the project number form), exactly ONE + of the entries will be saved, with no guarantees + as to which. For this reason, it is recommended + the same format be used for all entries when + mutating a Feature. + state (google.cloud.gkehub_v1.types.CommonFeatureState): + Output only. The Hub-wide Feature state. + membership_states (Sequence[google.cloud.gkehub_v1.types.Feature.MembershipStatesEntry]): + Output only. Membership-specific Feature + status. If this Feature does report any per- + Membership status, this field may be unused. + The keys indicate which Membership the state is + for, in the form: + `projects/{p}/locations/{l}/memberships/{m}` + Where {p} is the project number, {l} is a valid + location and {m} is a valid Membership in this + project at that location. {p} MUST match the + Feature's project number. + create_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. When the Feature resource was + created. + update_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. When the Feature resource was + last updated. + delete_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. When the Feature resource was + deleted. + """ + + name = proto.Field(proto.STRING, number=1,) + labels = proto.MapField(proto.STRING, proto.STRING, number=2,) + resource_state = proto.Field( + proto.MESSAGE, number=3, message="FeatureResourceState", + ) + spec = proto.Field(proto.MESSAGE, number=4, message="CommonFeatureSpec",) + membership_specs = proto.MapField( + proto.STRING, proto.MESSAGE, number=5, message="MembershipFeatureSpec", + ) + state = proto.Field(proto.MESSAGE, number=6, message="CommonFeatureState",) + membership_states = proto.MapField( + proto.STRING, proto.MESSAGE, number=7, message="MembershipFeatureState", + ) + create_time = proto.Field(proto.MESSAGE, number=8, message=timestamp_pb2.Timestamp,) + update_time = proto.Field(proto.MESSAGE, number=9, message=timestamp_pb2.Timestamp,) + delete_time = proto.Field( + proto.MESSAGE, number=10, message=timestamp_pb2.Timestamp, + ) + + +class FeatureResourceState(proto.Message): + r"""FeatureResourceState describes the state of a Feature *resource* in + the GkeHub API. See ``FeatureState`` for the "running state" of the + Feature in the Hub and across Memberships. + + Attributes: + state (google.cloud.gkehub_v1.types.FeatureResourceState.State): + The current state of the Feature resource in + the Hub API. + """ + + class State(proto.Enum): + r"""State describes the lifecycle status of a Feature.""" + STATE_UNSPECIFIED = 0 + ENABLING = 1 + ACTIVE = 2 + DISABLING = 3 + UPDATING = 4 + SERVICE_UPDATING = 5 + + state = proto.Field(proto.ENUM, number=1, enum=State,) + + +class FeatureState(proto.Message): + r"""FeatureState describes the high-level state of a Feature. It + may be used to describe a Feature's state at the environ-level, + or per-membershop, depending on the context. + + Attributes: + code (google.cloud.gkehub_v1.types.FeatureState.Code): + The high-level, machine-readable status of + this Feature. + description (str): + A human-readable description of the current + status. + update_time (google.protobuf.timestamp_pb2.Timestamp): + The time this status and any related Feature- + pecific details were updated. + """ + + class Code(proto.Enum): + r"""Code represents a machine-readable, high-level status of the + Feature. + """ + CODE_UNSPECIFIED = 0 + OK = 1 + WARNING = 2 + ERROR = 3 + + code = proto.Field(proto.ENUM, number=1, enum=Code,) + description = proto.Field(proto.STRING, number=2,) + update_time = proto.Field(proto.MESSAGE, number=3, message=timestamp_pb2.Timestamp,) + + +class CommonFeatureSpec(proto.Message): + r"""CommonFeatureSpec contains Hub-wide configuration informatio. + + Attributes: + multiclusteringress (google.cloud.gkehub.multiclusteringress_v1.multiclusteringress_pb2.FeatureSpec): + Multicluster Ingress-specific spec. + """ + + multiclusteringress = proto.Field( + proto.MESSAGE, + number=102, + oneof="feature_spec", + message=multiclusteringress_pb2.FeatureSpec, + ) + + +class CommonFeatureState(proto.Message): + r"""CommonFeatureState contains Hub-wide Feature status + information. + + Attributes: + state (google.cloud.gkehub_v1.types.FeatureState): + Output only. The "running state" of the + Feature in this Hub. + """ + + state = proto.Field(proto.MESSAGE, number=1, message="FeatureState",) + + +class MembershipFeatureSpec(proto.Message): + r"""MembershipFeatureSpec contains configuration information for + a single Membership. + + Attributes: + configmanagement (google.cloud.gkehub.configmanagement_v1.configmanagement_pb2.MembershipSpec): + Config Management-specific spec. + """ + + configmanagement = proto.Field( + proto.MESSAGE, + number=106, + oneof="feature_spec", + message=configmanagement_pb2.MembershipSpec, + ) + + +class MembershipFeatureState(proto.Message): + r"""MembershipFeatureState contains Feature status information + for a single Membership. + + Attributes: + configmanagement (google.cloud.gkehub.configmanagement_v1.configmanagement_pb2.MembershipState): + Config Management-specific state. + state (google.cloud.gkehub_v1.types.FeatureState): + The high-level state of this Feature for a + single membership. + """ + + configmanagement = proto.Field( + proto.MESSAGE, + number=106, + oneof="feature_state", + message=configmanagement_pb2.MembershipState, + ) + state = proto.Field(proto.MESSAGE, number=1, message="FeatureState",) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/gkehub_v1/types/membership.py b/google/cloud/gkehub_v1/types/membership.py new file mode 100644 index 0000000..67c3d98 --- /dev/null +++ b/google/cloud/gkehub_v1/types/membership.py @@ -0,0 +1,270 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import proto # type: ignore + +from google.protobuf import timestamp_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.cloud.gkehub_v1", + manifest={ + "Membership", + "MembershipEndpoint", + "GkeCluster", + "KubernetesMetadata", + "MembershipState", + "Authority", + }, +) + + +class Membership(proto.Message): + r"""Membership contains information about a member cluster. + + Attributes: + endpoint (google.cloud.gkehub_v1.types.MembershipEndpoint): + Optional. Endpoint information to reach this + member. + name (str): + Output only. The full, unique name of this Membership + resource in the format + ``projects/*/locations/*/memberships/{membership_id}``, set + during creation. + + ``membership_id`` must be a valid RFC 1123 compliant DNS + label: + + 1. At most 63 characters in length + 2. It must consist of lower case alphanumeric characters or + ``-`` + 3. It must start and end with an alphanumeric character + + Which can be expressed as the regex: + ``[a-z0-9]([-a-z0-9]*[a-z0-9])?``, with a maximum length of + 63 characters. + labels (Sequence[google.cloud.gkehub_v1.types.Membership.LabelsEntry]): + Optional. GCP labels for this membership. + description (str): + Output only. Description of this membership, limited to 63 + characters. Must match the regex: + ``[a-zA-Z0-9][a-zA-Z0-9_\-\.\ ]*`` + + This field is present for legacy purposes. + state (google.cloud.gkehub_v1.types.MembershipState): + Output only. State of the Membership + resource. + create_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. When the Membership was created. + update_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. When the Membership was last + updated. + delete_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. When the Membership was deleted. + external_id (str): + Optional. An externally-generated and managed ID for this + Membership. This ID may be modified after creation, but this + is not recommended. + + The ID must match the regex: + ``[a-zA-Z0-9][a-zA-Z0-9_\-\.]*`` + + If this Membership represents a Kubernetes cluster, this + value should be set to the UID of the ``kube-system`` + namespace object. + last_connection_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. For clusters using Connect, the + timestamp of the most recent connection + established with Google Cloud. This time is + updated every several minutes, not continuously. + For clusters that do not use GKE Connect, or + that have never connected successfully, this + field will be unset. + unique_id (str): + Output only. Google-generated UUID for this resource. This + is unique across all Membership resources. If a Membership + resource is deleted and another resource with the same name + is created, it gets a different unique_id. + authority (google.cloud.gkehub_v1.types.Authority): + Optional. How to identify workloads from this + Membership. See the documentation on Workload + Identity for more details: + https://cloud.google.com/kubernetes- + engine/docs/how-to/workload-identity + """ + + endpoint = proto.Field( + proto.MESSAGE, number=4, oneof="type", message="MembershipEndpoint", + ) + name = proto.Field(proto.STRING, number=1,) + labels = proto.MapField(proto.STRING, proto.STRING, number=2,) + description = proto.Field(proto.STRING, number=3,) + state = proto.Field(proto.MESSAGE, number=5, message="MembershipState",) + create_time = proto.Field(proto.MESSAGE, number=6, message=timestamp_pb2.Timestamp,) + update_time = proto.Field(proto.MESSAGE, number=7, message=timestamp_pb2.Timestamp,) + delete_time = proto.Field(proto.MESSAGE, number=8, message=timestamp_pb2.Timestamp,) + external_id = proto.Field(proto.STRING, number=9,) + last_connection_time = proto.Field( + proto.MESSAGE, number=10, message=timestamp_pb2.Timestamp, + ) + unique_id = proto.Field(proto.STRING, number=11,) + authority = proto.Field(proto.MESSAGE, number=12, message="Authority",) + + +class MembershipEndpoint(proto.Message): + r"""MembershipEndpoint contains information needed to contact a + Kubernetes API, endpoint and any additional Kubernetes metadata. + + Attributes: + gke_cluster (google.cloud.gkehub_v1.types.GkeCluster): + Optional. GKE-specific information. Only + present if this Membership is a GKE cluster. + kubernetes_metadata (google.cloud.gkehub_v1.types.KubernetesMetadata): + Output only. Useful Kubernetes-specific + metadata. + """ + + gke_cluster = proto.Field(proto.MESSAGE, number=1, message="GkeCluster",) + kubernetes_metadata = proto.Field( + proto.MESSAGE, number=2, message="KubernetesMetadata", + ) + + +class GkeCluster(proto.Message): + r"""GkeCluster contains information specific to GKE clusters. + + Attributes: + resource_link (str): + Immutable. Self-link of the GCP resource for + the GKE cluster. For example: + //container.googleapis.com/projects/my- + project/locations/us-west1-a/clusters/my-cluster + Zonal clusters are also supported. + """ + + resource_link = proto.Field(proto.STRING, number=1,) + + +class KubernetesMetadata(proto.Message): + r"""KubernetesMetadata provides informational metadata for + Memberships representing Kubernetes clusters. + + Attributes: + kubernetes_api_server_version (str): + Output only. Kubernetes API server version string as + reported by ``/version``. + node_provider_id (str): + Output only. Node providerID as reported by the first node + in the list of nodes on the Kubernetes endpoint. On + Kubernetes platforms that support zero-node clusters (like + GKE-on-GCP), the node_count will be zero and the + node_provider_id will be empty. + node_count (int): + Output only. Node count as reported by + Kubernetes nodes resources. + vcpu_count (int): + Output only. vCPU count as reported by + Kubernetes nodes resources. + memory_mb (int): + Output only. The total memory capacity as + reported by the sum of all Kubernetes nodes + resources, defined in MB. + update_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. The time at which these details were last + updated. This update_time is different from the + Membership-level update_time since EndpointDetails are + updated internally for API consumers. + """ + + kubernetes_api_server_version = proto.Field(proto.STRING, number=1,) + node_provider_id = proto.Field(proto.STRING, number=2,) + node_count = proto.Field(proto.INT32, number=3,) + vcpu_count = proto.Field(proto.INT32, number=4,) + memory_mb = proto.Field(proto.INT32, number=5,) + update_time = proto.Field( + proto.MESSAGE, number=100, message=timestamp_pb2.Timestamp, + ) + + +class MembershipState(proto.Message): + r"""MembershipState describes the state of a Membership resource. + + Attributes: + code (google.cloud.gkehub_v1.types.MembershipState.Code): + Output only. The current state of the + Membership resource. + """ + + class Code(proto.Enum): + r"""Code describes the state of a Membership resource.""" + CODE_UNSPECIFIED = 0 + CREATING = 1 + READY = 2 + DELETING = 3 + UPDATING = 4 + SERVICE_UPDATING = 5 + + code = proto.Field(proto.ENUM, number=1, enum=Code,) + + +class Authority(proto.Message): + r"""Authority encodes how Google will recognize identities from + this Membership. See the workload identity documentation for + more details: https://cloud.google.com/kubernetes- + engine/docs/how-to/workload-identity + + Attributes: + issuer (str): + Optional. A JSON Web Token (JWT) issuer URI. ``issuer`` must + start with ``https://`` and be a valid URL with length <2000 + characters. + + If set, then Google will allow valid OIDC tokens from this + issuer to authenticate within the workload_identity_pool. + OIDC discovery will be performed on this URI to validate + tokens from the issuer. + + Clearing ``issuer`` disables Workload Identity. ``issuer`` + cannot be directly modified; it must be cleared (and + Workload Identity disabled) before using a new issuer (and + re-enabling Workload Identity). + workload_identity_pool (str): + Output only. The name of the workload identity pool in which + ``issuer`` will be recognized. + + There is a single Workload Identity Pool per Hub that is + shared between all Memberships that belong to that Hub. For + a Hub hosted in {PROJECT_ID}, the workload pool format is + ``{PROJECT_ID}.hub.id.goog``, although this is subject to + change in newer versions of this API. + identity_provider (str): + Output only. An identity provider that reflects the + ``issuer`` in the workload identity pool. + oidc_jwks (bytes): + Optional. OIDC verification keys for this Membership in JWKS + format (RFC 7517). + + When this field is set, OIDC discovery will NOT be performed + on ``issuer``, and instead OIDC tokens will be validated + using this field. + """ + + issuer = proto.Field(proto.STRING, number=1,) + workload_identity_pool = proto.Field(proto.STRING, number=2,) + identity_provider = proto.Field(proto.STRING, number=3,) + oidc_jwks = proto.Field(proto.BYTES, number=4,) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/gkehub_v1/types/service.py b/google/cloud/gkehub_v1/types/service.py new file mode 100644 index 0000000..7c12ebd --- /dev/null +++ b/google/cloud/gkehub_v1/types/service.py @@ -0,0 +1,597 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import proto # type: ignore + +from google.cloud.gkehub_v1.types import feature +from google.cloud.gkehub_v1.types import membership +from google.protobuf import field_mask_pb2 # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore + + +__protobuf__ = proto.module( + package="google.cloud.gkehub_v1", + manifest={ + "ListMembershipsRequest", + "ListMembershipsResponse", + "GetMembershipRequest", + "CreateMembershipRequest", + "DeleteMembershipRequest", + "UpdateMembershipRequest", + "GenerateConnectManifestRequest", + "GenerateConnectManifestResponse", + "ConnectAgentResource", + "TypeMeta", + "ListFeaturesRequest", + "ListFeaturesResponse", + "GetFeatureRequest", + "CreateFeatureRequest", + "DeleteFeatureRequest", + "UpdateFeatureRequest", + "OperationMetadata", + }, +) + + +class ListMembershipsRequest(proto.Message): + r"""Request message for ``GkeHub.ListMemberships`` method. + + Attributes: + parent (str): + Required. The parent (project and location) where the + Memberships will be listed. Specified in the format + ``projects/*/locations/*``. + page_size (int): + Optional. When requesting a 'page' of resources, + ``page_size`` specifies number of resources to return. If + unspecified or set to 0, all resources will be returned. + page_token (str): + Optional. Token returned by previous call to + ``ListMemberships`` which specifies the position in the list + from where to continue listing the resources. + filter (str): + Optional. Lists Memberships that match the filter + expression, following the syntax outlined in + https://google.aip.dev/160. + + Examples: + + - Name is ``bar`` in project ``foo-proj`` and location + ``global``: + + name = + "projects/foo-proj/locations/global/membership/bar" + + - Memberships that have a label called ``foo``: + + labels.foo:\* + + - Memberships that have a label called ``foo`` whose value + is ``bar``: + + labels.foo = bar + + - Memberships in the CREATING state: + + state = CREATING + order_by (str): + Optional. One or more fields to compare and + use to sort the output. See + https://google.aip.dev/132#ordering. + """ + + parent = proto.Field(proto.STRING, number=1,) + page_size = proto.Field(proto.INT32, number=2,) + page_token = proto.Field(proto.STRING, number=3,) + filter = proto.Field(proto.STRING, number=4,) + order_by = proto.Field(proto.STRING, number=5,) + + +class ListMembershipsResponse(proto.Message): + r"""Response message for the ``GkeHub.ListMemberships`` method. + + Attributes: + resources (Sequence[google.cloud.gkehub_v1.types.Membership]): + The list of matching Memberships. + next_page_token (str): + A token to request the next page of resources from the + ``ListMemberships`` method. The value of an empty string + means that there are no more resources to return. + unreachable (Sequence[str]): + List of locations that could not be reached + while fetching this list. + """ + + @property + def raw_page(self): + return self + + resources = proto.RepeatedField( + proto.MESSAGE, number=1, message=membership.Membership, + ) + next_page_token = proto.Field(proto.STRING, number=2,) + unreachable = proto.RepeatedField(proto.STRING, number=3,) + + +class GetMembershipRequest(proto.Message): + r"""Request message for ``GkeHub.GetMembership`` method. + + Attributes: + name (str): + Required. The Membership resource name in the format + ``projects/*/locations/*/memberships/*``. + """ + + name = proto.Field(proto.STRING, number=1,) + + +class CreateMembershipRequest(proto.Message): + r"""Request message for the ``GkeHub.CreateMembership`` method. + + Attributes: + parent (str): + Required. The parent (project and location) where the + Memberships will be created. Specified in the format + ``projects/*/locations/*``. + membership_id (str): + Required. Client chosen ID for the membership. + ``membership_id`` must be a valid RFC 1123 compliant DNS + label: + + 1. At most 63 characters in length + 2. It must consist of lower case alphanumeric characters or + ``-`` + 3. It must start and end with an alphanumeric character + + Which can be expressed as the regex: + ``[a-z0-9]([-a-z0-9]*[a-z0-9])?``, with a maximum length of + 63 characters. + resource (google.cloud.gkehub_v1.types.Membership): + Required. The membership to create. + request_id (str): + Optional. A request ID to identify requests. + Specify a unique request ID so that if you must + retry your request, the server will know to + ignore the request if it has already been + completed. The server will guarantee that for at + least 60 minutes after the first request. + For example, consider a situation where you make + an initial request and the request times out. If + you make the request again with the same request + ID, the server can check if original operation + with the same request ID was received, and if + so, will ignore the second request. This + prevents clients from accidentally creating + duplicate commitments. + The request ID must be a valid UUID with the + exception that zero UUID is not supported + (00000000-0000-0000-0000-000000000000). + """ + + parent = proto.Field(proto.STRING, number=1,) + membership_id = proto.Field(proto.STRING, number=2,) + resource = proto.Field(proto.MESSAGE, number=3, message=membership.Membership,) + request_id = proto.Field(proto.STRING, number=4,) + + +class DeleteMembershipRequest(proto.Message): + r"""Request message for ``GkeHub.DeleteMembership`` method. + + Attributes: + name (str): + Required. The Membership resource name in the format + ``projects/*/locations/*/memberships/*``. + request_id (str): + Optional. A request ID to identify requests. + Specify a unique request ID so that if you must + retry your request, the server will know to + ignore the request if it has already been + completed. The server will guarantee that for at + least 60 minutes after the first request. + For example, consider a situation where you make + an initial request and the request times out. If + you make the request again with the same request + ID, the server can check if original operation + with the same request ID was received, and if + so, will ignore the second request. This + prevents clients from accidentally creating + duplicate commitments. + The request ID must be a valid UUID with the + exception that zero UUID is not supported + (00000000-0000-0000-0000-000000000000). + """ + + name = proto.Field(proto.STRING, number=1,) + request_id = proto.Field(proto.STRING, number=2,) + + +class UpdateMembershipRequest(proto.Message): + r"""Request message for ``GkeHub.UpdateMembership`` method. + + Attributes: + name (str): + Required. The Membership resource name in the format + ``projects/*/locations/*/memberships/*``. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Required. Mask of fields to update. + resource (google.cloud.gkehub_v1.types.Membership): + Required. Only fields specified in update_mask are updated. + If you specify a field in the update_mask but don't specify + its value here that field will be deleted. If you are + updating a map field, set the value of a key to null or + empty string to delete the key from the map. It's not + possible to update a key's value to the empty string. If you + specify the update_mask to be a special path "*", fully + replaces all user-modifiable fields to match ``resource``. + request_id (str): + Optional. A request ID to identify requests. + Specify a unique request ID so that if you must + retry your request, the server will know to + ignore the request if it has already been + completed. The server will guarantee that for at + least 60 minutes after the first request. + For example, consider a situation where you make + an initial request and the request times out. If + you make the request again with the same request + ID, the server can check if original operation + with the same request ID was received, and if + so, will ignore the second request. This + prevents clients from accidentally creating + duplicate commitments. + The request ID must be a valid UUID with the + exception that zero UUID is not supported + (00000000-0000-0000-0000-000000000000). + """ + + name = proto.Field(proto.STRING, number=1,) + update_mask = proto.Field( + proto.MESSAGE, number=2, message=field_mask_pb2.FieldMask, + ) + resource = proto.Field(proto.MESSAGE, number=3, message=membership.Membership,) + request_id = proto.Field(proto.STRING, number=4,) + + +class GenerateConnectManifestRequest(proto.Message): + r"""Request message for ``GkeHub.GenerateConnectManifest`` method. . + + Attributes: + name (str): + Required. The Membership resource name the Agent will + associate with, in the format + ``projects/*/locations/*/memberships/*``. + namespace (str): + Optional. Namespace for GKE Connect agent resources. + Defaults to ``gke-connect``. + + The Connect Agent is authorized automatically when run in + the default namespace. Otherwise, explicit authorization + must be granted with an additional IAM binding. + proxy (bytes): + Optional. URI of a proxy if connectivity from the agent to + gkeconnect.googleapis.com requires the use of a proxy. + Format must be in the form ``http(s)://{proxy_address}``, + depending on the HTTP/HTTPS protocol supported by the proxy. + This will direct the connect agent's outbound traffic + through a HTTP(S) proxy. + version (str): + Optional. The Connect agent version to use. + Defaults to the most current version. + is_upgrade (bool): + Optional. If true, generate the resources for + upgrade only. Some resources generated only for + installation (e.g. secrets) will be excluded. + registry (str): + Optional. The registry to fetch the connect + agent image from. Defaults to gcr.io/gkeconnect. + image_pull_secret_content (bytes): + Optional. The image pull secret content for + the registry, if not public. + """ + + name = proto.Field(proto.STRING, number=1,) + namespace = proto.Field(proto.STRING, number=2,) + proxy = proto.Field(proto.BYTES, number=3,) + version = proto.Field(proto.STRING, number=4,) + is_upgrade = proto.Field(proto.BOOL, number=5,) + registry = proto.Field(proto.STRING, number=6,) + image_pull_secret_content = proto.Field(proto.BYTES, number=7,) + + +class GenerateConnectManifestResponse(proto.Message): + r"""GenerateConnectManifestResponse contains manifest information + for installing/upgrading a Connect agent. + + Attributes: + manifest (Sequence[google.cloud.gkehub_v1.types.ConnectAgentResource]): + The ordered list of Kubernetes resources that + need to be applied to the cluster for GKE + Connect agent installation/upgrade. + """ + + manifest = proto.RepeatedField( + proto.MESSAGE, number=1, message="ConnectAgentResource", + ) + + +class ConnectAgentResource(proto.Message): + r"""ConnectAgentResource represents a Kubernetes resource + manifest for Connect Agent deployment. + + Attributes: + type_ (google.cloud.gkehub_v1.types.TypeMeta): + Kubernetes type of the resource. + manifest (str): + YAML manifest of the resource. + """ + + type_ = proto.Field(proto.MESSAGE, number=1, message="TypeMeta",) + manifest = proto.Field(proto.STRING, number=2,) + + +class TypeMeta(proto.Message): + r"""TypeMeta is the type information needed for content + unmarshalling of Kubernetes resources in the manifest. + + Attributes: + kind (str): + Kind of the resource (e.g. Deployment). + api_version (str): + APIVersion of the resource (e.g. v1). + """ + + kind = proto.Field(proto.STRING, number=1,) + api_version = proto.Field(proto.STRING, number=2,) + + +class ListFeaturesRequest(proto.Message): + r"""Request message for ``GkeHub.ListFeatures`` method. + + Attributes: + parent (str): + The parent (project and location) where the Features will be + listed. Specified in the format ``projects/*/locations/*``. + page_size (int): + When requesting a 'page' of resources, ``page_size`` + specifies number of resources to return. If unspecified or + set to 0, all resources will be returned. + page_token (str): + Token returned by previous call to ``ListFeatures`` which + specifies the position in the list from where to continue + listing the resources. + filter (str): + Lists Features that match the filter expression, following + the syntax outlined in https://google.aip.dev/160. + + Examples: + + - Feature with the name "servicemesh" in project + "foo-proj": + + name = + "projects/foo-proj/locations/global/features/servicemesh" + + - Features that have a label called ``foo``: + + labels.foo:\* + + - Features that have a label called ``foo`` whose value is + ``bar``: + + labels.foo = bar + order_by (str): + One or more fields to compare and use to sort + the output. See + https://google.aip.dev/132#ordering. + """ + + parent = proto.Field(proto.STRING, number=1,) + page_size = proto.Field(proto.INT32, number=2,) + page_token = proto.Field(proto.STRING, number=3,) + filter = proto.Field(proto.STRING, number=4,) + order_by = proto.Field(proto.STRING, number=5,) + + +class ListFeaturesResponse(proto.Message): + r"""Response message for the ``GkeHub.ListFeatures`` method. + + Attributes: + resources (Sequence[google.cloud.gkehub_v1.types.Feature]): + The list of matching Features + next_page_token (str): + A token to request the next page of resources from the + ``ListFeatures`` method. The value of an empty string means + that there are no more resources to return. + """ + + @property + def raw_page(self): + return self + + resources = proto.RepeatedField(proto.MESSAGE, number=1, message=feature.Feature,) + next_page_token = proto.Field(proto.STRING, number=2,) + + +class GetFeatureRequest(proto.Message): + r"""Request message for ``GkeHub.GetFeature`` method. + + Attributes: + name (str): + The Feature resource name in the format + ``projects/*/locations/*/features/*`` + """ + + name = proto.Field(proto.STRING, number=1,) + + +class CreateFeatureRequest(proto.Message): + r"""Request message for the ``GkeHub.CreateFeature`` method. + + Attributes: + parent (str): + The parent (project and location) where the Feature will be + created. Specified in the format ``projects/*/locations/*``. + feature_id (str): + The ID of the feature to create. + resource (google.cloud.gkehub_v1.types.Feature): + The Feature resource to create. + request_id (str): + Optional. A request ID to identify requests. + Specify a unique request ID so that if you must + retry your request, the server will know to + ignore the request if it has already been + completed. The server will guarantee that for at + least 60 minutes after the first request. + For example, consider a situation where you make + an initial request and the request times out. If + you make the request again with the same request + ID, the server can check if original operation + with the same request ID was received, and if + so, will ignore the second request. This + prevents clients from accidentally creating + duplicate commitments. + The request ID must be a valid UUID with the + exception that zero UUID is not supported + (00000000-0000-0000-0000-000000000000). + """ + + parent = proto.Field(proto.STRING, number=1,) + feature_id = proto.Field(proto.STRING, number=2,) + resource = proto.Field(proto.MESSAGE, number=3, message=feature.Feature,) + request_id = proto.Field(proto.STRING, number=4,) + + +class DeleteFeatureRequest(proto.Message): + r"""Request message for ``GkeHub.DeleteFeature`` method. + + Attributes: + name (str): + The Feature resource name in the format + ``projects/*/locations/*/features/*``. + force (bool): + If set to true, the delete will ignore any outstanding + resources for this Feature (that is, + ``FeatureState.has_resources`` is set to true). These + resources will NOT be cleaned up or modified in any way. + request_id (str): + Optional. A request ID to identify requests. + Specify a unique request ID so that if you must + retry your request, the server will know to + ignore the request if it has already been + completed. The server will guarantee that for at + least 60 minutes after the first request. + For example, consider a situation where you make + an initial request and the request times out. If + you make the request again with the same request + ID, the server can check if original operation + with the same request ID was received, and if + so, will ignore the second request. This + prevents clients from accidentally creating + duplicate commitments. + The request ID must be a valid UUID with the + exception that zero UUID is not supported + (00000000-0000-0000-0000-000000000000). + """ + + name = proto.Field(proto.STRING, number=1,) + force = proto.Field(proto.BOOL, number=2,) + request_id = proto.Field(proto.STRING, number=3,) + + +class UpdateFeatureRequest(proto.Message): + r"""Request message for ``GkeHub.UpdateFeature`` method. + + Attributes: + name (str): + The Feature resource name in the format + ``projects/*/locations/*/features/*``. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Mask of fields to update. + resource (google.cloud.gkehub_v1.types.Feature): + Only fields specified in update_mask are updated. If you + specify a field in the update_mask but don't specify its + value here that field will be deleted. If you are updating a + map field, set the value of a key to null or empty string to + delete the key from the map. It's not possible to update a + key's value to the empty string. If you specify the + update_mask to be a special path "*", fully replaces all + user-modifiable fields to match ``resource``. + request_id (str): + Optional. A request ID to identify requests. + Specify a unique request ID so that if you must + retry your request, the server will know to + ignore the request if it has already been + completed. The server will guarantee that for at + least 60 minutes after the first request. + For example, consider a situation where you make + an initial request and the request times out. If + you make the request again with the same request + ID, the server can check if original operation + with the same request ID was received, and if + so, will ignore the second request. This + prevents clients from accidentally creating + duplicate commitments. + The request ID must be a valid UUID with the + exception that zero UUID is not supported + (00000000-0000-0000-0000-000000000000). + """ + + name = proto.Field(proto.STRING, number=1,) + update_mask = proto.Field( + proto.MESSAGE, number=2, message=field_mask_pb2.FieldMask, + ) + resource = proto.Field(proto.MESSAGE, number=3, message=feature.Feature,) + request_id = proto.Field(proto.STRING, number=4,) + + +class OperationMetadata(proto.Message): + r"""Represents the metadata of the long-running operation. + + Attributes: + create_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. The time the operation was + created. + end_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. The time the operation finished + running. + target (str): + Output only. Server-defined resource path for + the target of the operation. + verb (str): + Output only. Name of the verb executed by the + operation. + status_detail (str): + Output only. Human-readable status of the + operation, if any. + cancel_requested (bool): + Output only. Identifies whether the user has requested + cancellation of the operation. Operations that have + successfully been cancelled have [Operation.error][] value + with a [google.rpc.Status.code][google.rpc.Status.code] of + 1, corresponding to ``Code.CANCELLED``. + api_version (str): + Output only. API version used to start the + operation. + """ + + create_time = proto.Field(proto.MESSAGE, number=1, message=timestamp_pb2.Timestamp,) + end_time = proto.Field(proto.MESSAGE, number=2, message=timestamp_pb2.Timestamp,) + target = proto.Field(proto.STRING, number=3,) + verb = proto.Field(proto.STRING, number=4,) + status_detail = proto.Field(proto.STRING, number=5,) + cancel_requested = proto.Field(proto.BOOL, number=6,) + api_version = proto.Field(proto.STRING, number=7,) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/base.py b/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/base.py index 97da42a..ae89f69 100644 --- a/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/base.py +++ b/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/base.py @@ -98,7 +98,7 @@ def __init__( scopes_kwargs = self._get_scopes_kwargs(self._host, scopes) # Save the scopes. - self._scopes = scopes or self.AUTH_SCOPES + self._scopes = scopes # If no credentials are provided, then determine the appropriate # defaults. diff --git a/owlbot.py b/owlbot.py index 30544fa..1ce6b4c 100644 --- a/owlbot.py +++ b/owlbot.py @@ -22,10 +22,68 @@ common = gcp.CommonTemplates() -default_version = "v1beta1" +default_version = "v1" for library in s.get_staging_dirs(default_version): - s.move(library, excludes=["setup.py", "README.rst", "docs/index.rst"]) + dependencies = [ + "configmanagement", + "multiclusteringress", + ] + + # rename google.cloud.gkehub.vX to google.cloud.gkehub_vX + s.replace( + [ + library / f"google/cloud/gkehub_{library.name}/**/*.py", + library / f"tests/unit/gapic/gkehub_{library.name}/**/*.py", + ], + f"google.cloud.gkehub.{library.name}", + f"google.cloud.gkehub_{library.name}", + ) + + # rename dependencies google.cloud.gkehub.dep.vX to google.cloud.gkehub.dep_vX + for dep in dependencies: + s.replace( + [ + library / f"google/cloud/gkehub_{library.name}/**/*.py", + library / f"tests/unit/gapic/gkehub_{library.name}/**/*.py", + library / f"google/cloud/gkehub/{dep}_{library.name}/**/*.py", + ], + f"from google.cloud.gkehub.{dep}.{library.name} import", + f"import google.cloud.gkehub.{dep}_{library.name} as" + ) + + s.replace( + [ + library / f"google/cloud/gkehub_{library.name}/**/*.py", + library / f"tests/unit/gapic/gkehub_{library.name}/**/*.py", + library / f"google/cloud/gkehub/{dep}_{library.name}/**/*.py", + ], + f"google.cloud.gkehub.{dep}.{library.name}", + f"google.cloud.gkehub.{dep}_{library.name}" + ) + + # Work around gapic generator bug https://github.com/googleapis/gapic-generator-python/issues/902 + s.replace(library / f"google/cloud/**/types/*.py", + r""". + Attributes:""", + r""".\n + Attributes:""", + ) + + # Work around docs issue. Fix proposed upstream in cl/382492769 + s.replace(library / f"google/cloud/gkehub_{library.name}/types/feature.py", + " projects/{p}/locations/{l}/memberships/{m}", + "`projects/{p}/locations/{l}/memberships/{m}`" + ) + + # Work around docs issue. Fix proposed upstream in cl/382492769 + s.replace(library / f"google/cloud/gkehub_{library.name}/types/membership.py", + """the GKE cluster. For example: + //container.googleapis.com/projects/my-""", + """the GKE cluster. For example: + //container.googleapis.com/projects/my-""" + ) + s.move(library, excludes=["setup.py", "README.rst", "docs/index.rst","google/cloud/gkehub/__init__.py"]) s.remove_staging_dirs() diff --git a/scripts/fixup_configmanagement_v1_keywords.py b/scripts/fixup_configmanagement_v1_keywords.py new file mode 100644 index 0000000..b06f1d0 --- /dev/null +++ b/scripts/fixup_configmanagement_v1_keywords.py @@ -0,0 +1,175 @@ +#! /usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import argparse +import os +import libcst as cst +import pathlib +import sys +from typing import (Any, Callable, Dict, List, Sequence, Tuple) + + +def partition( + predicate: Callable[[Any], bool], + iterator: Sequence[Any] +) -> Tuple[List[Any], List[Any]]: + """A stable, out-of-place partition.""" + results = ([], []) + + for i in iterator: + results[int(predicate(i))].append(i) + + # Returns trueList, falseList + return results[1], results[0] + + +class configmanagementCallTransformer(cst.CSTTransformer): + CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') + METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { + } + + def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: + try: + key = original.func.attr.value + kword_params = self.METHOD_TO_PARAMS[key] + except (AttributeError, KeyError): + # Either not a method from the API or too convoluted to be sure. + return updated + + # If the existing code is valid, keyword args come after positional args. + # Therefore, all positional args must map to the first parameters. + args, kwargs = partition(lambda a: not bool(a.keyword), updated.args) + if any(k.keyword.value == "request" for k in kwargs): + # We've already fixed this file, don't fix it again. + return updated + + kwargs, ctrl_kwargs = partition( + lambda a: not a.keyword.value in self.CTRL_PARAMS, + kwargs + ) + + args, ctrl_args = args[:len(kword_params)], args[len(kword_params):] + ctrl_kwargs.extend(cst.Arg(value=a.value, keyword=cst.Name(value=ctrl)) + for a, ctrl in zip(ctrl_args, self.CTRL_PARAMS)) + + request_arg = cst.Arg( + value=cst.Dict([ + cst.DictElement( + cst.SimpleString("'{}'".format(name)), +cst.Element(value=arg.value) + ) + # Note: the args + kwargs looks silly, but keep in mind that + # the control parameters had to be stripped out, and that + # those could have been passed positionally or by keyword. + for name, arg in zip(kword_params, args + kwargs)]), + keyword=cst.Name("request") + ) + + return updated.with_changes( + args=[request_arg] + ctrl_kwargs + ) + + +def fix_files( + in_dir: pathlib.Path, + out_dir: pathlib.Path, + *, + transformer=configmanagementCallTransformer(), +): + """Duplicate the input dir to the output dir, fixing file method calls. + + Preconditions: + * in_dir is a real directory + * out_dir is a real, empty directory + """ + pyfile_gen = ( + pathlib.Path(os.path.join(root, f)) + for root, _, files in os.walk(in_dir) + for f in files if os.path.splitext(f)[1] == ".py" + ) + + for fpath in pyfile_gen: + with open(fpath, 'r') as f: + src = f.read() + + # Parse the code and insert method call fixes. + tree = cst.parse_module(src) + updated = tree.visit(transformer) + + # Create the path and directory structure for the new file. + updated_path = out_dir.joinpath(fpath.relative_to(in_dir)) + updated_path.parent.mkdir(parents=True, exist_ok=True) + + # Generate the updated source file at the corresponding path. + with open(updated_path, 'w') as f: + f.write(updated.code) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description="""Fix up source that uses the configmanagement client library. + +The existing sources are NOT overwritten but are copied to output_dir with changes made. + +Note: This tool operates at a best-effort level at converting positional + parameters in client method calls to keyword based parameters. + Cases where it WILL FAIL include + A) * or ** expansion in a method call. + B) Calls via function or method alias (includes free function calls) + C) Indirect or dispatched calls (e.g. the method is looked up dynamically) + + These all constitute false negatives. The tool will also detect false + positives when an API method shares a name with another method. +""") + parser.add_argument( + '-d', + '--input-directory', + required=True, + dest='input_dir', + help='the input directory to walk for python files to fix up', + ) + parser.add_argument( + '-o', + '--output-directory', + required=True, + dest='output_dir', + help='the directory to output files fixed via un-flattening', + ) + args = parser.parse_args() + input_dir = pathlib.Path(args.input_dir) + output_dir = pathlib.Path(args.output_dir) + if not input_dir.is_dir(): + print( + f"input directory '{input_dir}' does not exist or is not a directory", + file=sys.stderr, + ) + sys.exit(-1) + + if not output_dir.is_dir(): + print( + f"output directory '{output_dir}' does not exist or is not a directory", + file=sys.stderr, + ) + sys.exit(-1) + + if os.listdir(output_dir): + print( + f"output directory '{output_dir}' is not empty", + file=sys.stderr, + ) + sys.exit(-1) + + fix_files(input_dir, output_dir) diff --git a/scripts/fixup_gkehub_v1_keywords.py b/scripts/fixup_gkehub_v1_keywords.py new file mode 100644 index 0000000..a8a2a9b --- /dev/null +++ b/scripts/fixup_gkehub_v1_keywords.py @@ -0,0 +1,186 @@ +#! /usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import argparse +import os +import libcst as cst +import pathlib +import sys +from typing import (Any, Callable, Dict, List, Sequence, Tuple) + + +def partition( + predicate: Callable[[Any], bool], + iterator: Sequence[Any] +) -> Tuple[List[Any], List[Any]]: + """A stable, out-of-place partition.""" + results = ([], []) + + for i in iterator: + results[int(predicate(i))].append(i) + + # Returns trueList, falseList + return results[1], results[0] + + +class gkehubCallTransformer(cst.CSTTransformer): + CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') + METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { + 'create_feature': ('parent', 'feature_id', 'resource', 'request_id', ), + 'create_membership': ('parent', 'membership_id', 'resource', 'request_id', ), + 'delete_feature': ('name', 'force', 'request_id', ), + 'delete_membership': ('name', 'request_id', ), + 'generate_connect_manifest': ('name', 'namespace', 'proxy', 'version', 'is_upgrade', 'registry', 'image_pull_secret_content', ), + 'get_feature': ('name', ), + 'get_membership': ('name', ), + 'list_features': ('parent', 'page_size', 'page_token', 'filter', 'order_by', ), + 'list_memberships': ('parent', 'page_size', 'page_token', 'filter', 'order_by', ), + 'update_feature': ('name', 'update_mask', 'resource', 'request_id', ), + 'update_membership': ('name', 'update_mask', 'resource', 'request_id', ), + } + + def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: + try: + key = original.func.attr.value + kword_params = self.METHOD_TO_PARAMS[key] + except (AttributeError, KeyError): + # Either not a method from the API or too convoluted to be sure. + return updated + + # If the existing code is valid, keyword args come after positional args. + # Therefore, all positional args must map to the first parameters. + args, kwargs = partition(lambda a: not bool(a.keyword), updated.args) + if any(k.keyword.value == "request" for k in kwargs): + # We've already fixed this file, don't fix it again. + return updated + + kwargs, ctrl_kwargs = partition( + lambda a: not a.keyword.value in self.CTRL_PARAMS, + kwargs + ) + + args, ctrl_args = args[:len(kword_params)], args[len(kword_params):] + ctrl_kwargs.extend(cst.Arg(value=a.value, keyword=cst.Name(value=ctrl)) + for a, ctrl in zip(ctrl_args, self.CTRL_PARAMS)) + + request_arg = cst.Arg( + value=cst.Dict([ + cst.DictElement( + cst.SimpleString("'{}'".format(name)), +cst.Element(value=arg.value) + ) + # Note: the args + kwargs looks silly, but keep in mind that + # the control parameters had to be stripped out, and that + # those could have been passed positionally or by keyword. + for name, arg in zip(kword_params, args + kwargs)]), + keyword=cst.Name("request") + ) + + return updated.with_changes( + args=[request_arg] + ctrl_kwargs + ) + + +def fix_files( + in_dir: pathlib.Path, + out_dir: pathlib.Path, + *, + transformer=gkehubCallTransformer(), +): + """Duplicate the input dir to the output dir, fixing file method calls. + + Preconditions: + * in_dir is a real directory + * out_dir is a real, empty directory + """ + pyfile_gen = ( + pathlib.Path(os.path.join(root, f)) + for root, _, files in os.walk(in_dir) + for f in files if os.path.splitext(f)[1] == ".py" + ) + + for fpath in pyfile_gen: + with open(fpath, 'r') as f: + src = f.read() + + # Parse the code and insert method call fixes. + tree = cst.parse_module(src) + updated = tree.visit(transformer) + + # Create the path and directory structure for the new file. + updated_path = out_dir.joinpath(fpath.relative_to(in_dir)) + updated_path.parent.mkdir(parents=True, exist_ok=True) + + # Generate the updated source file at the corresponding path. + with open(updated_path, 'w') as f: + f.write(updated.code) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description="""Fix up source that uses the gkehub client library. + +The existing sources are NOT overwritten but are copied to output_dir with changes made. + +Note: This tool operates at a best-effort level at converting positional + parameters in client method calls to keyword based parameters. + Cases where it WILL FAIL include + A) * or ** expansion in a method call. + B) Calls via function or method alias (includes free function calls) + C) Indirect or dispatched calls (e.g. the method is looked up dynamically) + + These all constitute false negatives. The tool will also detect false + positives when an API method shares a name with another method. +""") + parser.add_argument( + '-d', + '--input-directory', + required=True, + dest='input_dir', + help='the input directory to walk for python files to fix up', + ) + parser.add_argument( + '-o', + '--output-directory', + required=True, + dest='output_dir', + help='the directory to output files fixed via un-flattening', + ) + args = parser.parse_args() + input_dir = pathlib.Path(args.input_dir) + output_dir = pathlib.Path(args.output_dir) + if not input_dir.is_dir(): + print( + f"input directory '{input_dir}' does not exist or is not a directory", + file=sys.stderr, + ) + sys.exit(-1) + + if not output_dir.is_dir(): + print( + f"output directory '{output_dir}' does not exist or is not a directory", + file=sys.stderr, + ) + sys.exit(-1) + + if os.listdir(output_dir): + print( + f"output directory '{output_dir}' is not empty", + file=sys.stderr, + ) + sys.exit(-1) + + fix_files(input_dir, output_dir) diff --git a/scripts/fixup_multiclusteringress_v1_keywords.py b/scripts/fixup_multiclusteringress_v1_keywords.py new file mode 100644 index 0000000..e15ebbc --- /dev/null +++ b/scripts/fixup_multiclusteringress_v1_keywords.py @@ -0,0 +1,175 @@ +#! /usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import argparse +import os +import libcst as cst +import pathlib +import sys +from typing import (Any, Callable, Dict, List, Sequence, Tuple) + + +def partition( + predicate: Callable[[Any], bool], + iterator: Sequence[Any] +) -> Tuple[List[Any], List[Any]]: + """A stable, out-of-place partition.""" + results = ([], []) + + for i in iterator: + results[int(predicate(i))].append(i) + + # Returns trueList, falseList + return results[1], results[0] + + +class multiclusteringressCallTransformer(cst.CSTTransformer): + CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') + METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { + } + + def leave_Call(self, original: cst.Call, updated: cst.Call) -> cst.CSTNode: + try: + key = original.func.attr.value + kword_params = self.METHOD_TO_PARAMS[key] + except (AttributeError, KeyError): + # Either not a method from the API or too convoluted to be sure. + return updated + + # If the existing code is valid, keyword args come after positional args. + # Therefore, all positional args must map to the first parameters. + args, kwargs = partition(lambda a: not bool(a.keyword), updated.args) + if any(k.keyword.value == "request" for k in kwargs): + # We've already fixed this file, don't fix it again. + return updated + + kwargs, ctrl_kwargs = partition( + lambda a: not a.keyword.value in self.CTRL_PARAMS, + kwargs + ) + + args, ctrl_args = args[:len(kword_params)], args[len(kword_params):] + ctrl_kwargs.extend(cst.Arg(value=a.value, keyword=cst.Name(value=ctrl)) + for a, ctrl in zip(ctrl_args, self.CTRL_PARAMS)) + + request_arg = cst.Arg( + value=cst.Dict([ + cst.DictElement( + cst.SimpleString("'{}'".format(name)), +cst.Element(value=arg.value) + ) + # Note: the args + kwargs looks silly, but keep in mind that + # the control parameters had to be stripped out, and that + # those could have been passed positionally or by keyword. + for name, arg in zip(kword_params, args + kwargs)]), + keyword=cst.Name("request") + ) + + return updated.with_changes( + args=[request_arg] + ctrl_kwargs + ) + + +def fix_files( + in_dir: pathlib.Path, + out_dir: pathlib.Path, + *, + transformer=multiclusteringressCallTransformer(), +): + """Duplicate the input dir to the output dir, fixing file method calls. + + Preconditions: + * in_dir is a real directory + * out_dir is a real, empty directory + """ + pyfile_gen = ( + pathlib.Path(os.path.join(root, f)) + for root, _, files in os.walk(in_dir) + for f in files if os.path.splitext(f)[1] == ".py" + ) + + for fpath in pyfile_gen: + with open(fpath, 'r') as f: + src = f.read() + + # Parse the code and insert method call fixes. + tree = cst.parse_module(src) + updated = tree.visit(transformer) + + # Create the path and directory structure for the new file. + updated_path = out_dir.joinpath(fpath.relative_to(in_dir)) + updated_path.parent.mkdir(parents=True, exist_ok=True) + + # Generate the updated source file at the corresponding path. + with open(updated_path, 'w') as f: + f.write(updated.code) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description="""Fix up source that uses the multiclusteringress client library. + +The existing sources are NOT overwritten but are copied to output_dir with changes made. + +Note: This tool operates at a best-effort level at converting positional + parameters in client method calls to keyword based parameters. + Cases where it WILL FAIL include + A) * or ** expansion in a method call. + B) Calls via function or method alias (includes free function calls) + C) Indirect or dispatched calls (e.g. the method is looked up dynamically) + + These all constitute false negatives. The tool will also detect false + positives when an API method shares a name with another method. +""") + parser.add_argument( + '-d', + '--input-directory', + required=True, + dest='input_dir', + help='the input directory to walk for python files to fix up', + ) + parser.add_argument( + '-o', + '--output-directory', + required=True, + dest='output_dir', + help='the directory to output files fixed via un-flattening', + ) + args = parser.parse_args() + input_dir = pathlib.Path(args.input_dir) + output_dir = pathlib.Path(args.output_dir) + if not input_dir.is_dir(): + print( + f"input directory '{input_dir}' does not exist or is not a directory", + file=sys.stderr, + ) + sys.exit(-1) + + if not output_dir.is_dir(): + print( + f"output directory '{output_dir}' does not exist or is not a directory", + file=sys.stderr, + ) + sys.exit(-1) + + if os.listdir(output_dir): + print( + f"output directory '{output_dir}' is not empty", + file=sys.stderr, + ) + sys.exit(-1) + + fix_files(input_dir, output_dir) diff --git a/tests/unit/gapic/configmanagement_v1/__init__.py b/tests/unit/gapic/configmanagement_v1/__init__.py new file mode 100644 index 0000000..4de6597 --- /dev/null +++ b/tests/unit/gapic/configmanagement_v1/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/tests/unit/gapic/gkehub_v1/__init__.py b/tests/unit/gapic/gkehub_v1/__init__.py new file mode 100644 index 0000000..4de6597 --- /dev/null +++ b/tests/unit/gapic/gkehub_v1/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/tests/unit/gapic/gkehub_v1/test_gke_hub.py b/tests/unit/gapic/gkehub_v1/test_gke_hub.py new file mode 100644 index 0000000..5eefc81 --- /dev/null +++ b/tests/unit/gapic/gkehub_v1/test_gke_hub.py @@ -0,0 +1,3641 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import os +import mock +import packaging.version + +import grpc +from grpc.experimental import aio +import math +import pytest +from proto.marshal.rules.dates import DurationRule, TimestampRule + + +from google.api_core import client_options +from google.api_core import exceptions as core_exceptions +from google.api_core import future +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 # type: ignore +from google.api_core import operations_v1 +from google.auth import credentials as ga_credentials +from google.auth.exceptions import MutualTLSChannelError +import google.cloud.gkehub.configmanagement_v1 as configmanagement_pb2 # type: ignore +import google.cloud.gkehub.multiclusteringress_v1 as multiclusteringress_pb2 # type: ignore +from google.cloud.gkehub_v1.services.gke_hub import GkeHubAsyncClient +from google.cloud.gkehub_v1.services.gke_hub import GkeHubClient +from google.cloud.gkehub_v1.services.gke_hub import pagers +from google.cloud.gkehub_v1.services.gke_hub import transports +from google.cloud.gkehub_v1.services.gke_hub.transports.base import _GOOGLE_AUTH_VERSION +from google.cloud.gkehub_v1.types import feature +from google.cloud.gkehub_v1.types import membership +from google.cloud.gkehub_v1.types import service +from google.longrunning import operations_pb2 +from google.oauth2 import service_account +from google.protobuf import field_mask_pb2 # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore +import google.auth + + +# TODO(busunkim): Once google-auth >= 1.25.0 is required transitively +# through google-api-core: +# - Delete the auth "less than" test cases +# - Delete these pytest markers (Make the "greater than or equal to" tests the default). +requires_google_auth_lt_1_25_0 = pytest.mark.skipif( + packaging.version.parse(_GOOGLE_AUTH_VERSION) >= packaging.version.parse("1.25.0"), + reason="This test requires google-auth < 1.25.0", +) +requires_google_auth_gte_1_25_0 = pytest.mark.skipif( + packaging.version.parse(_GOOGLE_AUTH_VERSION) < packaging.version.parse("1.25.0"), + reason="This test requires google-auth >= 1.25.0", +) + + +def client_cert_source_callback(): + return b"cert bytes", b"key bytes" + + +# If default endpoint is localhost, then default mtls endpoint will be the same. +# This method modifies the default endpoint so the client can produce a different +# mtls endpoint for endpoint testing purposes. +def modify_default_endpoint(client): + return ( + "foo.googleapis.com" + if ("localhost" in client.DEFAULT_ENDPOINT) + else client.DEFAULT_ENDPOINT + ) + + +def test__get_default_mtls_endpoint(): + api_endpoint = "example.googleapis.com" + api_mtls_endpoint = "example.mtls.googleapis.com" + sandbox_endpoint = "example.sandbox.googleapis.com" + sandbox_mtls_endpoint = "example.mtls.sandbox.googleapis.com" + non_googleapi = "api.example.com" + + assert GkeHubClient._get_default_mtls_endpoint(None) is None + assert GkeHubClient._get_default_mtls_endpoint(api_endpoint) == api_mtls_endpoint + assert ( + GkeHubClient._get_default_mtls_endpoint(api_mtls_endpoint) == api_mtls_endpoint + ) + assert ( + GkeHubClient._get_default_mtls_endpoint(sandbox_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + GkeHubClient._get_default_mtls_endpoint(sandbox_mtls_endpoint) + == sandbox_mtls_endpoint + ) + assert GkeHubClient._get_default_mtls_endpoint(non_googleapi) == non_googleapi + + +@pytest.mark.parametrize("client_class", [GkeHubClient, GkeHubAsyncClient,]) +def test_gke_hub_client_from_service_account_info(client_class): + creds = ga_credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_info" + ) as factory: + factory.return_value = creds + info = {"valid": True} + client = client_class.from_service_account_info(info) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == "gkehub.googleapis.com:443" + + +@pytest.mark.parametrize("client_class", [GkeHubClient, GkeHubAsyncClient,]) +def test_gke_hub_client_service_account_always_use_jwt(client_class): + with mock.patch.object( + service_account.Credentials, "with_always_use_jwt_access", create=True + ) as use_jwt: + creds = service_account.Credentials(None, None, None) + client = client_class(credentials=creds) + use_jwt.assert_not_called() + + +@pytest.mark.parametrize( + "transport_class,transport_name", + [ + (transports.GkeHubGrpcTransport, "grpc"), + (transports.GkeHubGrpcAsyncIOTransport, "grpc_asyncio"), + ], +) +def test_gke_hub_client_service_account_always_use_jwt_true( + transport_class, transport_name +): + with mock.patch.object( + service_account.Credentials, "with_always_use_jwt_access", create=True + ) as use_jwt: + creds = service_account.Credentials(None, None, None) + transport = transport_class(credentials=creds, always_use_jwt_access=True) + use_jwt.assert_called_once_with(True) + + +@pytest.mark.parametrize("client_class", [GkeHubClient, GkeHubAsyncClient,]) +def test_gke_hub_client_from_service_account_file(client_class): + creds = ga_credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_file" + ) as factory: + factory.return_value = creds + client = client_class.from_service_account_file("dummy/file/path.json") + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + client = client_class.from_service_account_json("dummy/file/path.json") + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == "gkehub.googleapis.com:443" + + +def test_gke_hub_client_get_transport_class(): + transport = GkeHubClient.get_transport_class() + available_transports = [ + transports.GkeHubGrpcTransport, + ] + assert transport in available_transports + + transport = GkeHubClient.get_transport_class("grpc") + assert transport == transports.GkeHubGrpcTransport + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (GkeHubClient, transports.GkeHubGrpcTransport, "grpc"), + (GkeHubAsyncClient, transports.GkeHubGrpcAsyncIOTransport, "grpc_asyncio"), + ], +) +@mock.patch.object( + GkeHubClient, "DEFAULT_ENDPOINT", modify_default_endpoint(GkeHubClient) +) +@mock.patch.object( + GkeHubAsyncClient, "DEFAULT_ENDPOINT", modify_default_endpoint(GkeHubAsyncClient) +) +def test_gke_hub_client_client_options(client_class, transport_class, transport_name): + # Check that if channel is provided we won't create a new one. + with mock.patch.object(GkeHubClient, "get_transport_class") as gtc: + transport = transport_class(credentials=ga_credentials.AnonymousCredentials()) + client = client_class(transport=transport) + gtc.assert_not_called() + + # Check that if channel is provided via str we will create a new one. + with mock.patch.object(GkeHubClient, "get_transport_class") as gtc: + client = client_class(transport=transport_name) + gtc.assert_called() + + # Check the case api_endpoint is provided. + options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") + 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="squid.clam.whelk", + scopes=None, + client_cert_source_for_mtls=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_ENDPOINT is + # "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() + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + # 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_ENDPOINT": "always"}): + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class() + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_MTLS_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=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_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, + client_cert_source_for_mtls=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", + [ + (GkeHubClient, transports.GkeHubGrpcTransport, "grpc", "true"), + ( + GkeHubAsyncClient, + transports.GkeHubGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + (GkeHubClient, transports.GkeHubGrpcTransport, "grpc", "false"), + ( + GkeHubAsyncClient, + transports.GkeHubGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ], +) +@mock.patch.object( + GkeHubClient, "DEFAULT_ENDPOINT", modify_default_endpoint(GkeHubClient) +) +@mock.patch.object( + GkeHubAsyncClient, "DEFAULT_ENDPOINT", modify_default_endpoint(GkeHubAsyncClient) +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_gke_hub_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) + + if use_client_cert_env == "false": + expected_client_cert_source = None + expected_host = client.DEFAULT_ENDPOINT + else: + expected_client_cert_source = client_cert_source_callback + expected_host = client.DEFAULT_MTLS_ENDPOINT + + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + # Check the case ADC client cert is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + 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=True, + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=client_cert_source_callback, + ): + if use_client_cert_env == "false": + expected_host = client.DEFAULT_ENDPOINT + expected_client_cert_source = None + else: + expected_host = client.DEFAULT_MTLS_ENDPOINT + expected_client_cert_source = client_cert_source_callback + + patched.return_value = None + client = client_class() + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + # Check the case client_cert_source and ADC client cert are not provided. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + patched.return_value = None + client = client_class() + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (GkeHubClient, transports.GkeHubGrpcTransport, "grpc"), + (GkeHubAsyncClient, transports.GkeHubGrpcAsyncIOTransport, "grpc_asyncio"), + ], +) +def test_gke_hub_client_client_options_scopes( + client_class, transport_class, transport_name +): + # Check the case scopes are provided. + options = client_options.ClientOptions(scopes=["1", "2"],) + 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=["1", "2"], + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (GkeHubClient, transports.GkeHubGrpcTransport, "grpc"), + (GkeHubAsyncClient, transports.GkeHubGrpcAsyncIOTransport, "grpc_asyncio"), + ], +) +def test_gke_hub_client_client_options_credentials_file( + client_class, transport_class, transport_name +): + # Check the case credentials file is provided. + options = client_options.ClientOptions(credentials_file="credentials.json") + 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="credentials.json", + host=client.DEFAULT_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + +def test_gke_hub_client_client_options_from_dict(): + with mock.patch( + "google.cloud.gkehub_v1.services.gke_hub.transports.GkeHubGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = GkeHubClient(client_options={"api_endpoint": "squid.clam.whelk"}) + grpc_transport.assert_called_once_with( + credentials=None, + credentials_file=None, + host="squid.clam.whelk", + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + ) + + +def test_list_memberships( + transport: str = "grpc", request_type=service.ListMembershipsRequest +): + client = GkeHubClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_memberships), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = service.ListMembershipsResponse( + next_page_token="next_page_token_value", unreachable=["unreachable_value"], + ) + response = client.list_memberships(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == service.ListMembershipsRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListMembershipsPager) + assert response.next_page_token == "next_page_token_value" + assert response.unreachable == ["unreachable_value"] + + +def test_list_memberships_from_dict(): + test_list_memberships(request_type=dict) + + +def test_list_memberships_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GkeHubClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_memberships), "__call__") as call: + client.list_memberships() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == service.ListMembershipsRequest() + + +@pytest.mark.asyncio +async def test_list_memberships_async( + transport: str = "grpc_asyncio", request_type=service.ListMembershipsRequest +): + client = GkeHubAsyncClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_memberships), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + service.ListMembershipsResponse( + next_page_token="next_page_token_value", + unreachable=["unreachable_value"], + ) + ) + response = await client.list_memberships(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == service.ListMembershipsRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListMembershipsAsyncPager) + assert response.next_page_token == "next_page_token_value" + assert response.unreachable == ["unreachable_value"] + + +@pytest.mark.asyncio +async def test_list_memberships_async_from_dict(): + await test_list_memberships_async(request_type=dict) + + +def test_list_memberships_field_headers(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.ListMembershipsRequest() + + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_memberships), "__call__") as call: + call.return_value = service.ListMembershipsResponse() + client.list_memberships(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "parent=parent/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_list_memberships_field_headers_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.ListMembershipsRequest() + + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_memberships), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + service.ListMembershipsResponse() + ) + await client.list_memberships(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "parent=parent/value",) in kw["metadata"] + + +def test_list_memberships_flattened(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_memberships), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = service.ListMembershipsResponse() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.list_memberships(parent="parent_value",) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0].parent == "parent_value" + + +def test_list_memberships_flattened_error(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.list_memberships( + service.ListMembershipsRequest(), parent="parent_value", + ) + + +@pytest.mark.asyncio +async def test_list_memberships_flattened_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_memberships), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = service.ListMembershipsResponse() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + service.ListMembershipsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.list_memberships(parent="parent_value",) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0].parent == "parent_value" + + +@pytest.mark.asyncio +async def test_list_memberships_flattened_error_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.list_memberships( + service.ListMembershipsRequest(), parent="parent_value", + ) + + +def test_list_memberships_pager(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_memberships), "__call__") as call: + # Set the response to a series of pages. + call.side_effect = ( + service.ListMembershipsResponse( + resources=[ + membership.Membership(), + membership.Membership(), + membership.Membership(), + ], + next_page_token="abc", + ), + service.ListMembershipsResponse(resources=[], next_page_token="def",), + service.ListMembershipsResponse( + resources=[membership.Membership(),], next_page_token="ghi", + ), + service.ListMembershipsResponse( + resources=[membership.Membership(), membership.Membership(),], + ), + RuntimeError, + ) + + metadata = () + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", ""),)), + ) + pager = client.list_memberships(request={}) + + assert pager._metadata == metadata + + results = [i for i in pager] + assert len(results) == 6 + assert all(isinstance(i, membership.Membership) for i in results) + + +def test_list_memberships_pages(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_memberships), "__call__") as call: + # Set the response to a series of pages. + call.side_effect = ( + service.ListMembershipsResponse( + resources=[ + membership.Membership(), + membership.Membership(), + membership.Membership(), + ], + next_page_token="abc", + ), + service.ListMembershipsResponse(resources=[], next_page_token="def",), + service.ListMembershipsResponse( + resources=[membership.Membership(),], next_page_token="ghi", + ), + service.ListMembershipsResponse( + resources=[membership.Membership(), membership.Membership(),], + ), + RuntimeError, + ) + pages = list(client.list_memberships(request={}).pages) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + +@pytest.mark.asyncio +async def test_list_memberships_async_pager(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_memberships), "__call__", new_callable=mock.AsyncMock + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + service.ListMembershipsResponse( + resources=[ + membership.Membership(), + membership.Membership(), + membership.Membership(), + ], + next_page_token="abc", + ), + service.ListMembershipsResponse(resources=[], next_page_token="def",), + service.ListMembershipsResponse( + resources=[membership.Membership(),], next_page_token="ghi", + ), + service.ListMembershipsResponse( + resources=[membership.Membership(), membership.Membership(),], + ), + RuntimeError, + ) + async_pager = await client.list_memberships(request={},) + assert async_pager.next_page_token == "abc" + responses = [] + async for response in async_pager: + responses.append(response) + + assert len(responses) == 6 + assert all(isinstance(i, membership.Membership) for i in responses) + + +@pytest.mark.asyncio +async def test_list_memberships_async_pages(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_memberships), "__call__", new_callable=mock.AsyncMock + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + service.ListMembershipsResponse( + resources=[ + membership.Membership(), + membership.Membership(), + membership.Membership(), + ], + next_page_token="abc", + ), + service.ListMembershipsResponse(resources=[], next_page_token="def",), + service.ListMembershipsResponse( + resources=[membership.Membership(),], next_page_token="ghi", + ), + service.ListMembershipsResponse( + resources=[membership.Membership(), membership.Membership(),], + ), + RuntimeError, + ) + pages = [] + async for page_ in (await client.list_memberships(request={})).pages: + pages.append(page_) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + +def test_list_features( + transport: str = "grpc", request_type=service.ListFeaturesRequest +): + client = GkeHubClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_features), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = service.ListFeaturesResponse( + next_page_token="next_page_token_value", + ) + response = client.list_features(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == service.ListFeaturesRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListFeaturesPager) + assert response.next_page_token == "next_page_token_value" + + +def test_list_features_from_dict(): + test_list_features(request_type=dict) + + +def test_list_features_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GkeHubClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_features), "__call__") as call: + client.list_features() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == service.ListFeaturesRequest() + + +@pytest.mark.asyncio +async def test_list_features_async( + transport: str = "grpc_asyncio", request_type=service.ListFeaturesRequest +): + client = GkeHubAsyncClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_features), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + service.ListFeaturesResponse(next_page_token="next_page_token_value",) + ) + response = await client.list_features(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == service.ListFeaturesRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListFeaturesAsyncPager) + assert response.next_page_token == "next_page_token_value" + + +@pytest.mark.asyncio +async def test_list_features_async_from_dict(): + await test_list_features_async(request_type=dict) + + +def test_list_features_field_headers(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.ListFeaturesRequest() + + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_features), "__call__") as call: + call.return_value = service.ListFeaturesResponse() + client.list_features(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "parent=parent/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_list_features_field_headers_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.ListFeaturesRequest() + + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_features), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + service.ListFeaturesResponse() + ) + await client.list_features(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "parent=parent/value",) in kw["metadata"] + + +def test_list_features_flattened(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_features), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = service.ListFeaturesResponse() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.list_features(parent="parent_value",) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0].parent == "parent_value" + + +def test_list_features_flattened_error(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.list_features( + service.ListFeaturesRequest(), parent="parent_value", + ) + + +@pytest.mark.asyncio +async def test_list_features_flattened_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_features), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = service.ListFeaturesResponse() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + service.ListFeaturesResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.list_features(parent="parent_value",) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0].parent == "parent_value" + + +@pytest.mark.asyncio +async def test_list_features_flattened_error_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.list_features( + service.ListFeaturesRequest(), parent="parent_value", + ) + + +def test_list_features_pager(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_features), "__call__") as call: + # Set the response to a series of pages. + call.side_effect = ( + service.ListFeaturesResponse( + resources=[feature.Feature(), feature.Feature(), feature.Feature(),], + next_page_token="abc", + ), + service.ListFeaturesResponse(resources=[], next_page_token="def",), + service.ListFeaturesResponse( + resources=[feature.Feature(),], next_page_token="ghi", + ), + service.ListFeaturesResponse( + resources=[feature.Feature(), feature.Feature(),], + ), + RuntimeError, + ) + + metadata = () + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", ""),)), + ) + pager = client.list_features(request={}) + + assert pager._metadata == metadata + + results = [i for i in pager] + assert len(results) == 6 + assert all(isinstance(i, feature.Feature) for i in results) + + +def test_list_features_pages(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_features), "__call__") as call: + # Set the response to a series of pages. + call.side_effect = ( + service.ListFeaturesResponse( + resources=[feature.Feature(), feature.Feature(), feature.Feature(),], + next_page_token="abc", + ), + service.ListFeaturesResponse(resources=[], next_page_token="def",), + service.ListFeaturesResponse( + resources=[feature.Feature(),], next_page_token="ghi", + ), + service.ListFeaturesResponse( + resources=[feature.Feature(), feature.Feature(),], + ), + RuntimeError, + ) + pages = list(client.list_features(request={}).pages) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + +@pytest.mark.asyncio +async def test_list_features_async_pager(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_features), "__call__", new_callable=mock.AsyncMock + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + service.ListFeaturesResponse( + resources=[feature.Feature(), feature.Feature(), feature.Feature(),], + next_page_token="abc", + ), + service.ListFeaturesResponse(resources=[], next_page_token="def",), + service.ListFeaturesResponse( + resources=[feature.Feature(),], next_page_token="ghi", + ), + service.ListFeaturesResponse( + resources=[feature.Feature(), feature.Feature(),], + ), + RuntimeError, + ) + async_pager = await client.list_features(request={},) + assert async_pager.next_page_token == "abc" + responses = [] + async for response in async_pager: + responses.append(response) + + assert len(responses) == 6 + assert all(isinstance(i, feature.Feature) for i in responses) + + +@pytest.mark.asyncio +async def test_list_features_async_pages(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials,) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_features), "__call__", new_callable=mock.AsyncMock + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + service.ListFeaturesResponse( + resources=[feature.Feature(), feature.Feature(), feature.Feature(),], + next_page_token="abc", + ), + service.ListFeaturesResponse(resources=[], next_page_token="def",), + service.ListFeaturesResponse( + resources=[feature.Feature(),], next_page_token="ghi", + ), + service.ListFeaturesResponse( + resources=[feature.Feature(), feature.Feature(),], + ), + RuntimeError, + ) + pages = [] + async for page_ in (await client.list_features(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_membership( + transport: str = "grpc", request_type=service.GetMembershipRequest +): + client = GkeHubClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_membership), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = membership.Membership( + name="name_value", + description="description_value", + external_id="external_id_value", + unique_id="unique_id_value", + endpoint=membership.MembershipEndpoint( + gke_cluster=membership.GkeCluster(resource_link="resource_link_value") + ), + ) + response = client.get_membership(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == service.GetMembershipRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, membership.Membership) + assert response.name == "name_value" + assert response.description == "description_value" + assert response.external_id == "external_id_value" + assert response.unique_id == "unique_id_value" + + +def test_get_membership_from_dict(): + test_get_membership(request_type=dict) + + +def test_get_membership_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GkeHubClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_membership), "__call__") as call: + client.get_membership() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == service.GetMembershipRequest() + + +@pytest.mark.asyncio +async def test_get_membership_async( + transport: str = "grpc_asyncio", request_type=service.GetMembershipRequest +): + client = GkeHubAsyncClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_membership), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + membership.Membership( + name="name_value", + description="description_value", + external_id="external_id_value", + unique_id="unique_id_value", + ) + ) + response = await client.get_membership(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == service.GetMembershipRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, membership.Membership) + assert response.name == "name_value" + assert response.description == "description_value" + assert response.external_id == "external_id_value" + assert response.unique_id == "unique_id_value" + + +@pytest.mark.asyncio +async def test_get_membership_async_from_dict(): + await test_get_membership_async(request_type=dict) + + +def test_get_membership_field_headers(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.GetMembershipRequest() + + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_membership), "__call__") as call: + call.return_value = membership.Membership() + client.get_membership(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_get_membership_field_headers_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.GetMembershipRequest() + + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_membership), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + membership.Membership() + ) + await client.get_membership(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +def test_get_membership_flattened(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_membership), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = membership.Membership() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.get_membership(name="name_value",) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0].name == "name_value" + + +def test_get_membership_flattened_error(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_membership( + service.GetMembershipRequest(), name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_membership_flattened_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_membership), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = membership.Membership() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + membership.Membership() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.get_membership(name="name_value",) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0].name == "name_value" + + +@pytest.mark.asyncio +async def test_get_membership_flattened_error_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.get_membership( + service.GetMembershipRequest(), name="name_value", + ) + + +def test_get_feature(transport: str = "grpc", request_type=service.GetFeatureRequest): + client = GkeHubClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_feature), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = feature.Feature(name="name_value",) + response = client.get_feature(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == service.GetFeatureRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, feature.Feature) + assert response.name == "name_value" + + +def test_get_feature_from_dict(): + test_get_feature(request_type=dict) + + +def test_get_feature_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GkeHubClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_feature), "__call__") as call: + client.get_feature() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == service.GetFeatureRequest() + + +@pytest.mark.asyncio +async def test_get_feature_async( + transport: str = "grpc_asyncio", request_type=service.GetFeatureRequest +): + client = GkeHubAsyncClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_feature), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + feature.Feature(name="name_value",) + ) + response = await client.get_feature(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == service.GetFeatureRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, feature.Feature) + assert response.name == "name_value" + + +@pytest.mark.asyncio +async def test_get_feature_async_from_dict(): + await test_get_feature_async(request_type=dict) + + +def test_get_feature_field_headers(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.GetFeatureRequest() + + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_feature), "__call__") as call: + call.return_value = feature.Feature() + client.get_feature(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_get_feature_field_headers_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.GetFeatureRequest() + + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_feature), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(feature.Feature()) + await client.get_feature(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +def test_get_feature_flattened(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_feature), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = feature.Feature() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.get_feature(name="name_value",) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0].name == "name_value" + + +def test_get_feature_flattened_error(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_feature( + service.GetFeatureRequest(), name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_feature_flattened_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_feature), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = feature.Feature() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(feature.Feature()) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.get_feature(name="name_value",) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0].name == "name_value" + + +@pytest.mark.asyncio +async def test_get_feature_flattened_error_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.get_feature( + service.GetFeatureRequest(), name="name_value", + ) + + +def test_create_membership( + transport: str = "grpc", request_type=service.CreateMembershipRequest +): + client = GkeHubClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_membership), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.create_membership(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == service.CreateMembershipRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_create_membership_from_dict(): + test_create_membership(request_type=dict) + + +def test_create_membership_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GkeHubClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_membership), "__call__" + ) as call: + client.create_membership() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == service.CreateMembershipRequest() + + +@pytest.mark.asyncio +async def test_create_membership_async( + transport: str = "grpc_asyncio", request_type=service.CreateMembershipRequest +): + client = GkeHubAsyncClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_membership), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.create_membership(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == service.CreateMembershipRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +@pytest.mark.asyncio +async def test_create_membership_async_from_dict(): + await test_create_membership_async(request_type=dict) + + +def test_create_membership_field_headers(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.CreateMembershipRequest() + + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_membership), "__call__" + ) as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.create_membership(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "parent=parent/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_create_membership_field_headers_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.CreateMembershipRequest() + + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_membership), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.create_membership(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "parent=parent/value",) in kw["metadata"] + + +def test_create_membership_flattened(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_membership), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.create_membership( + parent="parent_value", + resource=membership.Membership( + endpoint=membership.MembershipEndpoint( + gke_cluster=membership.GkeCluster( + resource_link="resource_link_value" + ) + ) + ), + membership_id="membership_id_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0].parent == "parent_value" + assert args[0].resource == membership.Membership( + endpoint=membership.MembershipEndpoint( + gke_cluster=membership.GkeCluster(resource_link="resource_link_value") + ) + ) + assert args[0].membership_id == "membership_id_value" + + +def test_create_membership_flattened_error(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.create_membership( + service.CreateMembershipRequest(), + parent="parent_value", + resource=membership.Membership( + endpoint=membership.MembershipEndpoint( + gke_cluster=membership.GkeCluster( + resource_link="resource_link_value" + ) + ) + ), + membership_id="membership_id_value", + ) + + +@pytest.mark.asyncio +async def test_create_membership_flattened_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_membership), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.create_membership( + parent="parent_value", + resource=membership.Membership( + endpoint=membership.MembershipEndpoint( + gke_cluster=membership.GkeCluster( + resource_link="resource_link_value" + ) + ) + ), + membership_id="membership_id_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0].parent == "parent_value" + assert args[0].resource == membership.Membership( + endpoint=membership.MembershipEndpoint( + gke_cluster=membership.GkeCluster(resource_link="resource_link_value") + ) + ) + assert args[0].membership_id == "membership_id_value" + + +@pytest.mark.asyncio +async def test_create_membership_flattened_error_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.create_membership( + service.CreateMembershipRequest(), + parent="parent_value", + resource=membership.Membership( + endpoint=membership.MembershipEndpoint( + gke_cluster=membership.GkeCluster( + resource_link="resource_link_value" + ) + ) + ), + membership_id="membership_id_value", + ) + + +def test_create_feature( + transport: str = "grpc", request_type=service.CreateFeatureRequest +): + client = GkeHubClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_feature), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.create_feature(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == service.CreateFeatureRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_create_feature_from_dict(): + test_create_feature(request_type=dict) + + +def test_create_feature_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GkeHubClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_feature), "__call__") as call: + client.create_feature() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == service.CreateFeatureRequest() + + +@pytest.mark.asyncio +async def test_create_feature_async( + transport: str = "grpc_asyncio", request_type=service.CreateFeatureRequest +): + client = GkeHubAsyncClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_feature), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.create_feature(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == service.CreateFeatureRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +@pytest.mark.asyncio +async def test_create_feature_async_from_dict(): + await test_create_feature_async(request_type=dict) + + +def test_create_feature_field_headers(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.CreateFeatureRequest() + + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_feature), "__call__") as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.create_feature(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "parent=parent/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_create_feature_field_headers_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.CreateFeatureRequest() + + request.parent = "parent/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_feature), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.create_feature(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "parent=parent/value",) in kw["metadata"] + + +def test_create_feature_flattened(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_feature), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.create_feature( + parent="parent_value", + resource=feature.Feature(name="name_value"), + feature_id="feature_id_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0].parent == "parent_value" + assert args[0].resource == feature.Feature(name="name_value") + assert args[0].feature_id == "feature_id_value" + + +def test_create_feature_flattened_error(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.create_feature( + service.CreateFeatureRequest(), + parent="parent_value", + resource=feature.Feature(name="name_value"), + feature_id="feature_id_value", + ) + + +@pytest.mark.asyncio +async def test_create_feature_flattened_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_feature), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.create_feature( + parent="parent_value", + resource=feature.Feature(name="name_value"), + feature_id="feature_id_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0].parent == "parent_value" + assert args[0].resource == feature.Feature(name="name_value") + assert args[0].feature_id == "feature_id_value" + + +@pytest.mark.asyncio +async def test_create_feature_flattened_error_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.create_feature( + service.CreateFeatureRequest(), + parent="parent_value", + resource=feature.Feature(name="name_value"), + feature_id="feature_id_value", + ) + + +def test_delete_membership( + transport: str = "grpc", request_type=service.DeleteMembershipRequest +): + client = GkeHubClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_membership), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.delete_membership(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == service.DeleteMembershipRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_delete_membership_from_dict(): + test_delete_membership(request_type=dict) + + +def test_delete_membership_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GkeHubClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_membership), "__call__" + ) as call: + client.delete_membership() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == service.DeleteMembershipRequest() + + +@pytest.mark.asyncio +async def test_delete_membership_async( + transport: str = "grpc_asyncio", request_type=service.DeleteMembershipRequest +): + client = GkeHubAsyncClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_membership), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.delete_membership(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == service.DeleteMembershipRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +@pytest.mark.asyncio +async def test_delete_membership_async_from_dict(): + await test_delete_membership_async(request_type=dict) + + +def test_delete_membership_field_headers(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.DeleteMembershipRequest() + + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_membership), "__call__" + ) as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.delete_membership(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_delete_membership_field_headers_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.DeleteMembershipRequest() + + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_membership), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.delete_membership(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +def test_delete_membership_flattened(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_membership), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.delete_membership(name="name_value",) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0].name == "name_value" + + +def test_delete_membership_flattened_error(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.delete_membership( + service.DeleteMembershipRequest(), name="name_value", + ) + + +@pytest.mark.asyncio +async def test_delete_membership_flattened_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_membership), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.delete_membership(name="name_value",) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0].name == "name_value" + + +@pytest.mark.asyncio +async def test_delete_membership_flattened_error_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.delete_membership( + service.DeleteMembershipRequest(), name="name_value", + ) + + +def test_delete_feature( + transport: str = "grpc", request_type=service.DeleteFeatureRequest +): + client = GkeHubClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_feature), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.delete_feature(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == service.DeleteFeatureRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_delete_feature_from_dict(): + test_delete_feature(request_type=dict) + + +def test_delete_feature_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GkeHubClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_feature), "__call__") as call: + client.delete_feature() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == service.DeleteFeatureRequest() + + +@pytest.mark.asyncio +async def test_delete_feature_async( + transport: str = "grpc_asyncio", request_type=service.DeleteFeatureRequest +): + client = GkeHubAsyncClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_feature), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.delete_feature(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == service.DeleteFeatureRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +@pytest.mark.asyncio +async def test_delete_feature_async_from_dict(): + await test_delete_feature_async(request_type=dict) + + +def test_delete_feature_field_headers(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.DeleteFeatureRequest() + + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_feature), "__call__") as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.delete_feature(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_delete_feature_field_headers_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.DeleteFeatureRequest() + + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_feature), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.delete_feature(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +def test_delete_feature_flattened(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_feature), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.delete_feature(name="name_value",) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0].name == "name_value" + + +def test_delete_feature_flattened_error(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.delete_feature( + service.DeleteFeatureRequest(), name="name_value", + ) + + +@pytest.mark.asyncio +async def test_delete_feature_flattened_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_feature), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.delete_feature(name="name_value",) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0].name == "name_value" + + +@pytest.mark.asyncio +async def test_delete_feature_flattened_error_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.delete_feature( + service.DeleteFeatureRequest(), name="name_value", + ) + + +def test_update_membership( + transport: str = "grpc", request_type=service.UpdateMembershipRequest +): + client = GkeHubClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_membership), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.update_membership(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == service.UpdateMembershipRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_update_membership_from_dict(): + test_update_membership(request_type=dict) + + +def test_update_membership_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GkeHubClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_membership), "__call__" + ) as call: + client.update_membership() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == service.UpdateMembershipRequest() + + +@pytest.mark.asyncio +async def test_update_membership_async( + transport: str = "grpc_asyncio", request_type=service.UpdateMembershipRequest +): + client = GkeHubAsyncClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_membership), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.update_membership(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == service.UpdateMembershipRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +@pytest.mark.asyncio +async def test_update_membership_async_from_dict(): + await test_update_membership_async(request_type=dict) + + +def test_update_membership_field_headers(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.UpdateMembershipRequest() + + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_membership), "__call__" + ) as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.update_membership(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_update_membership_field_headers_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.UpdateMembershipRequest() + + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_membership), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.update_membership(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +def test_update_membership_flattened(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_membership), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.update_membership( + name="name_value", + resource=membership.Membership( + endpoint=membership.MembershipEndpoint( + gke_cluster=membership.GkeCluster( + resource_link="resource_link_value" + ) + ) + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0].name == "name_value" + assert args[0].resource == membership.Membership( + endpoint=membership.MembershipEndpoint( + gke_cluster=membership.GkeCluster(resource_link="resource_link_value") + ) + ) + assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + + +def test_update_membership_flattened_error(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_membership( + service.UpdateMembershipRequest(), + name="name_value", + resource=membership.Membership( + endpoint=membership.MembershipEndpoint( + gke_cluster=membership.GkeCluster( + resource_link="resource_link_value" + ) + ) + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.asyncio +async def test_update_membership_flattened_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_membership), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.update_membership( + name="name_value", + resource=membership.Membership( + endpoint=membership.MembershipEndpoint( + gke_cluster=membership.GkeCluster( + resource_link="resource_link_value" + ) + ) + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0].name == "name_value" + assert args[0].resource == membership.Membership( + endpoint=membership.MembershipEndpoint( + gke_cluster=membership.GkeCluster(resource_link="resource_link_value") + ) + ) + assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + + +@pytest.mark.asyncio +async def test_update_membership_flattened_error_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.update_membership( + service.UpdateMembershipRequest(), + name="name_value", + resource=membership.Membership( + endpoint=membership.MembershipEndpoint( + gke_cluster=membership.GkeCluster( + resource_link="resource_link_value" + ) + ) + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +def test_update_feature( + transport: str = "grpc", request_type=service.UpdateFeatureRequest +): + client = GkeHubClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_feature), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.update_feature(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == service.UpdateFeatureRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_update_feature_from_dict(): + test_update_feature(request_type=dict) + + +def test_update_feature_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GkeHubClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_feature), "__call__") as call: + client.update_feature() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == service.UpdateFeatureRequest() + + +@pytest.mark.asyncio +async def test_update_feature_async( + transport: str = "grpc_asyncio", request_type=service.UpdateFeatureRequest +): + client = GkeHubAsyncClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_feature), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.update_feature(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == service.UpdateFeatureRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +@pytest.mark.asyncio +async def test_update_feature_async_from_dict(): + await test_update_feature_async(request_type=dict) + + +def test_update_feature_field_headers(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.UpdateFeatureRequest() + + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_feature), "__call__") as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.update_feature(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_update_feature_field_headers_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.UpdateFeatureRequest() + + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_feature), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.update_feature(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +def test_update_feature_flattened(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_feature), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.update_feature( + name="name_value", + resource=feature.Feature(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0].name == "name_value" + assert args[0].resource == feature.Feature(name="name_value") + assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + + +def test_update_feature_flattened_error(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_feature( + service.UpdateFeatureRequest(), + name="name_value", + resource=feature.Feature(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.asyncio +async def test_update_feature_flattened_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_feature), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.update_feature( + name="name_value", + resource=feature.Feature(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0].name == "name_value" + assert args[0].resource == feature.Feature(name="name_value") + assert args[0].update_mask == field_mask_pb2.FieldMask(paths=["paths_value"]) + + +@pytest.mark.asyncio +async def test_update_feature_flattened_error_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.update_feature( + service.UpdateFeatureRequest(), + name="name_value", + resource=feature.Feature(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +def test_generate_connect_manifest( + transport: str = "grpc", request_type=service.GenerateConnectManifestRequest +): + client = GkeHubClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.generate_connect_manifest), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = service.GenerateConnectManifestResponse() + response = client.generate_connect_manifest(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == service.GenerateConnectManifestRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, service.GenerateConnectManifestResponse) + + +def test_generate_connect_manifest_from_dict(): + test_generate_connect_manifest(request_type=dict) + + +def test_generate_connect_manifest_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GkeHubClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.generate_connect_manifest), "__call__" + ) as call: + client.generate_connect_manifest() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == service.GenerateConnectManifestRequest() + + +@pytest.mark.asyncio +async def test_generate_connect_manifest_async( + transport: str = "grpc_asyncio", request_type=service.GenerateConnectManifestRequest +): + client = GkeHubAsyncClient( + credentials=ga_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 = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.generate_connect_manifest), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + service.GenerateConnectManifestResponse() + ) + response = await client.generate_connect_manifest(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == service.GenerateConnectManifestRequest() + + # Establish that the response is the type that we expect. + assert isinstance(response, service.GenerateConnectManifestResponse) + + +@pytest.mark.asyncio +async def test_generate_connect_manifest_async_from_dict(): + await test_generate_connect_manifest_async(request_type=dict) + + +def test_generate_connect_manifest_field_headers(): + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.GenerateConnectManifestRequest() + + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.generate_connect_manifest), "__call__" + ) as call: + call.return_value = service.GenerateConnectManifestResponse() + client.generate_connect_manifest(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_generate_connect_manifest_field_headers_async(): + client = GkeHubAsyncClient(credentials=ga_credentials.AnonymousCredentials(),) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = service.GenerateConnectManifestRequest() + + request.name = "name/value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.generate_connect_manifest), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + service.GenerateConnectManifestResponse() + ) + await client.generate_connect_manifest(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ("x-goog-request-params", "name=name/value",) in kw["metadata"] + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.GkeHubGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GkeHubClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport, + ) + + # It is an error to provide a credentials file and a transport instance. + transport = transports.GkeHubGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GkeHubClient( + client_options={"credentials_file": "credentials.json"}, + transport=transport, + ) + + # It is an error to provide scopes and a transport instance. + transport = transports.GkeHubGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GkeHubClient( + client_options={"scopes": ["1", "2"]}, transport=transport, + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.GkeHubGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + client = GkeHubClient(transport=transport) + assert client.transport is transport + + +def test_transport_get_channel(): + # A client may be instantiated with a custom transport instance. + transport = transports.GkeHubGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + transport = transports.GkeHubGrpcAsyncIOTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + +@pytest.mark.parametrize( + "transport_class", + [transports.GkeHubGrpcTransport, transports.GkeHubGrpcAsyncIOTransport,], +) +def test_transport_adc(transport_class): + # Test default credentials are used if not provided. + with mock.patch.object(google.auth, "default") as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class() + adc.assert_called_once() + + +def test_transport_grpc_default(): + # A client should use the gRPC transport by default. + client = GkeHubClient(credentials=ga_credentials.AnonymousCredentials(),) + assert isinstance(client.transport, transports.GkeHubGrpcTransport,) + + +def test_gke_hub_base_transport_error(): + # Passing both a credentials object and credentials_file should raise an error + with pytest.raises(core_exceptions.DuplicateCredentialArgs): + transport = transports.GkeHubTransport( + credentials=ga_credentials.AnonymousCredentials(), + credentials_file="credentials.json", + ) + + +def test_gke_hub_base_transport(): + # Instantiate the base transport. + with mock.patch( + "google.cloud.gkehub_v1.services.gke_hub.transports.GkeHubTransport.__init__" + ) as Transport: + Transport.return_value = None + transport = transports.GkeHubTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ( + "list_memberships", + "list_features", + "get_membership", + "get_feature", + "create_membership", + "create_feature", + "delete_membership", + "delete_feature", + "update_membership", + "update_feature", + "generate_connect_manifest", + ) + for method in methods: + with pytest.raises(NotImplementedError): + getattr(transport, method)(request=object()) + + # Additionally, the LRO client (a property) should + # also raise NotImplementedError + with pytest.raises(NotImplementedError): + transport.operations_client + + +@requires_google_auth_gte_1_25_0 +def test_gke_hub_base_transport_with_credentials_file(): + # Instantiate the base transport with a credentials file + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch( + "google.cloud.gkehub_v1.services.gke_hub.transports.GkeHubTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.GkeHubTransport( + credentials_file="credentials.json", quota_project_id="octopus", + ) + load_creds.assert_called_once_with( + "credentials.json", + scopes=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", + ) + + +@requires_google_auth_lt_1_25_0 +def test_gke_hub_base_transport_with_credentials_file_old_google_auth(): + # Instantiate the base transport with a credentials file + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch( + "google.cloud.gkehub_v1.services.gke_hub.transports.GkeHubTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.GkeHubTransport( + credentials_file="credentials.json", quota_project_id="octopus", + ) + load_creds.assert_called_once_with( + "credentials.json", + scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", + ) + + +def test_gke_hub_base_transport_with_adc(): + # Test the default credentials are used if credentials and credentials_file are None. + with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( + "google.cloud.gkehub_v1.services.gke_hub.transports.GkeHubTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.GkeHubTransport() + adc.assert_called_once() + + +@requires_google_auth_gte_1_25_0 +def test_gke_hub_auth_adc(): + # If no credentials are provided, we should use ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + GkeHubClient() + adc.assert_called_once_with( + scopes=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id=None, + ) + + +@requires_google_auth_lt_1_25_0 +def test_gke_hub_auth_adc_old_google_auth(): + # If no credentials are provided, we should use ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + GkeHubClient() + adc.assert_called_once_with( + scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id=None, + ) + + +@pytest.mark.parametrize( + "transport_class", + [transports.GkeHubGrpcTransport, transports.GkeHubGrpcAsyncIOTransport,], +) +@requires_google_auth_gte_1_25_0 +def test_gke_hub_transport_auth_adc(transport_class): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + adc.assert_called_once_with( + scopes=["1", "2"], + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", + ) + + +@pytest.mark.parametrize( + "transport_class", + [transports.GkeHubGrpcTransport, transports.GkeHubGrpcAsyncIOTransport,], +) +@requires_google_auth_lt_1_25_0 +def test_gke_hub_transport_auth_adc_old_google_auth(transport_class): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class(quota_project_id="octopus") + adc.assert_called_once_with( + scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", + ) + + +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.GkeHubGrpcTransport, grpc_helpers), + (transports.GkeHubGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +def test_gke_hub_transport_create_channel(transport_class, grpc_helpers): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + + create_channel.assert_called_with( + "gkehub.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + scopes=["1", "2"], + default_host="gkehub.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class", + [transports.GkeHubGrpcTransport, transports.GkeHubGrpcAsyncIOTransport], +) +def test_gke_hub_grpc_transport_client_cert_source_for_mtls(transport_class): + cred = ga_credentials.AnonymousCredentials() + + # Check ssl_channel_credentials is used if provided. + with mock.patch.object(transport_class, "create_channel") as mock_create_channel: + mock_ssl_channel_creds = mock.Mock() + transport_class( + host="squid.clam.whelk", + credentials=cred, + ssl_channel_credentials=mock_ssl_channel_creds, + ) + mock_create_channel.assert_called_once_with( + "squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=None, + ssl_credentials=mock_ssl_channel_creds, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Check if ssl_channel_credentials is not provided, then client_cert_source_for_mtls + # is used. + with mock.patch.object(transport_class, "create_channel", return_value=mock.Mock()): + with mock.patch("grpc.ssl_channel_credentials") as mock_ssl_cred: + transport_class( + credentials=cred, + client_cert_source_for_mtls=client_cert_source_callback, + ) + expected_cert, expected_key = client_cert_source_callback() + mock_ssl_cred.assert_called_once_with( + certificate_chain=expected_cert, private_key=expected_key + ) + + +def test_gke_hub_host_no_port(): + client = GkeHubClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="gkehub.googleapis.com" + ), + ) + assert client.transport._host == "gkehub.googleapis.com:443" + + +def test_gke_hub_host_with_port(): + client = GkeHubClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="gkehub.googleapis.com:8000" + ), + ) + assert client.transport._host == "gkehub.googleapis.com:8000" + + +def test_gke_hub_grpc_transport_channel(): + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.GkeHubGrpcTransport( + host="squid.clam.whelk", channel=channel, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + assert transport._ssl_channel_credentials == None + + +def test_gke_hub_grpc_asyncio_transport_channel(): + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.GkeHubGrpcAsyncIOTransport( + host="squid.clam.whelk", channel=channel, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + assert transport._ssl_channel_credentials == None + + +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. +@pytest.mark.parametrize( + "transport_class", + [transports.GkeHubGrpcTransport, transports.GkeHubGrpcAsyncIOTransport], +) +def test_gke_hub_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" + ) 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 = ga_credentials.AnonymousCredentials() + with pytest.warns(DeprecationWarning): + with mock.patch.object(google.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=None, + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == mock_ssl_cred + + +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. +@pytest.mark.parametrize( + "transport_class", + [transports.GkeHubGrpcTransport, transports.GkeHubGrpcAsyncIOTransport], +) +def test_gke_hub_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), + ): + with mock.patch.object( + transport_class, "create_channel" + ) 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=None, + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + assert transport.grpc_channel == mock_grpc_channel + + +def test_gke_hub_grpc_lro_client(): + client = GkeHubClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc", + ) + transport = client.transport + + # Ensure that we have a api-core operations client. + assert isinstance(transport.operations_client, operations_v1.OperationsClient,) + + # Ensure that subsequent calls to the property send the exact same object. + assert transport.operations_client is transport.operations_client + + +def test_gke_hub_grpc_lro_async_client(): + client = GkeHubAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc_asyncio", + ) + transport = client.transport + + # Ensure that we have a api-core operations client. + assert isinstance(transport.operations_client, operations_v1.OperationsAsyncClient,) + + # Ensure that subsequent calls to the property send the exact same object. + assert transport.operations_client is transport.operations_client + + +def test_feature_path(): + project = "squid" + location = "clam" + feature = "whelk" + expected = "projects/{project}/locations/{location}/features/{feature}".format( + project=project, location=location, feature=feature, + ) + actual = GkeHubClient.feature_path(project, location, feature) + assert expected == actual + + +def test_parse_feature_path(): + expected = { + "project": "octopus", + "location": "oyster", + "feature": "nudibranch", + } + path = GkeHubClient.feature_path(**expected) + + # Check that the path construction is reversible. + actual = GkeHubClient.parse_feature_path(path) + assert expected == actual + + +def test_membership_path(): + project = "cuttlefish" + location = "mussel" + membership = "winkle" + expected = "projects/{project}/locations/{location}/memberships/{membership}".format( + project=project, location=location, membership=membership, + ) + actual = GkeHubClient.membership_path(project, location, membership) + assert expected == actual + + +def test_parse_membership_path(): + expected = { + "project": "nautilus", + "location": "scallop", + "membership": "abalone", + } + path = GkeHubClient.membership_path(**expected) + + # Check that the path construction is reversible. + actual = GkeHubClient.parse_membership_path(path) + assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "squid" + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = GkeHubClient.common_billing_account_path(billing_account) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "clam", + } + path = GkeHubClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = GkeHubClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "whelk" + expected = "folders/{folder}".format(folder=folder,) + actual = GkeHubClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "octopus", + } + path = GkeHubClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = GkeHubClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "oyster" + expected = "organizations/{organization}".format(organization=organization,) + actual = GkeHubClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "nudibranch", + } + path = GkeHubClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = GkeHubClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "cuttlefish" + expected = "projects/{project}".format(project=project,) + actual = GkeHubClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "mussel", + } + path = GkeHubClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = GkeHubClient.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 = GkeHubClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "scallop", + "location": "abalone", + } + path = GkeHubClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = GkeHubClient.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.GkeHubTransport, "_prep_wrapped_messages" + ) as prep: + client = GkeHubClient( + credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.GkeHubTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = GkeHubClient.get_transport_class() + transport = transport_class( + credentials=ga_credentials.AnonymousCredentials(), client_info=client_info, + ) + prep.assert_called_once_with(client_info) diff --git a/tests/unit/gapic/gkehub_v1beta1/test_gke_hub_membership_service.py b/tests/unit/gapic/gkehub_v1beta1/test_gke_hub_membership_service.py index f6b3ec4..e6e73db 100644 --- a/tests/unit/gapic/gkehub_v1beta1/test_gke_hub_membership_service.py +++ b/tests/unit/gapic/gkehub_v1beta1/test_gke_hub_membership_service.py @@ -2538,7 +2538,7 @@ def test_gke_hub_membership_service_grpc_transport_client_cert_source_for_mtls( "squid.clam.whelk:443", credentials=cred, credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), + scopes=None, ssl_credentials=mock_ssl_channel_creds, quota_project_id=None, options=[ @@ -2647,7 +2647,7 @@ def test_gke_hub_membership_service_transport_channel_mtls_with_client_cert_sour "mtls.squid.clam.whelk:443", credentials=cred, credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), + scopes=None, ssl_credentials=mock_ssl_cred, quota_project_id=None, options=[ @@ -2694,7 +2694,7 @@ def test_gke_hub_membership_service_transport_channel_mtls_with_adc(transport_cl "mtls.squid.clam.whelk:443", credentials=mock_cred, credentials_file=None, - scopes=("https://www.googleapis.com/auth/cloud-platform",), + scopes=None, ssl_credentials=mock_ssl_cred, quota_project_id=None, options=[ diff --git a/tests/unit/gapic/multiclusteringress_v1/__init__.py b/tests/unit/gapic/multiclusteringress_v1/__init__.py new file mode 100644 index 0000000..4de6597 --- /dev/null +++ b/tests/unit/gapic/multiclusteringress_v1/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# From 100f72e7181f4faeb04a76e106888ffd766ed9ef Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Fri, 2 Jul 2021 14:48:25 +0000 Subject: [PATCH 08/15] fix(v1beta1): disable always_use_jwt_access (#52) Committer: @busunkim96 PiperOrigin-RevId: 382142900 Source-Link: https://github.com/googleapis/googleapis/commit/513440fda515f3c799c22a30e3906dcda325004e Source-Link: https://github.com/googleapis/googleapis-gen/commit/7b1e2c31233f79a704ec21ca410bf661d6bc68d0 --- .../transports/grpc.py | 5 ++++- .../transports/grpc_asyncio.py | 5 ++++- .../test_gke_hub_membership_service.py | 20 ++++++++++++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/grpc.py b/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/grpc.py index dec0aa3..1c0b01f 100644 --- a/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/grpc.py +++ b/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/grpc.py @@ -61,6 +61,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id: Optional[str] = None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -101,6 +102,8 @@ def __init__( 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. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport @@ -154,7 +157,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, - always_use_jwt_access=True, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: diff --git a/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/grpc_asyncio.py b/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/grpc_asyncio.py index 5102138..3726600 100644 --- a/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/grpc_asyncio.py +++ b/google/cloud/gkehub_v1beta1/services/gke_hub_membership_service/transports/grpc_asyncio.py @@ -107,6 +107,7 @@ def __init__( client_cert_source_for_mtls: Callable[[], Tuple[bytes, bytes]] = None, quota_project_id=None, client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, ) -> None: """Instantiate the transport. @@ -148,6 +149,8 @@ def __init__( 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. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. Raises: google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport @@ -200,7 +203,7 @@ def __init__( scopes=scopes, quota_project_id=quota_project_id, client_info=client_info, - always_use_jwt_access=True, + always_use_jwt_access=always_use_jwt_access, ) if not self._grpc_channel: diff --git a/tests/unit/gapic/gkehub_v1beta1/test_gke_hub_membership_service.py b/tests/unit/gapic/gkehub_v1beta1/test_gke_hub_membership_service.py index e6e73db..39711b9 100644 --- a/tests/unit/gapic/gkehub_v1beta1/test_gke_hub_membership_service.py +++ b/tests/unit/gapic/gkehub_v1beta1/test_gke_hub_membership_service.py @@ -139,7 +139,25 @@ def test_gke_hub_membership_service_client_service_account_always_use_jwt(client ) as use_jwt: creds = service_account.Credentials(None, None, None) client = client_class(credentials=creds) - use_jwt.assert_called_with(True) + use_jwt.assert_not_called() + + +@pytest.mark.parametrize( + "transport_class,transport_name", + [ + (transports.GkeHubMembershipServiceGrpcTransport, "grpc"), + (transports.GkeHubMembershipServiceGrpcAsyncIOTransport, "grpc_asyncio"), + ], +) +def test_gke_hub_membership_service_client_service_account_always_use_jwt_true( + transport_class, transport_name +): + with mock.patch.object( + service_account.Credentials, "with_always_use_jwt_access", create=True + ) as use_jwt: + creds = service_account.Credentials(None, None, None) + transport = transport_class(credentials=creds, always_use_jwt_access=True) + use_jwt.assert_called_once_with(True) @pytest.mark.parametrize( From 32b0bd722a2cbceac97ebef6a55b5ecd7dd0c3e5 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Wed, 14 Jul 2021 15:56:33 +0000 Subject: [PATCH 09/15] build(python): exit with success status if no samples found (#53) Source-Link: https://github.com/googleapis/synthtool/commit/53ea3896a52f87c758e79b5a19fa338c83925a98 Post-Processor: gcr.io/repo-automation-bots/owlbot-python:latest@sha256:e1793a23ae0ee9aafb2e3a53b564a351f74790dbe3c2d75f8fc3b8c43e5c036c --- .github/.OwlBot.lock.yaml | 2 +- .kokoro/test-samples-impl.sh | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index e2b39f9..a5d3697 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/repo-automation-bots/owlbot-python:latest - digest: sha256:99d90d097e4a4710cc8658ee0b5b963f4426d0e424819787c3ac1405c9a26719 + digest: sha256:e1793a23ae0ee9aafb2e3a53b564a351f74790dbe3c2d75f8fc3b8c43e5c036c diff --git a/.kokoro/test-samples-impl.sh b/.kokoro/test-samples-impl.sh index cf5de74..311a8d5 100755 --- a/.kokoro/test-samples-impl.sh +++ b/.kokoro/test-samples-impl.sh @@ -20,9 +20,9 @@ set -eo pipefail # Enables `**` to include files nested inside sub-folders shopt -s globstar -# Exit early if samples directory doesn't exist -if [ ! -d "./samples" ]; then - echo "No tests run. `./samples` not found" +# Exit early if samples don't exist +if ! find samples -name 'requirements.txt' | grep -q .; then + echo "No tests run. './samples/**/requirements.txt' not found" exit 0 fi From f5d5b099779805a9bc2df86635a36349d386e4c4 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Wed, 14 Jul 2021 18:06:24 +0000 Subject: [PATCH 10/15] build(python): remove python 3.7 from kokoro Dockerfile (#54) Source-Link: https://github.com/googleapis/synthtool/commit/e44dc0c742b1230887a73552357e0c18dcc30b92 Post-Processor: gcr.io/repo-automation-bots/owlbot-python:latest@sha256:5ff7446edeaede81c3ed58b23a4e76a5403fba1350ce28478045657303b6479d --- .github/.OwlBot.lock.yaml | 2 +- .kokoro/docker/docs/Dockerfile | 35 ++------------------- .kokoro/docker/docs/fetch_gpg_keys.sh | 45 --------------------------- 3 files changed, 3 insertions(+), 79 deletions(-) delete mode 100755 .kokoro/docker/docs/fetch_gpg_keys.sh diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index a5d3697..cb06536 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/repo-automation-bots/owlbot-python:latest - digest: sha256:e1793a23ae0ee9aafb2e3a53b564a351f74790dbe3c2d75f8fc3b8c43e5c036c + digest: sha256:5ff7446edeaede81c3ed58b23a4e76a5403fba1350ce28478045657303b6479d diff --git a/.kokoro/docker/docs/Dockerfile b/.kokoro/docker/docs/Dockerfile index 412b0b5..4e1b1fb 100644 --- a/.kokoro/docker/docs/Dockerfile +++ b/.kokoro/docker/docs/Dockerfile @@ -40,6 +40,7 @@ RUN apt-get update \ libssl-dev \ libsqlite3-dev \ portaudio19-dev \ + python3-distutils \ redis-server \ software-properties-common \ ssh \ @@ -59,40 +60,8 @@ RUN apt-get update \ && rm -rf /var/lib/apt/lists/* \ && rm -f /var/cache/apt/archives/*.deb - -COPY fetch_gpg_keys.sh /tmp -# Install the desired versions of Python. -RUN set -ex \ - && export GNUPGHOME="$(mktemp -d)" \ - && echo "disable-ipv6" >> "${GNUPGHOME}/dirmngr.conf" \ - && /tmp/fetch_gpg_keys.sh \ - && for PYTHON_VERSION in 3.7.8 3.8.5; do \ - wget --no-check-certificate -O python-${PYTHON_VERSION}.tar.xz "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz" \ - && wget --no-check-certificate -O python-${PYTHON_VERSION}.tar.xz.asc "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc" \ - && gpg --batch --verify python-${PYTHON_VERSION}.tar.xz.asc python-${PYTHON_VERSION}.tar.xz \ - && rm -r python-${PYTHON_VERSION}.tar.xz.asc \ - && mkdir -p /usr/src/python-${PYTHON_VERSION} \ - && tar -xJC /usr/src/python-${PYTHON_VERSION} --strip-components=1 -f python-${PYTHON_VERSION}.tar.xz \ - && rm python-${PYTHON_VERSION}.tar.xz \ - && cd /usr/src/python-${PYTHON_VERSION} \ - && ./configure \ - --enable-shared \ - # This works only on Python 2.7 and throws a warning on every other - # version, but seems otherwise harmless. - --enable-unicode=ucs4 \ - --with-system-ffi \ - --without-ensurepip \ - && make -j$(nproc) \ - && make install \ - && ldconfig \ - ; done \ - && rm -rf "${GNUPGHOME}" \ - && rm -rf /usr/src/python* \ - && rm -rf ~/.cache/ - RUN wget -O /tmp/get-pip.py 'https://bootstrap.pypa.io/get-pip.py' \ - && python3.7 /tmp/get-pip.py \ && python3.8 /tmp/get-pip.py \ && rm /tmp/get-pip.py -CMD ["python3.7"] +CMD ["python3.8"] diff --git a/.kokoro/docker/docs/fetch_gpg_keys.sh b/.kokoro/docker/docs/fetch_gpg_keys.sh deleted file mode 100755 index d653dd8..0000000 --- a/.kokoro/docker/docs/fetch_gpg_keys.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/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. - -# A script to fetch gpg keys with retry. -# Avoid jinja parsing the file. -# - -function retry { - if [[ "${#}" -le 1 ]]; then - echo "Usage: ${0} retry_count commands.." - exit 1 - fi - local retries=${1} - local command="${@:2}" - until [[ "${retries}" -le 0 ]]; do - $command && return 0 - if [[ $? -ne 0 ]]; then - echo "command failed, retrying" - ((retries--)) - fi - done - return 1 -} - -# 3.6.9, 3.7.5 (Ned Deily) -retry 3 gpg --keyserver ha.pool.sks-keyservers.net --recv-keys \ - 0D96DF4D4110E5C43FBFB17F2D347EA6AA65421D - -# 3.8.0 (Łukasz Langa) -retry 3 gpg --keyserver ha.pool.sks-keyservers.net --recv-keys \ - E3FF2839C048B25C084DEBE9B26995E310250568 - -# From 703536465a766c452a8c27a6ee951dec35cf3c4f Mon Sep 17 00:00:00 2001 From: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> Date: Tue, 20 Jul 2021 03:46:12 -0600 Subject: [PATCH 11/15] fix(deps): pin 'google-{api,cloud}-core', 'google-auth' to allow 2.x versions (#55) Expand pins on library dependencies in preparation for these dependencies taking a new major version. See https://github.com/googleapis/google-cloud-python/issues/10566. --- setup.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 080e576..cc38696 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,10 @@ release_status = "Development Status :: 4 - Beta" url = "https://github.com/googleapis/python-gke-hub" dependencies = [ - "google-api-core[grpc] >= 1.26.0, <2.0.0dev", + # NOTE: Maintainers, please do not require google-api-core>=2.x.x + # Until this issue is closed + # https://github.com/googleapis/google-cloud-python/issues/10566 + "google-api-core[grpc] >= 1.26.0, <3.0.0dev", "proto-plus >= 1.4.0", "packaging >= 14.3", ] From b08cf7e5f2dbb1f3615f5b652c2d69f991d8aa69 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Thu, 22 Jul 2021 14:04:11 +0000 Subject: [PATCH 12/15] feat: add Samples section to CONTRIBUTING.rst (#56) Source-Link: https://github.com/googleapis/synthtool/commit/52e4e46eff2a0b70e3ff5506a02929d089d077d4 Post-Processor: gcr.io/repo-automation-bots/owlbot-python:latest@sha256:6186535cbdbf6b9fe61f00294929221d060634dae4a0795c1cefdbc995b2d605 --- .github/.OwlBot.lock.yaml | 2 +- CONTRIBUTING.rst | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index cb06536..d57f742 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/repo-automation-bots/owlbot-python:latest - digest: sha256:5ff7446edeaede81c3ed58b23a4e76a5403fba1350ce28478045657303b6479d + digest: sha256:6186535cbdbf6b9fe61f00294929221d060634dae4a0795c1cefdbc995b2d605 diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 1ddbdb7..e5eb2e5 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -177,6 +177,30 @@ Build the docs via: $ nox -s docs +************************* +Samples and code snippets +************************* + +Code samples and snippets live in the `samples/` catalogue. Feel free to +provide more examples, but make sure to write tests for those examples. +Each folder containing example code requires its own `noxfile.py` script +which automates testing. If you decide to create a new folder, you can +base it on the `samples/snippets` folder (providing `noxfile.py` and +the requirements files). + +The tests will run against a real Google Cloud Project, so you should +configure them just like the System Tests. + +- To run sample tests, you can execute:: + + # Run all tests in a folder + $ cd samples/snippets + $ nox -s py-3.8 + + # Run a single sample test + $ cd samples/snippets + $ nox -s py-3.8 -- -k + ******************************************** Note About ``README`` as it pertains to PyPI ******************************************** From 6c54ae188a008dc7f478655ee16f3b82aebc4eca Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Fri, 23 Jul 2021 15:33:52 +0000 Subject: [PATCH 13/15] chore: fix kokoro config for samples (#57) Source-Link: https://github.com/googleapis/synthtool/commit/dd05f9d12f134871c9e45282349c9856fbebecdd Post-Processor: gcr.io/repo-automation-bots/owlbot-python:latest@sha256:aea14a583128771ae8aefa364e1652f3c56070168ef31beb203534222d842b8b --- .github/.OwlBot.lock.yaml | 2 +- .kokoro/samples/python3.6/periodic-head.cfg | 2 +- .kokoro/samples/python3.7/periodic-head.cfg | 2 +- .kokoro/samples/python3.8/periodic-head.cfg | 2 +- .kokoro/samples/python3.9/periodic-head.cfg | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index d57f742..9ee60f7 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -1,3 +1,3 @@ docker: image: gcr.io/repo-automation-bots/owlbot-python:latest - digest: sha256:6186535cbdbf6b9fe61f00294929221d060634dae4a0795c1cefdbc995b2d605 + digest: sha256:aea14a583128771ae8aefa364e1652f3c56070168ef31beb203534222d842b8b diff --git a/.kokoro/samples/python3.6/periodic-head.cfg b/.kokoro/samples/python3.6/periodic-head.cfg index f9cfcd3..6d8a99d 100644 --- a/.kokoro/samples/python3.6/periodic-head.cfg +++ b/.kokoro/samples/python3.6/periodic-head.cfg @@ -7,5 +7,5 @@ env_vars: { env_vars: { key: "TRAMPOLINE_BUILD_FILE" - value: "github/python-pubsub/.kokoro/test-samples-against-head.sh" + value: "github/python-gke-hub/.kokoro/test-samples-against-head.sh" } diff --git a/.kokoro/samples/python3.7/periodic-head.cfg b/.kokoro/samples/python3.7/periodic-head.cfg index f9cfcd3..6d8a99d 100644 --- a/.kokoro/samples/python3.7/periodic-head.cfg +++ b/.kokoro/samples/python3.7/periodic-head.cfg @@ -7,5 +7,5 @@ env_vars: { env_vars: { key: "TRAMPOLINE_BUILD_FILE" - value: "github/python-pubsub/.kokoro/test-samples-against-head.sh" + value: "github/python-gke-hub/.kokoro/test-samples-against-head.sh" } diff --git a/.kokoro/samples/python3.8/periodic-head.cfg b/.kokoro/samples/python3.8/periodic-head.cfg index f9cfcd3..6d8a99d 100644 --- a/.kokoro/samples/python3.8/periodic-head.cfg +++ b/.kokoro/samples/python3.8/periodic-head.cfg @@ -7,5 +7,5 @@ env_vars: { env_vars: { key: "TRAMPOLINE_BUILD_FILE" - value: "github/python-pubsub/.kokoro/test-samples-against-head.sh" + value: "github/python-gke-hub/.kokoro/test-samples-against-head.sh" } diff --git a/.kokoro/samples/python3.9/periodic-head.cfg b/.kokoro/samples/python3.9/periodic-head.cfg index f9cfcd3..6d8a99d 100644 --- a/.kokoro/samples/python3.9/periodic-head.cfg +++ b/.kokoro/samples/python3.9/periodic-head.cfg @@ -7,5 +7,5 @@ env_vars: { env_vars: { key: "TRAMPOLINE_BUILD_FILE" - value: "github/python-pubsub/.kokoro/test-samples-against-head.sh" + value: "github/python-gke-hub/.kokoro/test-samples-against-head.sh" } From 66f14c93978f97f8180ca8f0a02856d4d633a2bf Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Sat, 24 Jul 2021 10:18:35 +0000 Subject: [PATCH 14/15] fix: enable self signed jwt for grpc (#58) PiperOrigin-RevId: 386504689 Source-Link: https://github.com/googleapis/googleapis/commit/762094a99ac6e03a17516b13dfbef37927267a70 Source-Link: https://github.com/googleapis/googleapis-gen/commit/6bfc480e1a161d5de121c2bcc3745885d33b265a --- .../gkehub_v1/services/gke_hub/client.py | 4 +++ tests/unit/gapic/gkehub_v1/test_gke_hub.py | 31 +++++++++++-------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/google/cloud/gkehub_v1/services/gke_hub/client.py b/google/cloud/gkehub_v1/services/gke_hub/client.py index 59f4467..4a62ea0 100644 --- a/google/cloud/gkehub_v1/services/gke_hub/client.py +++ b/google/cloud/gkehub_v1/services/gke_hub/client.py @@ -379,6 +379,10 @@ def __init__( client_cert_source_for_mtls=client_cert_source_func, quota_project_id=client_options.quota_project_id, client_info=client_info, + always_use_jwt_access=( + Transport == type(self).get_transport_class("grpc") + or Transport == type(self).get_transport_class("grpc_asyncio") + ), ) def list_memberships( diff --git a/tests/unit/gapic/gkehub_v1/test_gke_hub.py b/tests/unit/gapic/gkehub_v1/test_gke_hub.py index 5eefc81..ab4a52a 100644 --- a/tests/unit/gapic/gkehub_v1/test_gke_hub.py +++ b/tests/unit/gapic/gkehub_v1/test_gke_hub.py @@ -118,16 +118,6 @@ def test_gke_hub_client_from_service_account_info(client_class): assert client.transport._host == "gkehub.googleapis.com:443" -@pytest.mark.parametrize("client_class", [GkeHubClient, GkeHubAsyncClient,]) -def test_gke_hub_client_service_account_always_use_jwt(client_class): - with mock.patch.object( - service_account.Credentials, "with_always_use_jwt_access", create=True - ) as use_jwt: - creds = service_account.Credentials(None, None, None) - client = client_class(credentials=creds) - use_jwt.assert_not_called() - - @pytest.mark.parametrize( "transport_class,transport_name", [ @@ -135,9 +125,7 @@ def test_gke_hub_client_service_account_always_use_jwt(client_class): (transports.GkeHubGrpcAsyncIOTransport, "grpc_asyncio"), ], ) -def test_gke_hub_client_service_account_always_use_jwt_true( - transport_class, transport_name -): +def test_gke_hub_client_service_account_always_use_jwt(transport_class, transport_name): with mock.patch.object( service_account.Credentials, "with_always_use_jwt_access", create=True ) as use_jwt: @@ -145,6 +133,13 @@ def test_gke_hub_client_service_account_always_use_jwt_true( transport = transport_class(credentials=creds, always_use_jwt_access=True) use_jwt.assert_called_once_with(True) + with mock.patch.object( + service_account.Credentials, "with_always_use_jwt_access", create=True + ) as use_jwt: + creds = service_account.Credentials(None, None, None) + transport = transport_class(credentials=creds, always_use_jwt_access=False) + use_jwt.assert_not_called() + @pytest.mark.parametrize("client_class", [GkeHubClient, GkeHubAsyncClient,]) def test_gke_hub_client_from_service_account_file(client_class): @@ -213,6 +208,7 @@ def test_gke_hub_client_client_options(client_class, transport_class, transport_ client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, ) # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is @@ -229,6 +225,7 @@ def test_gke_hub_client_client_options(client_class, transport_class, transport_ client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, ) # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is @@ -245,6 +242,7 @@ def test_gke_hub_client_client_options(client_class, transport_class, transport_ client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, ) # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has @@ -273,6 +271,7 @@ def test_gke_hub_client_client_options(client_class, transport_class, transport_ client_cert_source_for_mtls=None, quota_project_id="octopus", client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, ) @@ -335,6 +334,7 @@ def test_gke_hub_client_mtls_env_auto( client_cert_source_for_mtls=expected_client_cert_source, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, ) # Check the case ADC client cert is provided. Whether client cert is used depends on @@ -368,6 +368,7 @@ def test_gke_hub_client_mtls_env_auto( client_cert_source_for_mtls=expected_client_cert_source, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, ) # Check the case client_cert_source and ADC client cert are not provided. @@ -389,6 +390,7 @@ def test_gke_hub_client_mtls_env_auto( client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, ) @@ -415,6 +417,7 @@ def test_gke_hub_client_client_options_scopes( client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, ) @@ -441,6 +444,7 @@ def test_gke_hub_client_client_options_credentials_file( client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, ) @@ -458,6 +462,7 @@ def test_gke_hub_client_client_options_from_dict(): client_cert_source_for_mtls=None, quota_project_id=None, client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, ) From fcb849d3f55e89241e632426e6ac65d0a86bad58 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 27 Jul 2021 13:44:14 +0000 Subject: [PATCH 15/15] chore: release 0.2.0 (#46) :robot: I have created a release \*beep\* \*boop\* --- ## [0.2.0](https://www.github.com/googleapis/python-gke-hub/compare/v0.1.2...v0.2.0) (2021-07-24) ### Features * add always_use_jwt_access ([f11dcfd](https://www.github.com/googleapis/python-gke-hub/commit/f11dcfdf34ce4fa26de2fc4779b5b4f46a5c52bd)) * add always_use_jwt_access ([#45](https://www.github.com/googleapis/python-gke-hub/issues/45)) ([225d132](https://www.github.com/googleapis/python-gke-hub/commit/225d13235789a5d778658c2938e2c07df847a0cd)) * add v1 ([#51](https://www.github.com/googleapis/python-gke-hub/issues/51)) ([f11dcfd](https://www.github.com/googleapis/python-gke-hub/commit/f11dcfdf34ce4fa26de2fc4779b5b4f46a5c52bd)) ### Bug Fixes * **deps:** pin 'google-{api,cloud}-core', 'google-auth' to allow 2.x versions ([#55](https://www.github.com/googleapis/python-gke-hub/issues/55)) ([7035364](https://www.github.com/googleapis/python-gke-hub/commit/703536465a766c452a8c27a6ee951dec35cf3c4f)) * enable self signed jwt for grpc ([#58](https://www.github.com/googleapis/python-gke-hub/issues/58)) ([66f14c9](https://www.github.com/googleapis/python-gke-hub/commit/66f14c93978f97f8180ca8f0a02856d4d633a2bf)) * **v1beta1:** disable always_use_jwt_access ([#52](https://www.github.com/googleapis/python-gke-hub/issues/52)) ([100f72e](https://www.github.com/googleapis/python-gke-hub/commit/100f72e7181f4faeb04a76e106888ffd766ed9ef)) ### Documentation * omit mention of Python 2.7 in 'CONTRIBUTING.rst' ([#1127](https://www.github.com/googleapis/python-gke-hub/issues/1127)) ([#40](https://www.github.com/googleapis/python-gke-hub/issues/40)) ([8f703d7](https://www.github.com/googleapis/python-gke-hub/commit/8f703d74ad3d9b3ea31b2136ed4e97594b52f832)), closes [#1126](https://www.github.com/googleapis/python-gke-hub/issues/1126) * add Samples section to CONTRIBUTING.rst ([#56](https://www.github.com/googleapis/python-gke-hub/issues/56)) ([b08cf7e](https://www.github.com/googleapis/python-gke-hub/commit/b08cf7e5f2dbb1f3615f5b652c2d69f991d8aa69)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- CHANGELOG.md | 22 +++++ google/cloud/gkehub/__init__.py | 84 +++++++++++++++++ .../cloud/gkehub/configmanagement/__init__.py | 94 ------------------- google/cloud/gkehub/configmanagement/py.typed | 2 - .../types/configmanagement.py | 2 +- .../gkehub/multiclusteringress/__init__.py | 22 ----- .../cloud/gkehub/multiclusteringress/py.typed | 2 - .../types/multiclusteringress.py | 2 +- .../services/gke_hub/async_client.py | 4 +- .../gkehub_v1/services/gke_hub/client.py | 4 +- .../services/gke_hub/transports/grpc.py | 26 ++--- .../gke_hub/transports/grpc_asyncio.py | 26 ++--- google/cloud/gkehub_v1/types/feature.py | 12 +-- google/cloud/gkehub_v1/types/membership.py | 2 +- google/cloud/gkehub_v1/types/service.py | 2 +- owlbot.py | 25 +---- setup.py | 2 +- tests/unit/gapic/gkehub_v1/test_gke_hub.py | 4 +- 18 files changed, 152 insertions(+), 185 deletions(-) create mode 100644 google/cloud/gkehub/__init__.py delete mode 100644 google/cloud/gkehub/configmanagement/__init__.py delete mode 100644 google/cloud/gkehub/configmanagement/py.typed delete mode 100644 google/cloud/gkehub/multiclusteringress/__init__.py delete mode 100644 google/cloud/gkehub/multiclusteringress/py.typed diff --git a/CHANGELOG.md b/CHANGELOG.md index 47934e4..5eab68f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## [0.2.0](https://www.github.com/googleapis/python-gke-hub/compare/v0.1.2...v0.2.0) (2021-07-24) + + +### Features + +* add always_use_jwt_access ([f11dcfd](https://www.github.com/googleapis/python-gke-hub/commit/f11dcfdf34ce4fa26de2fc4779b5b4f46a5c52bd)) +* add always_use_jwt_access ([#45](https://www.github.com/googleapis/python-gke-hub/issues/45)) ([225d132](https://www.github.com/googleapis/python-gke-hub/commit/225d13235789a5d778658c2938e2c07df847a0cd)) +* add v1 ([#51](https://www.github.com/googleapis/python-gke-hub/issues/51)) ([f11dcfd](https://www.github.com/googleapis/python-gke-hub/commit/f11dcfdf34ce4fa26de2fc4779b5b4f46a5c52bd)) + + +### Bug Fixes + +* **deps:** pin 'google-{api,cloud}-core', 'google-auth' to allow 2.x versions ([#55](https://www.github.com/googleapis/python-gke-hub/issues/55)) ([7035364](https://www.github.com/googleapis/python-gke-hub/commit/703536465a766c452a8c27a6ee951dec35cf3c4f)) +* enable self signed jwt for grpc ([#58](https://www.github.com/googleapis/python-gke-hub/issues/58)) ([66f14c9](https://www.github.com/googleapis/python-gke-hub/commit/66f14c93978f97f8180ca8f0a02856d4d633a2bf)) +* **v1beta1:** disable always_use_jwt_access ([#52](https://www.github.com/googleapis/python-gke-hub/issues/52)) ([100f72e](https://www.github.com/googleapis/python-gke-hub/commit/100f72e7181f4faeb04a76e106888ffd766ed9ef)) + + +### Documentation + +* omit mention of Python 2.7 in 'CONTRIBUTING.rst' ([#1127](https://www.github.com/googleapis/python-gke-hub/issues/1127)) ([#40](https://www.github.com/googleapis/python-gke-hub/issues/40)) ([8f703d7](https://www.github.com/googleapis/python-gke-hub/commit/8f703d74ad3d9b3ea31b2136ed4e97594b52f832)), closes [#1126](https://www.github.com/googleapis/python-gke-hub/issues/1126) +* add Samples section to CONTRIBUTING.rst ([#56](https://www.github.com/googleapis/python-gke-hub/issues/56)) ([b08cf7e](https://www.github.com/googleapis/python-gke-hub/commit/b08cf7e5f2dbb1f3615f5b652c2d69f991d8aa69)) + ### [0.1.2](https://www.github.com/googleapis/python-gke-hub/compare/v0.1.1...v0.1.2) (2021-06-16) diff --git a/google/cloud/gkehub/__init__.py b/google/cloud/gkehub/__init__.py new file mode 100644 index 0000000..3faab2a --- /dev/null +++ b/google/cloud/gkehub/__init__.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from google.cloud.gkehub_v1.services.gke_hub.client import GkeHubClient +from google.cloud.gkehub_v1.services.gke_hub.async_client import GkeHubAsyncClient + +from google.cloud.gkehub_v1.types.feature import CommonFeatureSpec +from google.cloud.gkehub_v1.types.feature import CommonFeatureState +from google.cloud.gkehub_v1.types.feature import Feature +from google.cloud.gkehub_v1.types.feature import FeatureResourceState +from google.cloud.gkehub_v1.types.feature import FeatureState +from google.cloud.gkehub_v1.types.feature import MembershipFeatureSpec +from google.cloud.gkehub_v1.types.feature import MembershipFeatureState +from google.cloud.gkehub_v1.types.membership import Authority +from google.cloud.gkehub_v1.types.membership import GkeCluster +from google.cloud.gkehub_v1.types.membership import KubernetesMetadata +from google.cloud.gkehub_v1.types.membership import Membership +from google.cloud.gkehub_v1.types.membership import MembershipEndpoint +from google.cloud.gkehub_v1.types.membership import MembershipState +from google.cloud.gkehub_v1.types.service import ConnectAgentResource +from google.cloud.gkehub_v1.types.service import CreateFeatureRequest +from google.cloud.gkehub_v1.types.service import CreateMembershipRequest +from google.cloud.gkehub_v1.types.service import DeleteFeatureRequest +from google.cloud.gkehub_v1.types.service import DeleteMembershipRequest +from google.cloud.gkehub_v1.types.service import GenerateConnectManifestRequest +from google.cloud.gkehub_v1.types.service import GenerateConnectManifestResponse +from google.cloud.gkehub_v1.types.service import GetFeatureRequest +from google.cloud.gkehub_v1.types.service import GetMembershipRequest +from google.cloud.gkehub_v1.types.service import ListFeaturesRequest +from google.cloud.gkehub_v1.types.service import ListFeaturesResponse +from google.cloud.gkehub_v1.types.service import ListMembershipsRequest +from google.cloud.gkehub_v1.types.service import ListMembershipsResponse +from google.cloud.gkehub_v1.types.service import OperationMetadata +from google.cloud.gkehub_v1.types.service import TypeMeta +from google.cloud.gkehub_v1.types.service import UpdateFeatureRequest +from google.cloud.gkehub_v1.types.service import UpdateMembershipRequest + +__all__ = ( + "GkeHubClient", + "GkeHubAsyncClient", + "CommonFeatureSpec", + "CommonFeatureState", + "Feature", + "FeatureResourceState", + "FeatureState", + "MembershipFeatureSpec", + "MembershipFeatureState", + "Authority", + "GkeCluster", + "KubernetesMetadata", + "Membership", + "MembershipEndpoint", + "MembershipState", + "ConnectAgentResource", + "CreateFeatureRequest", + "CreateMembershipRequest", + "DeleteFeatureRequest", + "DeleteMembershipRequest", + "GenerateConnectManifestRequest", + "GenerateConnectManifestResponse", + "GetFeatureRequest", + "GetMembershipRequest", + "ListFeaturesRequest", + "ListFeaturesResponse", + "ListMembershipsRequest", + "ListMembershipsResponse", + "OperationMetadata", + "TypeMeta", + "UpdateFeatureRequest", + "UpdateMembershipRequest", +) diff --git a/google/cloud/gkehub/configmanagement/__init__.py b/google/cloud/gkehub/configmanagement/__init__.py deleted file mode 100644 index f170446..0000000 --- a/google/cloud/gkehub/configmanagement/__init__.py +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - - -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ConfigSync -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( - ConfigSyncDeploymentState, -) -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( - ConfigSyncState, -) -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( - ConfigSyncVersion, -) -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ErrorResource -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( - GatekeeperDeploymentState, -) -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import GitConfig -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( - GroupVersionKind, -) -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( - HierarchyControllerConfig, -) -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( - HierarchyControllerDeploymentState, -) -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( - HierarchyControllerState, -) -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( - HierarchyControllerVersion, -) -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import InstallError -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( - MembershipSpec, -) -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( - MembershipState, -) -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import OperatorState -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( - PolicyController, -) -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( - PolicyControllerState, -) -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( - PolicyControllerVersion, -) -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import SyncError -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import SyncState -from google.cloud.gkehub.configmanagement_v1.types.configmanagement import ( - DeploymentState, -) - -__all__ = ( - "ConfigSync", - "ConfigSyncDeploymentState", - "ConfigSyncState", - "ConfigSyncVersion", - "ErrorResource", - "GatekeeperDeploymentState", - "GitConfig", - "GroupVersionKind", - "HierarchyControllerConfig", - "HierarchyControllerDeploymentState", - "HierarchyControllerState", - "HierarchyControllerVersion", - "InstallError", - "MembershipSpec", - "MembershipState", - "OperatorState", - "PolicyController", - "PolicyControllerState", - "PolicyControllerVersion", - "SyncError", - "SyncState", - "DeploymentState", -) diff --git a/google/cloud/gkehub/configmanagement/py.typed b/google/cloud/gkehub/configmanagement/py.typed deleted file mode 100644 index 5d21684..0000000 --- a/google/cloud/gkehub/configmanagement/py.typed +++ /dev/null @@ -1,2 +0,0 @@ -# Marker file for PEP 561. -# The google-cloud-gkehub-configmanagement package uses inline types. diff --git a/google/cloud/gkehub/configmanagement_v1/types/configmanagement.py b/google/cloud/gkehub/configmanagement_v1/types/configmanagement.py index 2e80137..81afa63 100644 --- a/google/cloud/gkehub/configmanagement_v1/types/configmanagement.py +++ b/google/cloud/gkehub/configmanagement_v1/types/configmanagement.py @@ -19,7 +19,7 @@ __protobuf__ = proto.module( - package="google.cloud.gkehub.configmanagement_v1", + package="google.cloud.gkehub.configmanagement.v1", manifest={ "DeploymentState", "MembershipState", diff --git a/google/cloud/gkehub/multiclusteringress/__init__.py b/google/cloud/gkehub/multiclusteringress/__init__.py deleted file mode 100644 index a05e215..0000000 --- a/google/cloud/gkehub/multiclusteringress/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - - -from google.cloud.gkehub.multiclusteringress_v1.types.multiclusteringress import ( - FeatureSpec, -) - -__all__ = ("FeatureSpec",) diff --git a/google/cloud/gkehub/multiclusteringress/py.typed b/google/cloud/gkehub/multiclusteringress/py.typed deleted file mode 100644 index 298daf2..0000000 --- a/google/cloud/gkehub/multiclusteringress/py.typed +++ /dev/null @@ -1,2 +0,0 @@ -# Marker file for PEP 561. -# The google-cloud-gkehub-multiclusteringress package uses inline types. diff --git a/google/cloud/gkehub/multiclusteringress_v1/types/multiclusteringress.py b/google/cloud/gkehub/multiclusteringress_v1/types/multiclusteringress.py index ef30a0b..740be66 100644 --- a/google/cloud/gkehub/multiclusteringress_v1/types/multiclusteringress.py +++ b/google/cloud/gkehub/multiclusteringress_v1/types/multiclusteringress.py @@ -17,7 +17,7 @@ __protobuf__ = proto.module( - package="google.cloud.gkehub.multiclusteringress_v1", manifest={"FeatureSpec",}, + package="google.cloud.gkehub.multiclusteringress.v1", manifest={"FeatureSpec",}, ) diff --git a/google/cloud/gkehub_v1/services/gke_hub/async_client.py b/google/cloud/gkehub_v1/services/gke_hub/async_client.py index d56e4b5..632ae32 100644 --- a/google/cloud/gkehub_v1/services/gke_hub/async_client.py +++ b/google/cloud/gkehub_v1/services/gke_hub/async_client.py @@ -47,8 +47,8 @@ class GkeHubAsyncClient: The GKE Hub service operates on the following resources: - - [Membership][google.cloud.gkehub_v1.Membership] - - [Feature][google.cloud.gkehub_v1.Feature] + - [Membership][google.cloud.gkehub.v1.Membership] + - [Feature][google.cloud.gkehub.v1.Feature] GKE Hub is currently only available in the global region. diff --git a/google/cloud/gkehub_v1/services/gke_hub/client.py b/google/cloud/gkehub_v1/services/gke_hub/client.py index 4a62ea0..f3ed8f7 100644 --- a/google/cloud/gkehub_v1/services/gke_hub/client.py +++ b/google/cloud/gkehub_v1/services/gke_hub/client.py @@ -82,8 +82,8 @@ class GkeHubClient(metaclass=GkeHubClientMeta): The GKE Hub service operates on the following resources: - - [Membership][google.cloud.gkehub_v1.Membership] - - [Feature][google.cloud.gkehub_v1.Feature] + - [Membership][google.cloud.gkehub.v1.Membership] + - [Feature][google.cloud.gkehub.v1.Feature] GKE Hub is currently only available in the global region. diff --git a/google/cloud/gkehub_v1/services/gke_hub/transports/grpc.py b/google/cloud/gkehub_v1/services/gke_hub/transports/grpc.py index 0614912..0d1dff5 100644 --- a/google/cloud/gkehub_v1/services/gke_hub/transports/grpc.py +++ b/google/cloud/gkehub_v1/services/gke_hub/transports/grpc.py @@ -41,8 +41,8 @@ class GkeHubGrpcTransport(GkeHubTransport): The GKE Hub service operates on the following resources: - - [Membership][google.cloud.gkehub_v1.Membership] - - [Feature][google.cloud.gkehub_v1.Feature] + - [Membership][google.cloud.gkehub.v1.Membership] + - [Feature][google.cloud.gkehub.v1.Feature] GKE Hub is currently only available in the global region. @@ -277,7 +277,7 @@ def list_memberships( # to pass in the functions for each. if "list_memberships" not in self._stubs: self._stubs["list_memberships"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/ListMemberships", + "/google.cloud.gkehub.v1.GkeHub/ListMemberships", request_serializer=service.ListMembershipsRequest.serialize, response_deserializer=service.ListMembershipsResponse.deserialize, ) @@ -303,7 +303,7 @@ def list_features( # to pass in the functions for each. if "list_features" not in self._stubs: self._stubs["list_features"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/ListFeatures", + "/google.cloud.gkehub.v1.GkeHub/ListFeatures", request_serializer=service.ListFeaturesRequest.serialize, response_deserializer=service.ListFeaturesResponse.deserialize, ) @@ -329,7 +329,7 @@ def get_membership( # to pass in the functions for each. if "get_membership" not in self._stubs: self._stubs["get_membership"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/GetMembership", + "/google.cloud.gkehub.v1.GkeHub/GetMembership", request_serializer=service.GetMembershipRequest.serialize, response_deserializer=membership.Membership.deserialize, ) @@ -353,7 +353,7 @@ def get_feature(self) -> Callable[[service.GetFeatureRequest], feature.Feature]: # to pass in the functions for each. if "get_feature" not in self._stubs: self._stubs["get_feature"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/GetFeature", + "/google.cloud.gkehub.v1.GkeHub/GetFeature", request_serializer=service.GetFeatureRequest.serialize, response_deserializer=feature.Feature.deserialize, ) @@ -383,7 +383,7 @@ def create_membership( # to pass in the functions for each. if "create_membership" not in self._stubs: self._stubs["create_membership"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/CreateMembership", + "/google.cloud.gkehub.v1.GkeHub/CreateMembership", request_serializer=service.CreateMembershipRequest.serialize, response_deserializer=operations_pb2.Operation.FromString, ) @@ -409,7 +409,7 @@ def create_feature( # to pass in the functions for each. if "create_feature" not in self._stubs: self._stubs["create_feature"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/CreateFeature", + "/google.cloud.gkehub.v1.GkeHub/CreateFeature", request_serializer=service.CreateFeatureRequest.serialize, response_deserializer=operations_pb2.Operation.FromString, ) @@ -440,7 +440,7 @@ def delete_membership( # to pass in the functions for each. if "delete_membership" not in self._stubs: self._stubs["delete_membership"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/DeleteMembership", + "/google.cloud.gkehub.v1.GkeHub/DeleteMembership", request_serializer=service.DeleteMembershipRequest.serialize, response_deserializer=operations_pb2.Operation.FromString, ) @@ -466,7 +466,7 @@ def delete_feature( # to pass in the functions for each. if "delete_feature" not in self._stubs: self._stubs["delete_feature"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/DeleteFeature", + "/google.cloud.gkehub.v1.GkeHub/DeleteFeature", request_serializer=service.DeleteFeatureRequest.serialize, response_deserializer=operations_pb2.Operation.FromString, ) @@ -492,7 +492,7 @@ def update_membership( # to pass in the functions for each. if "update_membership" not in self._stubs: self._stubs["update_membership"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/UpdateMembership", + "/google.cloud.gkehub.v1.GkeHub/UpdateMembership", request_serializer=service.UpdateMembershipRequest.serialize, response_deserializer=operations_pb2.Operation.FromString, ) @@ -518,7 +518,7 @@ def update_feature( # to pass in the functions for each. if "update_feature" not in self._stubs: self._stubs["update_feature"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/UpdateFeature", + "/google.cloud.gkehub.v1.GkeHub/UpdateFeature", request_serializer=service.UpdateFeatureRequest.serialize, response_deserializer=operations_pb2.Operation.FromString, ) @@ -550,7 +550,7 @@ def generate_connect_manifest( # to pass in the functions for each. if "generate_connect_manifest" not in self._stubs: self._stubs["generate_connect_manifest"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/GenerateConnectManifest", + "/google.cloud.gkehub.v1.GkeHub/GenerateConnectManifest", request_serializer=service.GenerateConnectManifestRequest.serialize, response_deserializer=service.GenerateConnectManifestResponse.deserialize, ) diff --git a/google/cloud/gkehub_v1/services/gke_hub/transports/grpc_asyncio.py b/google/cloud/gkehub_v1/services/gke_hub/transports/grpc_asyncio.py index 09e3173..2b75938 100644 --- a/google/cloud/gkehub_v1/services/gke_hub/transports/grpc_asyncio.py +++ b/google/cloud/gkehub_v1/services/gke_hub/transports/grpc_asyncio.py @@ -43,8 +43,8 @@ class GkeHubGrpcAsyncIOTransport(GkeHubTransport): The GKE Hub service operates on the following resources: - - [Membership][google.cloud.gkehub_v1.Membership] - - [Feature][google.cloud.gkehub_v1.Feature] + - [Membership][google.cloud.gkehub.v1.Membership] + - [Feature][google.cloud.gkehub.v1.Feature] GKE Hub is currently only available in the global region. @@ -284,7 +284,7 @@ def list_memberships( # to pass in the functions for each. if "list_memberships" not in self._stubs: self._stubs["list_memberships"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/ListMemberships", + "/google.cloud.gkehub.v1.GkeHub/ListMemberships", request_serializer=service.ListMembershipsRequest.serialize, response_deserializer=service.ListMembershipsResponse.deserialize, ) @@ -312,7 +312,7 @@ def list_features( # to pass in the functions for each. if "list_features" not in self._stubs: self._stubs["list_features"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/ListFeatures", + "/google.cloud.gkehub.v1.GkeHub/ListFeatures", request_serializer=service.ListFeaturesRequest.serialize, response_deserializer=service.ListFeaturesResponse.deserialize, ) @@ -338,7 +338,7 @@ def get_membership( # to pass in the functions for each. if "get_membership" not in self._stubs: self._stubs["get_membership"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/GetMembership", + "/google.cloud.gkehub.v1.GkeHub/GetMembership", request_serializer=service.GetMembershipRequest.serialize, response_deserializer=membership.Membership.deserialize, ) @@ -364,7 +364,7 @@ def get_feature( # to pass in the functions for each. if "get_feature" not in self._stubs: self._stubs["get_feature"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/GetFeature", + "/google.cloud.gkehub.v1.GkeHub/GetFeature", request_serializer=service.GetFeatureRequest.serialize, response_deserializer=feature.Feature.deserialize, ) @@ -396,7 +396,7 @@ def create_membership( # to pass in the functions for each. if "create_membership" not in self._stubs: self._stubs["create_membership"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/CreateMembership", + "/google.cloud.gkehub.v1.GkeHub/CreateMembership", request_serializer=service.CreateMembershipRequest.serialize, response_deserializer=operations_pb2.Operation.FromString, ) @@ -422,7 +422,7 @@ def create_feature( # to pass in the functions for each. if "create_feature" not in self._stubs: self._stubs["create_feature"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/CreateFeature", + "/google.cloud.gkehub.v1.GkeHub/CreateFeature", request_serializer=service.CreateFeatureRequest.serialize, response_deserializer=operations_pb2.Operation.FromString, ) @@ -455,7 +455,7 @@ def delete_membership( # to pass in the functions for each. if "delete_membership" not in self._stubs: self._stubs["delete_membership"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/DeleteMembership", + "/google.cloud.gkehub.v1.GkeHub/DeleteMembership", request_serializer=service.DeleteMembershipRequest.serialize, response_deserializer=operations_pb2.Operation.FromString, ) @@ -481,7 +481,7 @@ def delete_feature( # to pass in the functions for each. if "delete_feature" not in self._stubs: self._stubs["delete_feature"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/DeleteFeature", + "/google.cloud.gkehub.v1.GkeHub/DeleteFeature", request_serializer=service.DeleteFeatureRequest.serialize, response_deserializer=operations_pb2.Operation.FromString, ) @@ -509,7 +509,7 @@ def update_membership( # to pass in the functions for each. if "update_membership" not in self._stubs: self._stubs["update_membership"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/UpdateMembership", + "/google.cloud.gkehub.v1.GkeHub/UpdateMembership", request_serializer=service.UpdateMembershipRequest.serialize, response_deserializer=operations_pb2.Operation.FromString, ) @@ -535,7 +535,7 @@ def update_feature( # to pass in the functions for each. if "update_feature" not in self._stubs: self._stubs["update_feature"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/UpdateFeature", + "/google.cloud.gkehub.v1.GkeHub/UpdateFeature", request_serializer=service.UpdateFeatureRequest.serialize, response_deserializer=operations_pb2.Operation.FromString, ) @@ -567,7 +567,7 @@ def generate_connect_manifest( # to pass in the functions for each. if "generate_connect_manifest" not in self._stubs: self._stubs["generate_connect_manifest"] = self.grpc_channel.unary_unary( - "/google.cloud.gkehub_v1.GkeHub/GenerateConnectManifest", + "/google.cloud.gkehub.v1.GkeHub/GenerateConnectManifest", request_serializer=service.GenerateConnectManifestRequest.serialize, response_deserializer=service.GenerateConnectManifestResponse.deserialize, ) diff --git a/google/cloud/gkehub_v1/types/feature.py b/google/cloud/gkehub_v1/types/feature.py index 0f91981..749a588 100644 --- a/google/cloud/gkehub_v1/types/feature.py +++ b/google/cloud/gkehub_v1/types/feature.py @@ -15,13 +15,13 @@ # import proto # type: ignore -import google.cloud.gkehub.configmanagement_v1 as configmanagement_pb2 # type: ignore -import google.cloud.gkehub.multiclusteringress_v1 as multiclusteringress_pb2 # type: ignore +from google.cloud.gkehub import configmanagement_v1 as configmanagement_pb2 # type: ignore +from google.cloud.gkehub import multiclusteringress_v1 as multiclusteringress_pb2 # type: ignore from google.protobuf import timestamp_pb2 # type: ignore __protobuf__ = proto.module( - package="google.cloud.gkehub_v1", + package="google.cloud.gkehub.v1", manifest={ "Feature", "FeatureResourceState", @@ -175,7 +175,7 @@ class CommonFeatureSpec(proto.Message): r"""CommonFeatureSpec contains Hub-wide configuration informatio. Attributes: - multiclusteringress (google.cloud.gkehub.multiclusteringress_v1.multiclusteringress_pb2.FeatureSpec): + multiclusteringress (google.cloud.gkehub.multiclusteringress.v1.multiclusteringress_pb2.FeatureSpec): Multicluster Ingress-specific spec. """ @@ -205,7 +205,7 @@ class MembershipFeatureSpec(proto.Message): a single Membership. Attributes: - configmanagement (google.cloud.gkehub.configmanagement_v1.configmanagement_pb2.MembershipSpec): + configmanagement (google.cloud.gkehub.configmanagement.v1.configmanagement_pb2.MembershipSpec): Config Management-specific spec. """ @@ -222,7 +222,7 @@ class MembershipFeatureState(proto.Message): for a single Membership. Attributes: - configmanagement (google.cloud.gkehub.configmanagement_v1.configmanagement_pb2.MembershipState): + configmanagement (google.cloud.gkehub.configmanagement.v1.configmanagement_pb2.MembershipState): Config Management-specific state. state (google.cloud.gkehub_v1.types.FeatureState): The high-level state of this Feature for a diff --git a/google/cloud/gkehub_v1/types/membership.py b/google/cloud/gkehub_v1/types/membership.py index 67c3d98..f1ea88d 100644 --- a/google/cloud/gkehub_v1/types/membership.py +++ b/google/cloud/gkehub_v1/types/membership.py @@ -19,7 +19,7 @@ __protobuf__ = proto.module( - package="google.cloud.gkehub_v1", + package="google.cloud.gkehub.v1", manifest={ "Membership", "MembershipEndpoint", diff --git a/google/cloud/gkehub_v1/types/service.py b/google/cloud/gkehub_v1/types/service.py index 7c12ebd..d0aec24 100644 --- a/google/cloud/gkehub_v1/types/service.py +++ b/google/cloud/gkehub_v1/types/service.py @@ -22,7 +22,7 @@ __protobuf__ = proto.module( - package="google.cloud.gkehub_v1", + package="google.cloud.gkehub.v1", manifest={ "ListMembershipsRequest", "ListMembershipsResponse", diff --git a/owlbot.py b/owlbot.py index 1ce6b4c..07d70f4 100644 --- a/owlbot.py +++ b/owlbot.py @@ -30,16 +30,6 @@ "multiclusteringress", ] - # rename google.cloud.gkehub.vX to google.cloud.gkehub_vX - s.replace( - [ - library / f"google/cloud/gkehub_{library.name}/**/*.py", - library / f"tests/unit/gapic/gkehub_{library.name}/**/*.py", - ], - f"google.cloud.gkehub.{library.name}", - f"google.cloud.gkehub_{library.name}", - ) - # rename dependencies google.cloud.gkehub.dep.vX to google.cloud.gkehub.dep_vX for dep in dependencies: s.replace( @@ -49,17 +39,7 @@ library / f"google/cloud/gkehub/{dep}_{library.name}/**/*.py", ], f"from google.cloud.gkehub.{dep}.{library.name} import", - f"import google.cloud.gkehub.{dep}_{library.name} as" - ) - - s.replace( - [ - library / f"google/cloud/gkehub_{library.name}/**/*.py", - library / f"tests/unit/gapic/gkehub_{library.name}/**/*.py", - library / f"google/cloud/gkehub/{dep}_{library.name}/**/*.py", - ], - f"google.cloud.gkehub.{dep}.{library.name}", - f"google.cloud.gkehub.{dep}_{library.name}" + f"from google.cloud.gkehub import {dep}_{library.name} as" ) # Work around gapic generator bug https://github.com/googleapis/gapic-generator-python/issues/902 @@ -83,7 +63,8 @@ """the GKE cluster. For example: //container.googleapis.com/projects/my-""" ) - s.move(library, excludes=["setup.py", "README.rst", "docs/index.rst","google/cloud/gkehub/__init__.py"]) + + s.move(library, excludes=["setup.py", "README.rst", "docs/index.rst", "google/cloud/gkehub/configmanagement", "google/cloud/gkehub/multiclusteringress"]) s.remove_staging_dirs() diff --git a/setup.py b/setup.py index cc38696..ea41ed4 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ import setuptools # type: ignore name = "google-cloud-gke-hub" -version = "0.1.2" +version = "0.2.0" description = "GKE Hub API client library" release_status = "Development Status :: 4 - Beta" url = "https://github.com/googleapis/python-gke-hub" diff --git a/tests/unit/gapic/gkehub_v1/test_gke_hub.py b/tests/unit/gapic/gkehub_v1/test_gke_hub.py index ab4a52a..e2e15fa 100644 --- a/tests/unit/gapic/gkehub_v1/test_gke_hub.py +++ b/tests/unit/gapic/gkehub_v1/test_gke_hub.py @@ -34,8 +34,8 @@ from google.api_core import operations_v1 from google.auth import credentials as ga_credentials from google.auth.exceptions import MutualTLSChannelError -import google.cloud.gkehub.configmanagement_v1 as configmanagement_pb2 # type: ignore -import google.cloud.gkehub.multiclusteringress_v1 as multiclusteringress_pb2 # type: ignore +from google.cloud.gkehub import configmanagement_v1 as configmanagement_pb2 # type: ignore +from google.cloud.gkehub import multiclusteringress_v1 as multiclusteringress_pb2 # type: ignore from google.cloud.gkehub_v1.services.gke_hub import GkeHubAsyncClient from google.cloud.gkehub_v1.services.gke_hub import GkeHubClient from google.cloud.gkehub_v1.services.gke_hub import pagers