From f432083e7cc9418b378f52274bed3fa1495b4096 Mon Sep 17 00:00:00 2001 From: arithmetic1728 <58957152+arithmetic1728@users.noreply.github.com> Date: Thu, 16 Jul 2020 12:06:57 -0700 Subject: [PATCH 01/36] feat!: migrate to microgenerator (#33) --- container/AUTHORING_GUIDE.md | 1 + container/CONTRIBUTING.md | 1 + 2 files changed, 2 insertions(+) create mode 100644 container/AUTHORING_GUIDE.md create mode 100644 container/CONTRIBUTING.md diff --git a/container/AUTHORING_GUIDE.md b/container/AUTHORING_GUIDE.md new file mode 100644 index 00000000000..55c97b32f4c --- /dev/null +++ b/container/AUTHORING_GUIDE.md @@ -0,0 +1 @@ +See https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/AUTHORING_GUIDE.md \ No newline at end of file diff --git a/container/CONTRIBUTING.md b/container/CONTRIBUTING.md new file mode 100644 index 00000000000..34c882b6f1a --- /dev/null +++ b/container/CONTRIBUTING.md @@ -0,0 +1 @@ +See https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/CONTRIBUTING.md \ No newline at end of file From 91547b02d1020ecd22d1a7b62109fa3d0acaef0e Mon Sep 17 00:00:00 2001 From: Shabir Mohamed Abdul Samadh <7249208+Shabirmean@users.noreply.github.com> Date: Tue, 15 Feb 2022 20:36:05 -0500 Subject: [PATCH 02/36] docs(samples): add usage samples to show handling of LRO response Operation (#191) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * improvement: add samples for the using the library * cleanup: update the git ignore * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * chore: remove unnecessary comments * chore: update git ignore * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * doc: add simple usage instructions to README * cleanup: add copyright headers * chore: update git ignore * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * doc: add more details to retry function doc * chore: update git ignore * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * doc: add seperate sections about the samples * chore: update git ignore * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * cleanup: add region tags * doc: update the readme to remove inline code * chore: update git ignore * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * doc: update readme * chore: update git ignore * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * process: add nox and fix lint errors * chore: update git ignore * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * process: add requirements.txt * chore: add lro samples to gitignore * test: add test for quickstart * test: add test for create cluster * test: add test for delete cluster * test: fix fixture in test * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * lint: finx linting errors * cleanup: remove the main from being inside the region tags * cleanup: remove the main from being inside the region tags * cleanup: remove the main from being inside the region tags * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * doc: fix typo Co-authored-by: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> * doc: pr comment doc update Co-authored-by: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> * doc: add license headers to missing files * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Owl Bot Co-authored-by: Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> --- container/snippets/README.md | 45 ++++ container/snippets/create_cluster.py | 111 +++++++++ container/snippets/create_cluster_test.py | 72 ++++++ container/snippets/delete_cluster.py | 104 ++++++++ container/snippets/delete_cluster_test.py | 96 ++++++++ container/snippets/noxfile.py | 279 ++++++++++++++++++++++ container/snippets/noxfile_config.py | 42 ++++ container/snippets/quickstart.py | 56 +++++ container/snippets/quickstart_test.py | 55 +++++ container/snippets/requirement-test.txt | 4 + container/snippets/requirements.txt | 3 + 11 files changed, 867 insertions(+) create mode 100644 container/snippets/README.md create mode 100644 container/snippets/create_cluster.py create mode 100644 container/snippets/create_cluster_test.py create mode 100644 container/snippets/delete_cluster.py create mode 100644 container/snippets/delete_cluster_test.py create mode 100644 container/snippets/noxfile.py create mode 100644 container/snippets/noxfile_config.py create mode 100644 container/snippets/quickstart.py create mode 100644 container/snippets/quickstart_test.py create mode 100644 container/snippets/requirement-test.txt create mode 100644 container/snippets/requirements.txt diff --git a/container/snippets/README.md b/container/snippets/README.md new file mode 100644 index 00000000000..a1d0691fd8c --- /dev/null +++ b/container/snippets/README.md @@ -0,0 +1,45 @@ +# Samples + +All the samples are self contained unless they are placed inside their own folders. The samples use [Application Default Credentails (ADC)](https://cloud.google.com/docs/authentication/production#automatically) to authenticate with GCP. So make sure ADC is setup correctly _(i.e. `GOOGLE_APPLICATION_CREDENTIALS` environment variable is set)_ before running the samples. Some sample might require additional python modules to be installed. + +You can run samples as follows: + +```python +python ... +``` + +You can run the following command to find the usage and arguments for the samples: + +```python +python -h +``` +```bash +# example +python quickstart.py -h + +usage: quickstart.py [-h] project_id zone + +positional arguments: + project_id Google Cloud project ID + zone GKE Cluster zone + +optional arguments: + -h, --help show this help message and exit +``` + +### Quickstart sample +- [**quickstart.py**](quickstart.py): A simple example to list the GKE clusters in a given GCP project and zone. The sample uses the [`list_clusters()`](https://cloud.google.com/python/docs/reference/container/latest/google.cloud.container_v1.services.cluster_manager.ClusterManagerClient#google_cloud_container_v1_services_cluster_manager_ClusterManagerClient_list_clusters) API to fetch the list of cluster. + + +### Long running operation sample + +The following samples are examples of operations that take a while to complete. +For example _creating a cluster_ in GKE can take a while to set up the cluster +nodes, networking and configuring Kubernetes. Thus, calls to such long running +APIs return an object of type [`Operation`](https://cloud.google.com/python/docs/reference/container/latest/google.cloud.container_v1.types.Operation). We can +then use the id of the returned operation to **poll** the [`get_operation()`](https://cloud.google.com/python/docs/reference/container/latest/google.cloud.container_v1.services.cluster_manager.ClusterManagerClient#google_cloud_container_v1_services_cluster_manager_ClusterManagerClient_get_operation) API to check for it's status. You can see the +different statuses it can be in, in [this proto definition](https://github.com/googleapis/googleapis/blob/master/google/container/v1/cluster_service.proto#L1763-L1778). + +- [**create_cluster.py**](create_cluster.py): An example of creating a GKE cluster _(with mostly the defaults)_. This example shows how to handle responses of type [`Operation`](https://cloud.google.com/python/docs/reference/container/latest/google.cloud.container_v1.types.Operation) that reperesents a long running operation. The example uses the python module [`backoff`](https://github.com/litl/backoff) to handle a graceful exponential backoff retry mechanism to check if the `Operation` has completed. + +- [**delete_cluster.py**](delete_cluster.py): An example of deleting a GKE cluster. This example shows how to handle responses of type [`Operation`](https://cloud.google.com/python/docs/reference/container/latest/google.cloud.container_v1.types.Operation) that reperesents a long running operation. \ No newline at end of file diff --git a/container/snippets/create_cluster.py b/container/snippets/create_cluster.py new file mode 100644 index 00000000000..ad5ddfc3998 --- /dev/null +++ b/container/snippets/create_cluster.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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. + +# [START gke_create_cluster] +import argparse +import sys +from typing import Dict + +import backoff +from google.cloud import container_v1 + + +def on_success(details: Dict[str, str]) -> None: + """ + A handler function to pass into the retry backoff algorithm as the function + to be executed upon a successful attempt. + + Read the `Event handlers` section of the backoff python module at: + https://pypi.org/project/backoff/ + """ + print("Successfully created cluster after {elapsed:0.1f} seconds".format(**details)) + + +def on_failure(details: Dict[str, str]) -> None: + """ + A handler function to pass into the retry backoff algorithm as the function + to be executed upon a failed attempt. + + Read the `Event handlers` section of the backoff python module at: + https://pypi.org/project/backoff/ + """ + print("Backing off {wait:0.1f} seconds after {tries} tries".format(**details)) + + +@backoff.on_predicate( + # the backoff algorithm to use. we use exponential backoff here + backoff.expo, + # the test function on the return value to determine if a retry is necessary + lambda x: x != container_v1.Operation.Status.DONE, + # maximum number of times to retry before giving up + max_tries=20, + # function to execute upon a failure and when a retry a scheduled + on_backoff=on_failure, + # function to execute upon a successful attempt and no more retries needed + on_success=on_success, +) +def poll_for_op_status( + client: container_v1.ClusterManagerClient, op_id: str +) -> container_v1.Operation.Status: + """ + This function calls the Operation API in GCP with the given operation id. It + serves as a simple retry function that fetches the operation and returns + it's status. + + We use the 'backoff' python module to provide us the implementation of the + backoff & retry strategy. The function is annotated with the `backoff` + python module to schedule this function based on a reasonable backoff + algorithm. + """ + + op = client.get_operation({"name": op_id}) + return op.status + + +def create_cluster(project_id: str, location: str, cluster_name: str) -> None: + """Create a new GKE cluster in the given GCP Project and Zone""" + # Initialize the Cluster management client. + client = container_v1.ClusterManagerClient() + # Create a fully qualified location identifier of form `projects/{project_id}/location/{zone}'. + cluster_location = client.common_location_path(project_id, location) + cluster_def = { + "name": cluster_name, + "initial_node_count": 2, + "node_config": {"machine_type": "e2-standard-2"}, + } + # Create the request object with the location identifier. + request = {"parent": cluster_location, "cluster": cluster_def} + create_response = client.create_cluster(request) + op_identifier = f"{cluster_location}/operations/{create_response.name}" + # poll for the operation status and schedule a retry until the cluster is created + poll_for_op_status(client, op_identifier) + + +# [END gke_create_cluster] + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter, + ) + parser.add_argument("project_id", help="Google Cloud project ID") + parser.add_argument("zone", help="GKE Cluster zone") + parser.add_argument("cluster_name", help="Name to be given to the GKE Cluster") + args = parser.parse_args() + + if len(sys.argv) != 4: + parser.print_usage() + sys.exit(1) + + create_cluster(args.project_id, args.zone, args.cluster_name) diff --git a/container/snippets/create_cluster_test.py b/container/snippets/create_cluster_test.py new file mode 100644 index 00000000000..a06ab2c511d --- /dev/null +++ b/container/snippets/create_cluster_test.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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 uuid + +import backoff + +from google.cloud import container_v1 as gke + +import pytest + +import create_cluster as gke_create + +PROJECT_ID = os.environ["GOOGLE_CLOUD_PROJECT"] +ZONE = "us-central1-b" +CLUSTER_NAME = f"py-container-repo-test-{uuid.uuid4().hex[:10]}" + + +@pytest.fixture(autouse=True) +def setup_and_tear_down() -> None: + + # nohing to setup here + + # run the tests here + yield + + # delete the cluster + client = gke.ClusterManagerClient() + cluster_location = client.common_location_path(PROJECT_ID, ZONE) + cluster_name = f"{cluster_location}/clusters/{CLUSTER_NAME}" + op = client.delete_cluster({"name": cluster_name}) + op_id = f"{cluster_location}/operations/{op.name}" + + # schedule a retry to ensure the cluster is deleted + @backoff.on_predicate( + backoff.expo, lambda x: x != gke.Operation.Status.DONE, max_tries=20 + ) + def wait_for_delete() -> gke.Operation.Status: + return client.get_operation({"name": op_id}).status + + wait_for_delete() + + +def test_create_clusters(capsys: object) -> None: + gke_create.create_cluster(PROJECT_ID, ZONE, CLUSTER_NAME) + out, _ = capsys.readouterr() + + assert "Backing off " in out + assert "Successfully created cluster after" in out + + client = gke.ClusterManagerClient() + cluster_location = client.common_location_path(PROJECT_ID, ZONE) + list_response = client.list_clusters({"parent": cluster_location}) + + list_of_clusters = [] + for cluster in list_response.clusters: + list_of_clusters.append(cluster.name) + + assert CLUSTER_NAME in list_of_clusters diff --git a/container/snippets/delete_cluster.py b/container/snippets/delete_cluster.py new file mode 100644 index 00000000000..0290766e9b9 --- /dev/null +++ b/container/snippets/delete_cluster.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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. + +# [START gke_delete_cluster] +import argparse +import sys +from typing import Dict + +import backoff +from google.cloud import container_v1 + + +def on_success(details: Dict[str, str]) -> None: + """ + A handler function to pass into the retry backoff algorithm as the function + to be executed upon a successful attempt. + + Read the `Event handlers` section of the backoff python module at: + https://pypi.org/project/backoff/ + """ + print("Successfully deleted cluster after {elapsed:0.1f} seconds".format(**details)) + + +def on_failure(details: Dict[str, str]) -> None: + """ + A handler function to pass into the retry backoff algorithm as the function + to be executed upon a failed attempt. + + Read the `Event handlers` section of the backoff python module at: + https://pypi.org/project/backoff/ + """ + print("Backing off {wait:0.1f} seconds after {tries} tries".format(**details)) + + +@backoff.on_predicate( + # the backoff algorithm to use. we use exponential backoff here + backoff.expo, + # the test function on the return value to determine if a retry is necessary + lambda x: x != container_v1.Operation.Status.DONE, + # maximum number of times to retry before giving up + max_tries=20, + # function to execute upon a failure and when a retry is scheduled + on_backoff=on_failure, + # function to execute upon a successful attempt and no more retries needed + on_success=on_success, +) +def poll_for_op_status( + client: container_v1.ClusterManagerClient, op_id: str +) -> container_v1.Operation.Status: + """ + A simple retry function that fetches the operation and returns it's status. + + The function is annotated with the `backoff` python module to schedule this + function based on a reasonable backoff algorithm + """ + + op = client.get_operation({"name": op_id}) + return op.status + + +def delete_cluster(project_id: str, location: str, cluster_name: str) -> None: + """Delete an existing GKE cluster in the given GCP Project and Zone""" + + # Initialize the Cluster management client. + client = container_v1.ClusterManagerClient() + # Create a fully qualified location identifier of form `projects/{project_id}/location/{zone}'. + cluster_location = client.common_location_path(project_id, location) + cluster_name = f"{cluster_location}/clusters/{cluster_name}" + # Create the request object with the location identifier. + request = {"name": cluster_name} + delete_response = client.delete_cluster(request) + op_identifier = f"{cluster_location}/operations/{delete_response.name}" + # poll for the operation status until the cluster is deleted + poll_for_op_status(client, op_identifier) + + +# [END gke_delete_cluster] + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter, + ) + parser.add_argument("project_id", help="Google Cloud project ID") + parser.add_argument("zone", help="GKE Cluster zone") + parser.add_argument("cluster_name", help="Name to be given to the GKE Cluster") + args = parser.parse_args() + + if len(sys.argv) != 4: + parser.print_usage() + sys.exit(1) + + delete_cluster(args.project_id, args.zone, args.cluster_name) diff --git a/container/snippets/delete_cluster_test.py b/container/snippets/delete_cluster_test.py new file mode 100644 index 00000000000..fc7845d3465 --- /dev/null +++ b/container/snippets/delete_cluster_test.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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 uuid + +import backoff + +from google.api_core import exceptions as googleEx +from google.cloud import container_v1 as gke + +import pytest + +import delete_cluster as gke_delete + +PROJECT_ID = os.environ["GOOGLE_CLOUD_PROJECT"] +ZONE = "us-central1-b" +CLUSTER_NAME = f"py-container-repo-test-{uuid.uuid4().hex[:10]}" + + +@pytest.fixture(autouse=True) +def setup_and_tear_down() -> None: + + # create a cluster to be deleted + client = gke.ClusterManagerClient() + cluster_location = client.common_location_path(PROJECT_ID, ZONE) + cluster_def = { + "name": CLUSTER_NAME, + "initial_node_count": 2, + "node_config": {"machine_type": "e2-standard-2"}, + } + op = client.create_cluster({"parent": cluster_location, "cluster": cluster_def}) + op_id = f"{cluster_location}/operations/{op.name}" + + # schedule a retry to ensure the cluster is created + @backoff.on_predicate( + backoff.expo, lambda x: x != gke.Operation.Status.DONE, max_tries=20 + ) + def wait_for_create() -> gke.Operation.Status: + return client.get_operation({"name": op_id}).status + + wait_for_create() + + # run the tests here + yield + + # delete the cluster in case the test itself failed + client = gke.ClusterManagerClient() + cluster_location = client.common_location_path(PROJECT_ID, ZONE) + cluster_name = f"{cluster_location}/clusters/{CLUSTER_NAME}" + + try: + op = client.delete_cluster({"name": cluster_name}) + op_id = f"{cluster_location}/operations/{op.name}" + + # schedule a retry to ensure the cluster is deleted + @backoff.on_predicate( + backoff.expo, lambda x: x != gke.Operation.Status.DONE, max_tries=20 + ) + def wait_for_delete() -> gke.Operation.Status: + return client.get_operation({"name": op_id}).status + + wait_for_delete() + except googleEx.NotFound: + # if the delete test passed then this is bound to happen + pass + + +def test_delete_clusters(capsys: object) -> None: + gke_delete.delete_cluster(PROJECT_ID, ZONE, CLUSTER_NAME) + out, _ = capsys.readouterr() + + assert "Backing off " in out + assert "Successfully deleted cluster after" in out + + client = gke.ClusterManagerClient() + cluster_location = client.common_location_path(PROJECT_ID, ZONE) + list_response = client.list_clusters({"parent": cluster_location}) + + list_of_clusters = [] + for cluster in list_response.clusters: + list_of_clusters.append(cluster.name) + + assert CLUSTER_NAME not in list_of_clusters diff --git a/container/snippets/noxfile.py b/container/snippets/noxfile.py new file mode 100644 index 00000000000..20cdfc62013 --- /dev/null +++ b/container/snippets/noxfile.py @@ -0,0 +1,279 @@ +# Copyright 2019 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 __future__ import print_function + +import glob +import os +from pathlib import Path +import sys +from typing import Callable, Dict, List, Optional + +import nox + + +# WARNING - WARNING - WARNING - WARNING - WARNING +# WARNING - WARNING - WARNING - WARNING - WARNING +# DO NOT EDIT THIS FILE EVER! +# WARNING - WARNING - WARNING - WARNING - WARNING +# WARNING - WARNING - WARNING - WARNING - WARNING + +BLACK_VERSION = "black==19.10b0" + +# Copy `noxfile_config.py` to your directory and modify it instead. + +# `TEST_CONFIG` dict is a configuration hook that allows users to +# modify the test configurations. The values here should be in sync +# with `noxfile_config.py`. Users will copy `noxfile_config.py` into +# their directory and modify it. + +TEST_CONFIG = { + # You can opt out from the test for specific Python versions. + "ignored_versions": [], + # Old samples are opted out of enforcing Python type hints + # All new samples should feature them + "enforce_type_hints": False, + # An envvar key for determining the project id to use. Change it + # to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a + # build specific Cloud project. You can also use your own string + # to use your own Cloud project. + "gcloud_project_env": "GOOGLE_CLOUD_PROJECT", + # 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT', + # If you need to use a specific version of pip, + # change pip_version_override to the string representation + # of the version number, for example, "20.2.4" + "pip_version_override": None, + # A dictionary you want to inject into your test. Don't put any + # secrets here. These values will override predefined values. + "envs": {}, +} + + +try: + # Ensure we can import noxfile_config in the project's directory. + sys.path.append(".") + from noxfile_config import TEST_CONFIG_OVERRIDE +except ImportError as e: + print("No user noxfile_config found: detail: {}".format(e)) + TEST_CONFIG_OVERRIDE = {} + +# Update the TEST_CONFIG with the user supplied values. +TEST_CONFIG.update(TEST_CONFIG_OVERRIDE) + + +def get_pytest_env_vars() -> Dict[str, str]: + """Returns a dict for pytest invocation.""" + ret = {} + + # Override the GCLOUD_PROJECT and the alias. + env_key = TEST_CONFIG["gcloud_project_env"] + # This should error out if not set. + ret["GOOGLE_CLOUD_PROJECT"] = os.environ[env_key] + + # Apply user supplied envs. + ret.update(TEST_CONFIG["envs"]) + return ret + + +# DO NOT EDIT - automatically generated. +# All versions used to test samples. +ALL_VERSIONS = ["3.6", "3.7", "3.8", "3.9", "3.10"] + +# Any default versions that should be ignored. +IGNORED_VERSIONS = TEST_CONFIG["ignored_versions"] + +TESTED_VERSIONS = sorted([v for v in ALL_VERSIONS if v not in IGNORED_VERSIONS]) + +INSTALL_LIBRARY_FROM_SOURCE = os.environ.get("INSTALL_LIBRARY_FROM_SOURCE", False) in ( + "True", + "true", +) + +# Error if a python version is missing +nox.options.error_on_missing_interpreters = True + +# +# Style Checks +# + + +def _determine_local_import_names(start_dir: str) -> List[str]: + """Determines all import names that should be considered "local". + + This is used when running the linter to insure that import order is + properly checked. + """ + file_ext_pairs = [os.path.splitext(path) for path in os.listdir(start_dir)] + return [ + basename + for basename, extension in file_ext_pairs + if extension == ".py" + or os.path.isdir(os.path.join(start_dir, basename)) + and basename not in ("__pycache__") + ] + + +# Linting with flake8. +# +# We ignore the following rules: +# E203: whitespace before ‘:’ +# E266: too many leading ‘#’ for block comment +# E501: line too long +# I202: Additional newline in a section of imports +# +# We also need to specify the rules which are ignored by default: +# ['E226', 'W504', 'E126', 'E123', 'W503', 'E24', 'E704', 'E121'] +FLAKE8_COMMON_ARGS = [ + "--show-source", + "--builtin=gettext", + "--max-complexity=20", + "--import-order-style=google", + "--exclude=.nox,.cache,env,lib,generated_pb2,*_pb2.py,*_pb2_grpc.py", + "--ignore=E121,E123,E126,E203,E226,E24,E266,E501,E704,W503,W504,I202", + "--max-line-length=88", +] + + +@nox.session +def lint(session: nox.sessions.Session) -> None: + if not TEST_CONFIG["enforce_type_hints"]: + session.install("flake8", "flake8-import-order") + else: + session.install("flake8", "flake8-import-order", "flake8-annotations") + + local_names = _determine_local_import_names(".") + args = FLAKE8_COMMON_ARGS + [ + "--application-import-names", + ",".join(local_names), + ".", + ] + session.run("flake8", *args) + + +# +# Black +# + + +@nox.session +def blacken(session: nox.sessions.Session) -> None: + session.install(BLACK_VERSION) + python_files = [path for path in os.listdir(".") if path.endswith(".py")] + + session.run("black", *python_files) + + +# +# Sample Tests +# + + +PYTEST_COMMON_ARGS = ["--junitxml=sponge_log.xml"] + + +def _session_tests( + session: nox.sessions.Session, post_install: Callable = None +) -> None: + # check for presence of tests + test_list = glob.glob("*_test.py") + glob.glob("test_*.py") + test_list.extend(glob.glob("tests")) + if len(test_list) == 0: + print("No tests found, skipping directory.") + else: + if TEST_CONFIG["pip_version_override"]: + pip_version = TEST_CONFIG["pip_version_override"] + session.install(f"pip=={pip_version}") + """Runs py.test for a particular project.""" + if os.path.exists("requirements.txt"): + if os.path.exists("constraints.txt"): + session.install("-r", "requirements.txt", "-c", "constraints.txt") + else: + session.install("-r", "requirements.txt") + + if os.path.exists("requirements-test.txt"): + if os.path.exists("constraints-test.txt"): + session.install( + "-r", "requirements-test.txt", "-c", "constraints-test.txt" + ) + else: + session.install("-r", "requirements-test.txt") + + if INSTALL_LIBRARY_FROM_SOURCE: + session.install("-e", _get_repo_root()) + + if post_install: + post_install(session) + + session.run( + "pytest", + *(PYTEST_COMMON_ARGS + session.posargs), + # Pytest will return 5 when no tests are collected. This can happen + # on travis where slow and flaky tests are excluded. + # See http://doc.pytest.org/en/latest/_modules/_pytest/main.html + success_codes=[0, 5], + env=get_pytest_env_vars(), + ) + + +@nox.session(python=ALL_VERSIONS) +def py(session: nox.sessions.Session) -> None: + """Runs py.test for a sample using the specified version of Python.""" + if session.python in TESTED_VERSIONS: + _session_tests(session) + else: + session.skip( + "SKIPPED: {} tests are disabled for this sample.".format(session.python) + ) + + +# +# Readmegen +# + + +def _get_repo_root() -> Optional[str]: + """ Returns the root folder of the project. """ + # Get root of this repository. Assume we don't have directories nested deeper than 10 items. + p = Path(os.getcwd()) + for i in range(10): + if p is None: + break + if Path(p / ".git").exists(): + return str(p) + # .git is not available in repos cloned via Cloud Build + # setup.py is always in the library's root, so use that instead + # https://github.com/googleapis/synthtool/issues/792 + if Path(p / "setup.py").exists(): + return str(p) + p = p.parent + raise Exception("Unable to detect repository root.") + + +GENERATED_READMES = sorted([x for x in Path(".").rglob("*.rst.in")]) + + +@nox.session +@nox.parametrize("path", GENERATED_READMES) +def readmegen(session: nox.sessions.Session, path: str) -> None: + """(Re-)generates the readme for a sample.""" + session.install("jinja2", "pyyaml") + dir_ = os.path.dirname(path) + + if os.path.exists(os.path.join(dir_, "requirements.txt")): + session.install("-r", os.path.join(dir_, "requirements.txt")) + + in_file = os.path.join(dir_, "README.rst.in") + session.run( + "python", _get_repo_root() + "/scripts/readme-gen/readme_gen.py", in_file + ) diff --git a/container/snippets/noxfile_config.py b/container/snippets/noxfile_config.py new file mode 100644 index 00000000000..16f326e5c6d --- /dev/null +++ b/container/snippets/noxfile_config.py @@ -0,0 +1,42 @@ +# Copyright 2022 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. + +# Default TEST_CONFIG_OVERRIDE for python repos. + +# You can copy this file into your directory, then it will be imported from +# the noxfile.py. + +# The source of truth: +# https://github.com/GoogleCloudPlatform/python-docs-samples/blob/main/noxfile_config.py + +TEST_CONFIG_OVERRIDE = { + # You can opt out from the test for specific Python versions. + "ignored_versions": ["2.7"], + # Old samples are opted out of enforcing Python type hints + # All new samples should feature them + "enforce_type_hints": True, + # An envvar key for determining the project id to use. Change it + # to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a + # build specific Cloud project. You can also use your own string + # to use your own Cloud project. + "gcloud_project_env": "GOOGLE_CLOUD_PROJECT", + # 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT', + # If you need to use a specific version of pip, + # change pip_version_override to the string representation + # of the version number, for example, "20.2.4" + "pip_version_override": None, + # A dictionary you want to inject into your test. Don't put any + # secrets here. These values will override predefined values. + "envs": {}, +} diff --git a/container/snippets/quickstart.py b/container/snippets/quickstart.py new file mode 100644 index 00000000000..b7cecb52e05 --- /dev/null +++ b/container/snippets/quickstart.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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. + +# [START gke_list_cluster] +import argparse +import sys + +from google.cloud import container_v1 + + +def list_clusters(project_id: str, location: str) -> None: + """List all the GKE clusters in the given GCP Project and Zone""" + + # Initialize the Cluster management client. + client = container_v1.ClusterManagerClient() + # Create a fully qualified location identifier of form `projects/{project_id}/location/{zone}'. + cluster_location = client.common_location_path(project_id, location) + # Create the request object with the location identifier. + request = {"parent": cluster_location} + list_response = client.list_clusters(request) + + print( + f"There were {len(list_response.clusters)} clusters in {location} for project {project_id}." + ) + for cluster in list_response.clusters: + print(f"- {cluster.name}") + + +# [END gke_list_cluster] + +if __name__ == "__main__": + + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter, + ) + parser.add_argument("project_id", help="Google Cloud project ID") + parser.add_argument("zone", help="GKE Cluster zone") + args = parser.parse_args() + + if len(sys.argv) != 3: + parser.print_usage() + sys.exit(1) + + list_clusters(args.project_id, args.zone) diff --git a/container/snippets/quickstart_test.py b/container/snippets/quickstart_test.py new file mode 100644 index 00000000000..7904fa5535c --- /dev/null +++ b/container/snippets/quickstart_test.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2022 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 quickstart as gke_list + +PROJECT_ID = os.environ["GOOGLE_CLOUD_PROJECT"] +ZONE = "us-central1-b" + + +def test_list_clusters(capsys: object) -> None: + output_prefix = "There were " + output_suffix = f" clusters in {ZONE} for project {PROJECT_ID}." + + gke_list.list_clusters(PROJECT_ID, ZONE) + out, _ = capsys.readouterr() + + """ + Typical output looks as follows: + + There were 3 clusters in us-central1-b for project test-project. + - cluster1 + - cluster2 + - cluster3 + + Split array by '\n' + [ + "There were 3 clusters in us-central1-b for project test-project.", + "- cluster1", + "- cluster2", + "- cluster3", + "", + ] + """ + out_lines = out.split("\n") + first_line = out_lines[0] + first_line = first_line.replace(output_prefix, "") + first_line = first_line.replace(output_suffix, "") + cluster_count = int(first_line) # get the cluster count in the first line + + assert output_suffix in out + assert cluster_count == len(out_lines) - 2 diff --git a/container/snippets/requirement-test.txt b/container/snippets/requirement-test.txt new file mode 100644 index 00000000000..2336a1237f2 --- /dev/null +++ b/container/snippets/requirement-test.txt @@ -0,0 +1,4 @@ + +backoff==1.11.1 +pytest==7.0.0 +google-api-core=2.5.0 \ No newline at end of file diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt new file mode 100644 index 00000000000..748ddb99143 --- /dev/null +++ b/container/snippets/requirements.txt @@ -0,0 +1,3 @@ +google-cloud-container==2.10.1 +backoff==1.11.1 +pytest==7.0.0 \ No newline at end of file From 4da083a387c3a189ebcc27db9ef538a313ffb3a8 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Fri, 4 Mar 2022 12:53:34 -0500 Subject: [PATCH 03/36] chore: Adding support for pytest-xdist and pytest-parallel (#204) Source-Link: https://github.com/googleapis/synthtool/commit/82f5cb283efffe96e1b6cd634738e0e7de2cd90a Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:5d8da01438ece4021d135433f2cf3227aa39ef0eaccc941d62aa35e6902832ae Co-authored-by: Owl Bot --- container/snippets/noxfile.py | 78 ++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/container/snippets/noxfile.py b/container/snippets/noxfile.py index 20cdfc62013..85f5836dba3 100644 --- a/container/snippets/noxfile.py +++ b/container/snippets/noxfile.py @@ -188,42 +188,52 @@ def _session_tests( # check for presence of tests test_list = glob.glob("*_test.py") + glob.glob("test_*.py") test_list.extend(glob.glob("tests")) + if len(test_list) == 0: print("No tests found, skipping directory.") - else: - if TEST_CONFIG["pip_version_override"]: - pip_version = TEST_CONFIG["pip_version_override"] - session.install(f"pip=={pip_version}") - """Runs py.test for a particular project.""" - if os.path.exists("requirements.txt"): - if os.path.exists("constraints.txt"): - session.install("-r", "requirements.txt", "-c", "constraints.txt") - else: - session.install("-r", "requirements.txt") - - if os.path.exists("requirements-test.txt"): - if os.path.exists("constraints-test.txt"): - session.install( - "-r", "requirements-test.txt", "-c", "constraints-test.txt" - ) - else: - session.install("-r", "requirements-test.txt") - - if INSTALL_LIBRARY_FROM_SOURCE: - session.install("-e", _get_repo_root()) - - if post_install: - post_install(session) - - session.run( - "pytest", - *(PYTEST_COMMON_ARGS + session.posargs), - # Pytest will return 5 when no tests are collected. This can happen - # on travis where slow and flaky tests are excluded. - # See http://doc.pytest.org/en/latest/_modules/_pytest/main.html - success_codes=[0, 5], - env=get_pytest_env_vars(), - ) + return + + if TEST_CONFIG["pip_version_override"]: + pip_version = TEST_CONFIG["pip_version_override"] + session.install(f"pip=={pip_version}") + """Runs py.test for a particular project.""" + concurrent_args = [] + if os.path.exists("requirements.txt"): + if os.path.exists("constraints.txt"): + session.install("-r", "requirements.txt", "-c", "constraints.txt") + else: + session.install("-r", "requirements.txt") + with open("requirements.txt") as rfile: + packages = rfile.read() + + if os.path.exists("requirements-test.txt"): + if os.path.exists("constraints-test.txt"): + session.install("-r", "requirements-test.txt", "-c", "constraints-test.txt") + else: + session.install("-r", "requirements-test.txt") + with open("requirements-test.txt") as rtfile: + packages += rtfile.read() + + if INSTALL_LIBRARY_FROM_SOURCE: + session.install("-e", _get_repo_root()) + + if post_install: + post_install(session) + + if "pytest-parallel" in packages: + concurrent_args.extend(["--workers", "auto", "--tests-per-worker", "auto"]) + elif "pytest-xdist" in packages: + concurrent_args.extend(["-n", "auto"]) + + session.run( + "pytest", + *(PYTEST_COMMON_ARGS + session.posargs + concurrent_args), + # Pytest will return 5 when no tests are collected. This can happen + # on travis where slow and flaky tests are excluded. + # See http://doc.pytest.org/en/latest/_modules/_pytest/main.html + success_codes=[0, 5], + env=get_pytest_env_vars(), + ) @nox.session(python=ALL_VERSIONS) From 4dd369c6fc9ac28110924435aa867eb4dff55bdb Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 7 Mar 2022 17:16:57 +0100 Subject: [PATCH 04/36] chore(deps): update all dependencies (#206) --- container/snippets/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index 748ddb99143..66866c5a9b7 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ -google-cloud-container==2.10.1 +google-cloud-container==2.10.5 backoff==1.11.1 -pytest==7.0.0 \ No newline at end of file +pytest==7.0.1 \ No newline at end of file From 8caf13e2029ed6a12f4e56e6d5a563a684885474 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 7 Mar 2022 22:27:09 +0100 Subject: [PATCH 05/36] chore(deps): update dependency google-cloud-container to v2.10.6 (#207) --- container/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index 66866c5a9b7..5c2e68e5ab6 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ -google-cloud-container==2.10.5 +google-cloud-container==2.10.6 backoff==1.11.1 pytest==7.0.1 \ No newline at end of file From f9687c6bec3da0824cf8b2552887620709fdd00a Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Sun, 13 Mar 2022 21:15:37 +0100 Subject: [PATCH 06/36] chore(deps): update dependency pytest to v7.1.0 (#209) --- container/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index 5c2e68e5ab6..8e73b5274ae 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ google-cloud-container==2.10.6 backoff==1.11.1 -pytest==7.0.1 \ No newline at end of file +pytest==7.1.0 \ No newline at end of file From cae7f4d91ff12b39c863efbf496a354f501b40c0 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Sat, 19 Mar 2022 11:57:34 +0100 Subject: [PATCH 07/36] chore(deps): update dependency pytest to v7.1.1 (#211) --- container/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index 8e73b5274ae..cba90b27e11 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ google-cloud-container==2.10.6 backoff==1.11.1 -pytest==7.1.0 \ No newline at end of file +pytest==7.1.1 \ No newline at end of file From 72c72dbe39579c05d4c47f55e018ab8fa06bba50 Mon Sep 17 00:00:00 2001 From: Shabir Mohamed Abdul Samadh <7249208+Shabirmean@users.noreply.github.com> Date: Mon, 21 Mar 2022 21:08:38 -0400 Subject: [PATCH 08/36] fix: test cleanup stages with try finally (#212) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: test cleanup stages with try finally * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Owl Bot --- container/snippets/create_cluster_test.py | 32 ++++++++++++----------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/container/snippets/create_cluster_test.py b/container/snippets/create_cluster_test.py index a06ab2c511d..728c07509de 100644 --- a/container/snippets/create_cluster_test.py +++ b/container/snippets/create_cluster_test.py @@ -37,21 +37,23 @@ def setup_and_tear_down() -> None: # run the tests here yield - # delete the cluster - client = gke.ClusterManagerClient() - cluster_location = client.common_location_path(PROJECT_ID, ZONE) - cluster_name = f"{cluster_location}/clusters/{CLUSTER_NAME}" - op = client.delete_cluster({"name": cluster_name}) - op_id = f"{cluster_location}/operations/{op.name}" - - # schedule a retry to ensure the cluster is deleted - @backoff.on_predicate( - backoff.expo, lambda x: x != gke.Operation.Status.DONE, max_tries=20 - ) - def wait_for_delete() -> gke.Operation.Status: - return client.get_operation({"name": op_id}).status - - wait_for_delete() + try: + # delete the cluster + client = gke.ClusterManagerClient() + cluster_location = client.common_location_path(PROJECT_ID, ZONE) + cluster_name = f"{cluster_location}/clusters/{CLUSTER_NAME}" + op = client.delete_cluster({"name": cluster_name}) + op_id = f"{cluster_location}/operations/{op.name}" + + finally: + # schedule a retry to ensure the cluster is deleted + @backoff.on_predicate( + backoff.expo, lambda x: x != gke.Operation.Status.DONE, max_tries=20 + ) + def wait_for_delete() -> gke.Operation.Status: + return client.get_operation({"name": op_id}).status + + wait_for_delete() def test_create_clusters(capsys: object) -> None: From f9080cebb72b2c0312151ab5bfb130507760ae0b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 22 Mar 2022 14:19:21 +0100 Subject: [PATCH 09/36] chore(deps): update dependency google-cloud-container to v2.10.7 (#215) --- container/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index cba90b27e11..f21d27d727c 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ -google-cloud-container==2.10.6 +google-cloud-container==2.10.7 backoff==1.11.1 pytest==7.1.1 \ No newline at end of file From c93f8dfc3d9be761b35d7db82f3510036ea6e7f0 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 28 Mar 2022 23:58:11 +0000 Subject: [PATCH 10/36] chore(python): use black==22.3.0 (#217) Source-Link: https://github.com/googleapis/synthtool/commit/6fab84af09f2cf89a031fd8671d1def6b2931b11 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:7cffbc10910c3ab1b852c05114a08d374c195a81cdec1d4a67a1d129331d0bfe --- container/snippets/create_cluster.py | 3 ++- container/snippets/delete_cluster.py | 3 ++- container/snippets/noxfile.py | 4 ++-- container/snippets/quickstart.py | 3 ++- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/container/snippets/create_cluster.py b/container/snippets/create_cluster.py index ad5ddfc3998..949c6f6e2af 100644 --- a/container/snippets/create_cluster.py +++ b/container/snippets/create_cluster.py @@ -97,7 +97,8 @@ def create_cluster(project_id: str, location: str, cluster_name: str) -> None: if __name__ == "__main__": parser = argparse.ArgumentParser( - description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter, + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, ) parser.add_argument("project_id", help="Google Cloud project ID") parser.add_argument("zone", help="GKE Cluster zone") diff --git a/container/snippets/delete_cluster.py b/container/snippets/delete_cluster.py index 0290766e9b9..405de978806 100644 --- a/container/snippets/delete_cluster.py +++ b/container/snippets/delete_cluster.py @@ -90,7 +90,8 @@ def delete_cluster(project_id: str, location: str, cluster_name: str) -> None: if __name__ == "__main__": parser = argparse.ArgumentParser( - description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter, + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, ) parser.add_argument("project_id", help="Google Cloud project ID") parser.add_argument("zone", help="GKE Cluster zone") diff --git a/container/snippets/noxfile.py b/container/snippets/noxfile.py index 85f5836dba3..25f87a215d4 100644 --- a/container/snippets/noxfile.py +++ b/container/snippets/noxfile.py @@ -29,7 +29,7 @@ # WARNING - WARNING - WARNING - WARNING - WARNING # WARNING - WARNING - WARNING - WARNING - WARNING -BLACK_VERSION = "black==19.10b0" +BLACK_VERSION = "black==22.3.0" # Copy `noxfile_config.py` to your directory and modify it instead. @@ -253,7 +253,7 @@ def py(session: nox.sessions.Session) -> None: def _get_repo_root() -> Optional[str]: - """ Returns the root folder of the project. """ + """Returns the root folder of the project.""" # Get root of this repository. Assume we don't have directories nested deeper than 10 items. p = Path(os.getcwd()) for i in range(10): diff --git a/container/snippets/quickstart.py b/container/snippets/quickstart.py index b7cecb52e05..3299a9a1e66 100644 --- a/container/snippets/quickstart.py +++ b/container/snippets/quickstart.py @@ -43,7 +43,8 @@ def list_clusters(project_id: str, location: str) -> None: if __name__ == "__main__": parser = argparse.ArgumentParser( - description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter, + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, ) parser.add_argument("project_id", help="Google Cloud project ID") parser.add_argument("zone", help="GKE Cluster zone") From 1127debf4c8d4dc6c57736fd0d6baac0c7cd1485 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Wed, 20 Apr 2022 20:53:00 -0400 Subject: [PATCH 11/36] chore(python): add nox session to sort python imports (#229) Source-Link: https://github.com/googleapis/synthtool/commit/1b71c10e20de7ed3f97f692f99a0e3399b67049f Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:00c9d764fd1cd56265f12a5ef4b99a0c9e87cf261018099141e2ca5158890416 Co-authored-by: Owl Bot --- container/snippets/create_cluster_test.py | 2 -- container/snippets/delete_cluster_test.py | 2 -- container/snippets/noxfile.py | 23 ++++++++++++++++++++++- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/container/snippets/create_cluster_test.py b/container/snippets/create_cluster_test.py index 728c07509de..75a281c9601 100644 --- a/container/snippets/create_cluster_test.py +++ b/container/snippets/create_cluster_test.py @@ -17,9 +17,7 @@ import uuid import backoff - from google.cloud import container_v1 as gke - import pytest import create_cluster as gke_create diff --git a/container/snippets/delete_cluster_test.py b/container/snippets/delete_cluster_test.py index fc7845d3465..5e187d84de1 100644 --- a/container/snippets/delete_cluster_test.py +++ b/container/snippets/delete_cluster_test.py @@ -17,10 +17,8 @@ import uuid import backoff - from google.api_core import exceptions as googleEx from google.cloud import container_v1 as gke - import pytest import delete_cluster as gke_delete diff --git a/container/snippets/noxfile.py b/container/snippets/noxfile.py index 25f87a215d4..3b3ffa5d2b0 100644 --- a/container/snippets/noxfile.py +++ b/container/snippets/noxfile.py @@ -22,7 +22,6 @@ import nox - # WARNING - WARNING - WARNING - WARNING - WARNING # WARNING - WARNING - WARNING - WARNING - WARNING # DO NOT EDIT THIS FILE EVER! @@ -30,6 +29,7 @@ # WARNING - WARNING - WARNING - WARNING - WARNING BLACK_VERSION = "black==22.3.0" +ISORT_VERSION = "isort==5.10.1" # Copy `noxfile_config.py` to your directory and modify it instead. @@ -168,12 +168,33 @@ def lint(session: nox.sessions.Session) -> None: @nox.session def blacken(session: nox.sessions.Session) -> None: + """Run black. Format code to uniform standard.""" session.install(BLACK_VERSION) python_files = [path for path in os.listdir(".") if path.endswith(".py")] session.run("black", *python_files) +# +# format = isort + black +# + + +@nox.session +def format(session: nox.sessions.Session) -> None: + """ + Run isort to sort imports. Then run black + to format code to uniform standard. + """ + session.install(BLACK_VERSION, ISORT_VERSION) + python_files = [path for path in os.listdir(".") if path.endswith(".py")] + + # Use the --fss option to sort imports using strict alphabetical order. + # See https://pycqa.github.io/isort/docs/configuration/options.html#force-sort-within-sections + session.run("isort", "--fss", *python_files) + session.run("black", *python_files) + + # # Sample Tests # From bdc99b015f8babdd024bd0f0f801bfb0e4d3c587 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Mon, 25 Apr 2022 17:10:57 +0200 Subject: [PATCH 12/36] chore(deps): update dependency pytest to v7.1.2 (#232) --- container/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index f21d27d727c..84313f4f632 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ google-cloud-container==2.10.7 backoff==1.11.1 -pytest==7.1.1 \ No newline at end of file +pytest==7.1.2 \ No newline at end of file From 7920f1727987761b4b82ba6fddb26e3b4fbe1641 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 26 Apr 2022 20:04:17 +0200 Subject: [PATCH 13/36] chore(deps): update dependency backoff to v2 (#233) --- container/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index 84313f4f632..4d805ccc796 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ google-cloud-container==2.10.7 -backoff==1.11.1 +backoff==2.0.0 pytest==7.1.2 \ No newline at end of file From 48b42ae9da87e971c61c06fca8044943d8e09eab Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 27 Apr 2022 19:32:21 +0200 Subject: [PATCH 14/36] chore(deps): update dependency backoff to v2.0.1 (#235) --- container/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index 4d805ccc796..05be978edca 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ google-cloud-container==2.10.7 -backoff==2.0.0 +backoff==2.0.1 pytest==7.1.2 \ No newline at end of file From 0d6ae6c7261221648353aea1f9fdca518951716c Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Sun, 10 Jul 2022 13:22:44 -0400 Subject: [PATCH 15/36] fix: require python 3.7+ (#266) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(python): drop python 3.6 Source-Link: https://github.com/googleapis/synthtool/commit/4f89b13af10d086458f9b379e56a614f9d6dab7b Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:e7bb19d47c13839fe8c147e50e02e8b6cf5da8edd1af8b82208cd6f66cc2829c * add api_description to .repo-metadata.json * require python 3.7+ in setup.py * remove python 3.6 sample configs * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * update api_description in .repo-metadata.json * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Owl Bot Co-authored-by: Anthonios Partheniou --- container/snippets/noxfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/noxfile.py b/container/snippets/noxfile.py index 3b3ffa5d2b0..e9eb1cbfa5d 100644 --- a/container/snippets/noxfile.py +++ b/container/snippets/noxfile.py @@ -88,7 +88,7 @@ def get_pytest_env_vars() -> Dict[str, str]: # DO NOT EDIT - automatically generated. # All versions used to test samples. -ALL_VERSIONS = ["3.6", "3.7", "3.8", "3.9", "3.10"] +ALL_VERSIONS = ["3.7", "3.8", "3.9", "3.10"] # Any default versions that should be ignored. IGNORED_VERSIONS = TEST_CONFIG["ignored_versions"] From e79b44e66e52c778b32b20dd7290e12190ade96d Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 15 Jul 2022 18:13:34 +0200 Subject: [PATCH 16/36] chore(deps): update all dependencies (#258) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(deps): update all dependencies * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * revert Co-authored-by: Owl Bot Co-authored-by: Shabir Mohamed Abdul Samadh <7249208+Shabirmean@users.noreply.github.com> Co-authored-by: Anthonios Partheniou --- container/snippets/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index 05be978edca..d5b72badaa4 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ -google-cloud-container==2.10.7 -backoff==2.0.1 +google-cloud-container==2.10.8 +backoff==2.1.2 pytest==7.1.2 \ No newline at end of file From 73bc1bd6110aa38026f358d2ad7f3dbca1ac340c Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 2 Aug 2022 15:47:58 +0200 Subject: [PATCH 17/36] chore(deps): update all dependencies (#271) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(deps): update all dependencies * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * revert Co-authored-by: Owl Bot Co-authored-by: Anthonios Partheniou --- container/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index d5b72badaa4..05990f913fc 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ -google-cloud-container==2.10.8 +google-cloud-container==2.11.0 backoff==2.1.2 pytest==7.1.2 \ No newline at end of file From 40614e6420a188a138580cc72a38dc387af96435 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 10 Aug 2022 18:58:43 +0200 Subject: [PATCH 18/36] chore(deps): update all dependencies to v2.11.1 (#276) * chore(deps): update all dependencies to v2.11.1 * revert Co-authored-by: Anthonios Partheniou --- container/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index 05990f913fc..c919bcc957a 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ -google-cloud-container==2.11.0 +google-cloud-container==2.11.1 backoff==2.1.2 pytest==7.1.2 \ No newline at end of file From ccf1085bee7b55b7895fe9d24e71d4575f3c1a09 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 16 Aug 2022 17:01:50 +0200 Subject: [PATCH 19/36] chore(deps): update dependency google-cloud-container to v2.11.2 (#280) --- container/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index c919bcc957a..19fdfe2d821 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ -google-cloud-container==2.11.1 +google-cloud-container==2.11.2 backoff==2.1.2 pytest==7.1.2 \ No newline at end of file From bf9b246d7759bcc725b276469ad8dad2d5be2def Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 6 Sep 2022 18:14:34 +0200 Subject: [PATCH 20/36] chore(deps): update dependency pytest to v7.1.3 (#291) --- container/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index 19fdfe2d821..4c783c5e3a9 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ google-cloud-container==2.11.2 backoff==2.1.2 -pytest==7.1.2 \ No newline at end of file +pytest==7.1.3 \ No newline at end of file From 490f7700a77e6ca51b045a8ca9c9a70976276f81 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 13 Sep 2022 17:32:14 +0000 Subject: [PATCH 21/36] chore: detect samples tests in nested directories (#295) Source-Link: https://github.com/googleapis/synthtool/commit/50db768f450a50d7c1fd62513c113c9bb96fd434 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-python:latest@sha256:e09366bdf0fd9c8976592988390b24d53583dd9f002d476934da43725adbb978 --- container/snippets/noxfile.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/container/snippets/noxfile.py b/container/snippets/noxfile.py index e9eb1cbfa5d..c1715136d64 100644 --- a/container/snippets/noxfile.py +++ b/container/snippets/noxfile.py @@ -207,8 +207,10 @@ def _session_tests( session: nox.sessions.Session, post_install: Callable = None ) -> None: # check for presence of tests - test_list = glob.glob("*_test.py") + glob.glob("test_*.py") - test_list.extend(glob.glob("tests")) + test_list = glob.glob("**/*_test.py", recursive=True) + glob.glob( + "**/test_*.py", recursive=True + ) + test_list.extend(glob.glob("**/tests", recursive=True)) if len(test_list) == 0: print("No tests found, skipping directory.") From 3e789789a3f4e968618ab97e96120f5ab5a0b55b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 20 Sep 2022 03:43:36 +0200 Subject: [PATCH 22/36] chore(deps): update dependency google-cloud-container to v2.12.0 (#299) --- container/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index 4c783c5e3a9..2ab3c5faf1e 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ -google-cloud-container==2.11.2 +google-cloud-container==2.12.0 backoff==2.1.2 pytest==7.1.3 \ No newline at end of file From 8f1a926931b475a74bade51a6fe0b9becfbdfcc1 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 4 Oct 2022 15:43:22 +0200 Subject: [PATCH 23/36] chore(deps): update dependency google-cloud-container to v2.12.1 (#303) --- container/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index 2ab3c5faf1e..697d33e460e 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ -google-cloud-container==2.12.0 +google-cloud-container==2.12.1 backoff==2.1.2 pytest==7.1.3 \ No newline at end of file From 566162e24a73b01742380c37ba2af83c709bd038 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Thu, 6 Oct 2022 15:35:01 +0200 Subject: [PATCH 24/36] chore(deps): update dependency backoff to v2.2.1 (#304) --- container/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index 697d33e460e..e55bbd4cf92 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ google-cloud-container==2.12.1 -backoff==2.1.2 +backoff==2.2.1 pytest==7.1.3 \ No newline at end of file From fa3cac8b363a7fd13076636af67c4cb6bfe7ccb5 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 11 Oct 2022 18:28:16 +0200 Subject: [PATCH 25/36] chore(deps): update dependency google-cloud-container to v2.12.2 (#308) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [google-cloud-container](https://togithub.com/googleapis/python-container) | `==2.12.1` -> `==2.12.2` | [![age](https://badges.renovateapi.com/packages/pypi/google-cloud-container/2.12.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/pypi/google-cloud-container/2.12.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/pypi/google-cloud-container/2.12.2/compatibility-slim/2.12.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/pypi/google-cloud-container/2.12.2/confidence-slim/2.12.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/python-container ### [`v2.12.2`](https://togithub.com/googleapis/python-container/blob/HEAD/CHANGELOG.md#​2122-httpsgithubcomgoogleapispython-containercomparev2121v2122-2022-10-07) [Compare Source](https://togithub.com/googleapis/python-container/compare/v2.12.1...v2.12.2) ##### Bug Fixes - **deps:** Allow protobuf 3.19.5 ([#​305](https://togithub.com/googleapis/python-container/issues/305)) ([728fc48](https://togithub.com/googleapis/python-container/commit/728fc485d91c113a151dea2641ccfe163a5accaf))
--- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, click this checkbox. --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/python-container). --- container/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index e55bbd4cf92..3ffa554ff33 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ -google-cloud-container==2.12.1 +google-cloud-container==2.12.2 backoff==2.2.1 pytest==7.1.3 \ No newline at end of file From 857a2adafd263c6e0f4bf2d6d1ac76b2b99e4866 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 26 Oct 2022 12:56:38 +0200 Subject: [PATCH 26/36] chore(deps): update dependency pytest to v7.2.0 (#310) --- container/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index 3ffa554ff33..aa26440bf81 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ google-cloud-container==2.12.2 backoff==2.2.1 -pytest==7.1.3 \ No newline at end of file +pytest==7.2.0 \ No newline at end of file From b2d82b819dc4b3b33472da1d74d5207da8a0cda9 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Fri, 28 Oct 2022 14:21:59 +0200 Subject: [PATCH 27/36] chore(deps): update dependency google-cloud-container to v2.13.0 (#311) --- container/snippets/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/requirements.txt b/container/snippets/requirements.txt index aa26440bf81..801bc8b41d8 100644 --- a/container/snippets/requirements.txt +++ b/container/snippets/requirements.txt @@ -1,3 +1,3 @@ -google-cloud-container==2.12.2 +google-cloud-container==2.13.0 backoff==2.2.1 pytest==7.2.0 \ No newline at end of file From ac3c35503a26dd5ae989de07d6c4e7346ccf78e2 Mon Sep 17 00:00:00 2001 From: Don McCasland Date: Wed, 2 Nov 2022 11:47:05 -0700 Subject: [PATCH 28/36] Updating license headers --- container/snippets/noxfile.py | 2 +- container/snippets/requirement-test.txt | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/container/snippets/noxfile.py b/container/snippets/noxfile.py index c1715136d64..1062eecd567 100644 --- a/container/snippets/noxfile.py +++ b/container/snippets/noxfile.py @@ -1,4 +1,4 @@ -# Copyright 2019 Google LLC +# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/container/snippets/requirement-test.txt b/container/snippets/requirement-test.txt index 2336a1237f2..52a77251763 100644 --- a/container/snippets/requirement-test.txt +++ b/container/snippets/requirement-test.txt @@ -1,4 +1,17 @@ +# Copyright 2022 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. backoff==1.11.1 pytest==7.0.0 -google-api-core=2.5.0 \ No newline at end of file +google-api-core=2.5.0 From f282fe24bae39b9b9ac37884f1d77273526b8edb Mon Sep 17 00:00:00 2001 From: Don McCasland Date: Thu, 3 Nov 2022 09:00:37 -0700 Subject: [PATCH 29/36] Update container/snippets/noxfile.py Co-authored-by: nicain --- container/snippets/noxfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/noxfile.py b/container/snippets/noxfile.py index 1062eecd567..f561017688a 100644 --- a/container/snippets/noxfile.py +++ b/container/snippets/noxfile.py @@ -88,7 +88,7 @@ def get_pytest_env_vars() -> Dict[str, str]: # DO NOT EDIT - automatically generated. # All versions used to test samples. -ALL_VERSIONS = ["3.7", "3.8", "3.9", "3.10"] +ALL_VERSIONS = ["2.7","3.7", "3.8", "3.9", "3.10"] # Any default versions that should be ignored. IGNORED_VERSIONS = TEST_CONFIG["ignored_versions"] From 53e3bce96f2f6c00a96cc0b33a5e92339dffdf40 Mon Sep 17 00:00:00 2001 From: Don McCasland Date: Thu, 3 Nov 2022 09:08:40 -0700 Subject: [PATCH 30/36] lint fix --- container/snippets/noxfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/snippets/noxfile.py b/container/snippets/noxfile.py index f561017688a..1f1a9a37d52 100644 --- a/container/snippets/noxfile.py +++ b/container/snippets/noxfile.py @@ -88,7 +88,7 @@ def get_pytest_env_vars() -> Dict[str, str]: # DO NOT EDIT - automatically generated. # All versions used to test samples. -ALL_VERSIONS = ["2.7","3.7", "3.8", "3.9", "3.10"] +ALL_VERSIONS = ["2.7", "3.7", "3.8", "3.9", "3.10"] # Any default versions that should be ignored. IGNORED_VERSIONS = TEST_CONFIG["ignored_versions"] From 10625cf8a3b6998c635d966d08272d30c50a2c1a Mon Sep 17 00:00:00 2001 From: Don McCasland Date: Thu, 3 Nov 2022 09:56:16 -0700 Subject: [PATCH 31/36] Adding CODEOWNERS definition --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d8527c0527a..e7b89ed3e76 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -28,6 +28,7 @@ /codelabs/**/* @GoogleCloudPlatform/python-samples-reviewers /composer/**/* @leahecole @rachael-ds @rafalbiegacz @GoogleCloudPlatform/python-samples-reviewers /compute/**/* @m-strzelczyk @GoogleCloudPlatform/python-samples-reviewers +/container/**/* @GoogleCloudPlatform/dee-platform-ops @GoogleCloudPlatform/python-samples-reviewers /data-science-onramp/ @leahecole @bradmiro @GoogleCloudPlatform/python-samples-reviewers /dataflow/**/* @davidcavazos @GoogleCloudPlatform/python-samples-reviewers /datastore/**/* @GoogleCloudPlatform/cloud-native-db-dpes @GoogleCloudPlatform/python-samples-reviewers From 583de91918b8f6b4d50a0e20941678042e5fc4f3 Mon Sep 17 00:00:00 2001 From: Don McCasland Date: Thu, 3 Nov 2022 12:48:14 -0700 Subject: [PATCH 32/36] Update container/CONTRIBUTING.md Co-authored-by: Dan Lee <71398022+dandhlee@users.noreply.github.com> --- container/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/CONTRIBUTING.md b/container/CONTRIBUTING.md index 34c882b6f1a..f5fe2e6baf1 100644 --- a/container/CONTRIBUTING.md +++ b/container/CONTRIBUTING.md @@ -1 +1 @@ -See https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/CONTRIBUTING.md \ No newline at end of file +See https://github.com/GoogleCloudPlatform/python-docs-samples/blob/main/CONTRIBUTING.md \ No newline at end of file From df1d2c08919d896f0cf98bb1be6b1708c67eba46 Mon Sep 17 00:00:00 2001 From: Don McCasland Date: Thu, 3 Nov 2022 12:48:20 -0700 Subject: [PATCH 33/36] Update container/AUTHORING_GUIDE.md Co-authored-by: Dan Lee <71398022+dandhlee@users.noreply.github.com> --- container/AUTHORING_GUIDE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/AUTHORING_GUIDE.md b/container/AUTHORING_GUIDE.md index 55c97b32f4c..8249522ffc2 100644 --- a/container/AUTHORING_GUIDE.md +++ b/container/AUTHORING_GUIDE.md @@ -1 +1 @@ -See https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/AUTHORING_GUIDE.md \ No newline at end of file +See https://github.com/GoogleCloudPlatform/python-docs-samples/blob/main/AUTHORING_GUIDE.md \ No newline at end of file From 0621d068be8c4e5b3b66d4067372e08e8c759080 Mon Sep 17 00:00:00 2001 From: Don McCasland Date: Thu, 3 Nov 2022 12:50:14 -0700 Subject: [PATCH 34/36] Removing noxfile --- container/snippets/noxfile.py | 312 ---------------------------------- 1 file changed, 312 deletions(-) delete mode 100644 container/snippets/noxfile.py diff --git a/container/snippets/noxfile.py b/container/snippets/noxfile.py deleted file mode 100644 index 1f1a9a37d52..00000000000 --- a/container/snippets/noxfile.py +++ /dev/null @@ -1,312 +0,0 @@ -# Copyright 2022 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 __future__ import print_function - -import glob -import os -from pathlib import Path -import sys -from typing import Callable, Dict, List, Optional - -import nox - -# WARNING - WARNING - WARNING - WARNING - WARNING -# WARNING - WARNING - WARNING - WARNING - WARNING -# DO NOT EDIT THIS FILE EVER! -# WARNING - WARNING - WARNING - WARNING - WARNING -# WARNING - WARNING - WARNING - WARNING - WARNING - -BLACK_VERSION = "black==22.3.0" -ISORT_VERSION = "isort==5.10.1" - -# Copy `noxfile_config.py` to your directory and modify it instead. - -# `TEST_CONFIG` dict is a configuration hook that allows users to -# modify the test configurations. The values here should be in sync -# with `noxfile_config.py`. Users will copy `noxfile_config.py` into -# their directory and modify it. - -TEST_CONFIG = { - # You can opt out from the test for specific Python versions. - "ignored_versions": [], - # Old samples are opted out of enforcing Python type hints - # All new samples should feature them - "enforce_type_hints": False, - # An envvar key for determining the project id to use. Change it - # to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a - # build specific Cloud project. You can also use your own string - # to use your own Cloud project. - "gcloud_project_env": "GOOGLE_CLOUD_PROJECT", - # 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT', - # If you need to use a specific version of pip, - # change pip_version_override to the string representation - # of the version number, for example, "20.2.4" - "pip_version_override": None, - # A dictionary you want to inject into your test. Don't put any - # secrets here. These values will override predefined values. - "envs": {}, -} - - -try: - # Ensure we can import noxfile_config in the project's directory. - sys.path.append(".") - from noxfile_config import TEST_CONFIG_OVERRIDE -except ImportError as e: - print("No user noxfile_config found: detail: {}".format(e)) - TEST_CONFIG_OVERRIDE = {} - -# Update the TEST_CONFIG with the user supplied values. -TEST_CONFIG.update(TEST_CONFIG_OVERRIDE) - - -def get_pytest_env_vars() -> Dict[str, str]: - """Returns a dict for pytest invocation.""" - ret = {} - - # Override the GCLOUD_PROJECT and the alias. - env_key = TEST_CONFIG["gcloud_project_env"] - # This should error out if not set. - ret["GOOGLE_CLOUD_PROJECT"] = os.environ[env_key] - - # Apply user supplied envs. - ret.update(TEST_CONFIG["envs"]) - return ret - - -# DO NOT EDIT - automatically generated. -# All versions used to test samples. -ALL_VERSIONS = ["2.7", "3.7", "3.8", "3.9", "3.10"] - -# Any default versions that should be ignored. -IGNORED_VERSIONS = TEST_CONFIG["ignored_versions"] - -TESTED_VERSIONS = sorted([v for v in ALL_VERSIONS if v not in IGNORED_VERSIONS]) - -INSTALL_LIBRARY_FROM_SOURCE = os.environ.get("INSTALL_LIBRARY_FROM_SOURCE", False) in ( - "True", - "true", -) - -# Error if a python version is missing -nox.options.error_on_missing_interpreters = True - -# -# Style Checks -# - - -def _determine_local_import_names(start_dir: str) -> List[str]: - """Determines all import names that should be considered "local". - - This is used when running the linter to insure that import order is - properly checked. - """ - file_ext_pairs = [os.path.splitext(path) for path in os.listdir(start_dir)] - return [ - basename - for basename, extension in file_ext_pairs - if extension == ".py" - or os.path.isdir(os.path.join(start_dir, basename)) - and basename not in ("__pycache__") - ] - - -# Linting with flake8. -# -# We ignore the following rules: -# E203: whitespace before ‘:’ -# E266: too many leading ‘#’ for block comment -# E501: line too long -# I202: Additional newline in a section of imports -# -# We also need to specify the rules which are ignored by default: -# ['E226', 'W504', 'E126', 'E123', 'W503', 'E24', 'E704', 'E121'] -FLAKE8_COMMON_ARGS = [ - "--show-source", - "--builtin=gettext", - "--max-complexity=20", - "--import-order-style=google", - "--exclude=.nox,.cache,env,lib,generated_pb2,*_pb2.py,*_pb2_grpc.py", - "--ignore=E121,E123,E126,E203,E226,E24,E266,E501,E704,W503,W504,I202", - "--max-line-length=88", -] - - -@nox.session -def lint(session: nox.sessions.Session) -> None: - if not TEST_CONFIG["enforce_type_hints"]: - session.install("flake8", "flake8-import-order") - else: - session.install("flake8", "flake8-import-order", "flake8-annotations") - - local_names = _determine_local_import_names(".") - args = FLAKE8_COMMON_ARGS + [ - "--application-import-names", - ",".join(local_names), - ".", - ] - session.run("flake8", *args) - - -# -# Black -# - - -@nox.session -def blacken(session: nox.sessions.Session) -> None: - """Run black. Format code to uniform standard.""" - session.install(BLACK_VERSION) - python_files = [path for path in os.listdir(".") if path.endswith(".py")] - - session.run("black", *python_files) - - -# -# format = isort + black -# - - -@nox.session -def format(session: nox.sessions.Session) -> None: - """ - Run isort to sort imports. Then run black - to format code to uniform standard. - """ - session.install(BLACK_VERSION, ISORT_VERSION) - python_files = [path for path in os.listdir(".") if path.endswith(".py")] - - # Use the --fss option to sort imports using strict alphabetical order. - # See https://pycqa.github.io/isort/docs/configuration/options.html#force-sort-within-sections - session.run("isort", "--fss", *python_files) - session.run("black", *python_files) - - -# -# Sample Tests -# - - -PYTEST_COMMON_ARGS = ["--junitxml=sponge_log.xml"] - - -def _session_tests( - session: nox.sessions.Session, post_install: Callable = None -) -> None: - # check for presence of tests - test_list = glob.glob("**/*_test.py", recursive=True) + glob.glob( - "**/test_*.py", recursive=True - ) - test_list.extend(glob.glob("**/tests", recursive=True)) - - if len(test_list) == 0: - print("No tests found, skipping directory.") - return - - if TEST_CONFIG["pip_version_override"]: - pip_version = TEST_CONFIG["pip_version_override"] - session.install(f"pip=={pip_version}") - """Runs py.test for a particular project.""" - concurrent_args = [] - if os.path.exists("requirements.txt"): - if os.path.exists("constraints.txt"): - session.install("-r", "requirements.txt", "-c", "constraints.txt") - else: - session.install("-r", "requirements.txt") - with open("requirements.txt") as rfile: - packages = rfile.read() - - if os.path.exists("requirements-test.txt"): - if os.path.exists("constraints-test.txt"): - session.install("-r", "requirements-test.txt", "-c", "constraints-test.txt") - else: - session.install("-r", "requirements-test.txt") - with open("requirements-test.txt") as rtfile: - packages += rtfile.read() - - if INSTALL_LIBRARY_FROM_SOURCE: - session.install("-e", _get_repo_root()) - - if post_install: - post_install(session) - - if "pytest-parallel" in packages: - concurrent_args.extend(["--workers", "auto", "--tests-per-worker", "auto"]) - elif "pytest-xdist" in packages: - concurrent_args.extend(["-n", "auto"]) - - session.run( - "pytest", - *(PYTEST_COMMON_ARGS + session.posargs + concurrent_args), - # Pytest will return 5 when no tests are collected. This can happen - # on travis where slow and flaky tests are excluded. - # See http://doc.pytest.org/en/latest/_modules/_pytest/main.html - success_codes=[0, 5], - env=get_pytest_env_vars(), - ) - - -@nox.session(python=ALL_VERSIONS) -def py(session: nox.sessions.Session) -> None: - """Runs py.test for a sample using the specified version of Python.""" - if session.python in TESTED_VERSIONS: - _session_tests(session) - else: - session.skip( - "SKIPPED: {} tests are disabled for this sample.".format(session.python) - ) - - -# -# Readmegen -# - - -def _get_repo_root() -> Optional[str]: - """Returns the root folder of the project.""" - # Get root of this repository. Assume we don't have directories nested deeper than 10 items. - p = Path(os.getcwd()) - for i in range(10): - if p is None: - break - if Path(p / ".git").exists(): - return str(p) - # .git is not available in repos cloned via Cloud Build - # setup.py is always in the library's root, so use that instead - # https://github.com/googleapis/synthtool/issues/792 - if Path(p / "setup.py").exists(): - return str(p) - p = p.parent - raise Exception("Unable to detect repository root.") - - -GENERATED_READMES = sorted([x for x in Path(".").rglob("*.rst.in")]) - - -@nox.session -@nox.parametrize("path", GENERATED_READMES) -def readmegen(session: nox.sessions.Session, path: str) -> None: - """(Re-)generates the readme for a sample.""" - session.install("jinja2", "pyyaml") - dir_ = os.path.dirname(path) - - if os.path.exists(os.path.join(dir_, "requirements.txt")): - session.install("-r", os.path.join(dir_, "requirements.txt")) - - in_file = os.path.join(dir_, "README.rst.in") - session.run( - "python", _get_repo_root() + "/scripts/readme-gen/readme_gen.py", in_file - ) From 0adad32433016dd2a41e7f8cdd7be963bf6916c5 Mon Sep 17 00:00:00 2001 From: Don McCasland Date: Thu, 3 Nov 2022 12:52:35 -0700 Subject: [PATCH 35/36] Adding blunderbuss --- .github/blunderbuss.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/blunderbuss.yml b/.github/blunderbuss.yml index d672483061d..bc1059f6faa 100644 --- a/.github/blunderbuss.yml +++ b/.github/blunderbuss.yml @@ -47,6 +47,10 @@ assign_issues_by: - 'api: compute' to: - m-strzelczyk +- labels: + - 'api: container' + to: + - GoogleCloudPlatform/dee-platform-ops - labels: - 'api: datascienceonramp' to: From 444c340a359b0962da06091465ef58b9fa71b728 Mon Sep 17 00:00:00 2001 From: Don McCasland Date: Fri, 4 Nov 2022 13:12:05 -0700 Subject: [PATCH 36/36] Extending test timeout to 1 hour because cluster creation takes forever --- .kokoro/tests/run_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.kokoro/tests/run_tests.sh b/.kokoro/tests/run_tests.sh index 41cbcfa1132..f7397b13444 100755 --- a/.kokoro/tests/run_tests.sh +++ b/.kokoro/tests/run_tests.sh @@ -159,7 +159,7 @@ test_prog="${PROJECT_ROOT}/.kokoro/tests/run_single_test.sh" btlr_args=( "run" - "--max-cmd-duration=30m" + "--max-cmd-duration=60m" "**/requirements.txt" )