diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml
new file mode 100644
index 000000000..0ddb512db
--- /dev/null
+++ b/.github/sync-repo-settings.yaml
@@ -0,0 +1,15 @@
+# https://github.com/googleapis/repo-automation-bots/tree/master/packages/sync-repo-settings
+# Rules for master branch protection
+branchProtectionRules:
+# Identifies the protection rule pattern. Name of the branch to be protected.
+# Defaults to `master`
+- pattern: master
+ requiresCodeOwnerReviews: true
+ requiresStrictStatusChecks: true
+ requiredStatusCheckContexts:
+ - 'Kokoro'
+ - 'cla/google'
+ - 'Samples - Lint'
+ - 'Samples - Python 3.6'
+ - 'Samples - Python 3.7'
+ - 'Samples - Python 3.8'
diff --git a/.kokoro/build.sh b/.kokoro/build.sh
index cf739ec89..35c57a936 100755
--- a/.kokoro/build.sh
+++ b/.kokoro/build.sh
@@ -41,7 +41,7 @@ python3 -m pip install --upgrade --quiet nox
python3 -m nox --version
# If this is a continuous build, send the test log to the FlakyBot.
-# See https://github.com/googleapis/repo-automation-bots/tree/master/packages/flakybot.
+# See https://github.com/googleapis/repo-automation-bots/tree/main/packages/flakybot.
if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]]; then
cleanup() {
chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot
diff --git a/.kokoro/samples/lint/common.cfg b/.kokoro/samples/lint/common.cfg
index 1af313193..15efb2062 100644
--- a/.kokoro/samples/lint/common.cfg
+++ b/.kokoro/samples/lint/common.cfg
@@ -31,4 +31,4 @@ gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples"
gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
# Use the trampoline script to run in docker.
-build_file: "python-compute/.kokoro/trampoline.sh"
\ No newline at end of file
+build_file: "python-compute/.kokoro/trampoline_v2.sh"
\ No newline at end of file
diff --git a/.kokoro/samples/python3.10/common.cfg b/.kokoro/samples/python3.10/common.cfg
new file mode 100644
index 000000000..020b122ad
--- /dev/null
+++ b/.kokoro/samples/python3.10/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.10"
+}
+
+# Declare build specific Cloud project.
+env_vars: {
+ key: "BUILD_SPECIFIC_GCLOUD_PROJECT"
+ value: "python-docs-samples-tests-310"
+}
+
+env_vars: {
+ key: "TRAMPOLINE_BUILD_FILE"
+ value: "github/python-compute/.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-compute/.kokoro/trampoline_v2.sh"
\ No newline at end of file
diff --git a/.kokoro/samples/python3.10/continuous.cfg b/.kokoro/samples/python3.10/continuous.cfg
new file mode 100644
index 000000000..a1c8d9759
--- /dev/null
+++ b/.kokoro/samples/python3.10/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.10/periodic-head.cfg b/.kokoro/samples/python3.10/periodic-head.cfg
new file mode 100644
index 000000000..343d23602
--- /dev/null
+++ b/.kokoro/samples/python3.10/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-compute/.kokoro/test-samples-against-head.sh"
+}
diff --git a/.kokoro/samples/python3.10/periodic.cfg b/.kokoro/samples/python3.10/periodic.cfg
new file mode 100644
index 000000000..71cd1e597
--- /dev/null
+++ b/.kokoro/samples/python3.10/periodic.cfg
@@ -0,0 +1,6 @@
+# Format: //devtools/kokoro/config/proto/build.proto
+
+env_vars: {
+ key: "INSTALL_LIBRARY_FROM_SOURCE"
+ value: "False"
+}
diff --git a/.kokoro/samples/python3.10/presubmit.cfg b/.kokoro/samples/python3.10/presubmit.cfg
new file mode 100644
index 000000000..a1c8d9759
--- /dev/null
+++ b/.kokoro/samples/python3.10/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
diff --git a/.kokoro/samples/python3.6/common.cfg b/.kokoro/samples/python3.6/common.cfg
index 10658818e..02ed097ab 100644
--- a/.kokoro/samples/python3.6/common.cfg
+++ b/.kokoro/samples/python3.6/common.cfg
@@ -37,4 +37,4 @@ gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples"
gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
# Use the trampoline script to run in docker.
-build_file: "python-compute/.kokoro/trampoline.sh"
\ No newline at end of file
+build_file: "python-compute/.kokoro/trampoline_v2.sh"
\ No newline at end of file
diff --git a/.kokoro/samples/python3.6/periodic.cfg b/.kokoro/samples/python3.6/periodic.cfg
index 50fec9649..71cd1e597 100644
--- a/.kokoro/samples/python3.6/periodic.cfg
+++ b/.kokoro/samples/python3.6/periodic.cfg
@@ -3,4 +3,4 @@
env_vars: {
key: "INSTALL_LIBRARY_FROM_SOURCE"
value: "False"
-}
\ No newline at end of file
+}
diff --git a/.kokoro/samples/python3.7/common.cfg b/.kokoro/samples/python3.7/common.cfg
index cd1580266..5122a3e6e 100644
--- a/.kokoro/samples/python3.7/common.cfg
+++ b/.kokoro/samples/python3.7/common.cfg
@@ -37,4 +37,4 @@ gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples"
gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
# Use the trampoline script to run in docker.
-build_file: "python-compute/.kokoro/trampoline.sh"
\ No newline at end of file
+build_file: "python-compute/.kokoro/trampoline_v2.sh"
\ No newline at end of file
diff --git a/.kokoro/samples/python3.7/periodic.cfg b/.kokoro/samples/python3.7/periodic.cfg
index 50fec9649..71cd1e597 100644
--- a/.kokoro/samples/python3.7/periodic.cfg
+++ b/.kokoro/samples/python3.7/periodic.cfg
@@ -3,4 +3,4 @@
env_vars: {
key: "INSTALL_LIBRARY_FROM_SOURCE"
value: "False"
-}
\ No newline at end of file
+}
diff --git a/.kokoro/samples/python3.8/common.cfg b/.kokoro/samples/python3.8/common.cfg
index af9384375..6ec4f85c7 100644
--- a/.kokoro/samples/python3.8/common.cfg
+++ b/.kokoro/samples/python3.8/common.cfg
@@ -37,4 +37,4 @@ gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples"
gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
# Use the trampoline script to run in docker.
-build_file: "python-compute/.kokoro/trampoline.sh"
\ No newline at end of file
+build_file: "python-compute/.kokoro/trampoline_v2.sh"
\ No newline at end of file
diff --git a/.kokoro/samples/python3.8/periodic.cfg b/.kokoro/samples/python3.8/periodic.cfg
index 50fec9649..71cd1e597 100644
--- a/.kokoro/samples/python3.8/periodic.cfg
+++ b/.kokoro/samples/python3.8/periodic.cfg
@@ -3,4 +3,4 @@
env_vars: {
key: "INSTALL_LIBRARY_FROM_SOURCE"
value: "False"
-}
\ No newline at end of file
+}
diff --git a/.kokoro/samples/python3.9/common.cfg b/.kokoro/samples/python3.9/common.cfg
index 52e4c47c0..41ba01a99 100644
--- a/.kokoro/samples/python3.9/common.cfg
+++ b/.kokoro/samples/python3.9/common.cfg
@@ -37,4 +37,4 @@ gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/python-docs-samples"
gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
# Use the trampoline script to run in docker.
-build_file: "python-compute/.kokoro/trampoline.sh"
\ No newline at end of file
+build_file: "python-compute/.kokoro/trampoline_v2.sh"
\ No newline at end of file
diff --git a/.kokoro/samples/python3.9/periodic.cfg b/.kokoro/samples/python3.9/periodic.cfg
index 50fec9649..71cd1e597 100644
--- a/.kokoro/samples/python3.9/periodic.cfg
+++ b/.kokoro/samples/python3.9/periodic.cfg
@@ -3,4 +3,4 @@
env_vars: {
key: "INSTALL_LIBRARY_FROM_SOURCE"
value: "False"
-}
\ No newline at end of file
+}
diff --git a/.kokoro/test-samples-against-head.sh b/.kokoro/test-samples-against-head.sh
index fd9f81e69..ba3a707b0 100755
--- a/.kokoro/test-samples-against-head.sh
+++ b/.kokoro/test-samples-against-head.sh
@@ -23,6 +23,4 @@ set -eo pipefail
# Enables `**` to include files nested inside sub-folders
shopt -s globstar
-cd github/python-compute
-
exec .kokoro/test-samples-impl.sh
diff --git a/.kokoro/test-samples-impl.sh b/.kokoro/test-samples-impl.sh
index 311a8d54b..8a324c9c7 100755
--- a/.kokoro/test-samples-impl.sh
+++ b/.kokoro/test-samples-impl.sh
@@ -80,7 +80,7 @@ for file in samples/**/requirements.txt; do
EXIT=$?
# If this is a periodic build, send the test log to the FlakyBot.
- # See https://github.com/googleapis/repo-automation-bots/tree/master/packages/flakybot.
+ # See https://github.com/googleapis/repo-automation-bots/tree/main/packages/flakybot.
if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then
chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot
$KOKORO_GFILE_DIR/linux_amd64/flakybot
diff --git a/.kokoro/test-samples.sh b/.kokoro/test-samples.sh
index 526ddd123..11c042d34 100755
--- a/.kokoro/test-samples.sh
+++ b/.kokoro/test-samples.sh
@@ -24,8 +24,6 @@ set -eo pipefail
# Enables `**` to include files nested inside sub-folders
shopt -s globstar
-cd github/python-compute
-
# Run periodic samples tests at latest release
if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then
# preserving the test runner implementation.
diff --git a/.repo-metadata.json b/.repo-metadata.json
index d40bc1e22..46cf133ca 100644
--- a/.repo-metadata.json
+++ b/.repo-metadata.json
@@ -1,13 +1,15 @@
{
- "name": "compute",
- "name_pretty": "Compute Engine",
- "product_documentation": "https://cloud.google.com/compute/",
- "client_documentation": "https://googleapis.dev/python/compute/latest",
- "issue_tracker": "https://issuetracker.google.com/issues/new?component=187134&template=0",
- "release_level": "alpha",
- "language": "python",
- "library_type": "GAPIC_AUTO",
- "repo": "googleapis/python-compute",
- "distribution_name": "google-cloud-compute",
- "api_id": "compute.googleapis.com"
+ "name": "compute",
+ "name_pretty": "Compute Engine",
+ "product_documentation": "https://cloud.google.com/compute/",
+ "client_documentation": "https://googleapis.dev/python/compute/latest",
+ "issue_tracker": "https://issuetracker.google.com/issues/new?component=187134&template=0",
+ "release_level": "alpha",
+ "language": "python",
+ "library_type": "GAPIC_AUTO",
+ "repo": "googleapis/python-compute",
+ "distribution_name": "google-cloud-compute",
+ "api_id": "compute.googleapis.com",
+ "codeowner_team": "@googleapis/actools",
+ "default_version": "v1"
}
diff --git a/.trampolinerc b/.trampolinerc
index 383b6ec89..0eee72ab6 100644
--- a/.trampolinerc
+++ b/.trampolinerc
@@ -16,15 +16,26 @@
# Add required env vars here.
required_envvars+=(
- "STAGING_BUCKET"
- "V2_STAGING_BUCKET"
)
# Add env vars which are passed down into the container here.
pass_down_envvars+=(
+ "NOX_SESSION"
+ ###############
+ # Docs builds
+ ###############
"STAGING_BUCKET"
"V2_STAGING_BUCKET"
- "NOX_SESSION"
+ ##################
+ # Samples builds
+ ##################
+ "INSTALL_LIBRARY_FROM_SOURCE"
+ "RUN_TESTS_SESSION"
+ "BUILD_SPECIFIC_GCLOUD_PROJECT"
+ # Target directories.
+ "RUN_TESTS_DIRS"
+ # The nox session to run.
+ "RUN_TESTS_SESSION"
)
# Prevent unintentional override on the default image.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ccd4ecd1a..cffccc924 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,23 @@
# Changelog
+## [0.6.0](https://www.github.com/googleapis/python-compute/compare/v0.5.0...v0.6.0) (2021-10-14)
+
+
+### Features
+
+* add support for python 3.10 ([#131](https://www.github.com/googleapis/python-compute/issues/131)) ([703ac17](https://www.github.com/googleapis/python-compute/commit/703ac1703bc159dcd81e96759606ad896f125996))
+
+
+### Bug Fixes
+
+* **compute:** Updated max_results to 100 to avoid too many API calls ([#108](https://www.github.com/googleapis/python-compute/issues/108)) ([691e38e](https://www.github.com/googleapis/python-compute/commit/691e38e19d2c5dc7223e35b681c17b1194302e1b))
+* correct region tag formatting ([#102](https://www.github.com/googleapis/python-compute/issues/102)) ([8339c00](https://www.github.com/googleapis/python-compute/commit/8339c00db7eb693813511de7e3d7f8b28b709395))
+
+
+### Documentation
+
+* **samples:** Adding pagination sample. ([#78](https://www.github.com/googleapis/python-compute/issues/78)) ([db0404c](https://www.github.com/googleapis/python-compute/commit/db0404c7849147dcc5bafe797e23cdb5364b381b))
+
## [0.5.0](https://www.github.com/googleapis/python-compute/compare/v0.4.2...v0.5.0) (2021-08-09)
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 6d765f117..d0f0160e7 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -22,7 +22,7 @@ In order to add a feature:
documentation.
- The feature must work fully on the following CPython versions:
- 3.6, 3.7, 3.8 and 3.9 on both UNIX and Windows.
+ 3.6, 3.7, 3.8, 3.9 and 3.10 on both UNIX and Windows.
- The feature must not add unnecessary dependencies (where
"unnecessary" is of course subjective, but new dependencies should
@@ -50,9 +50,9 @@ You'll have to create a development environment using a Git checkout:
# Configure remotes such that you can pull changes from the googleapis/python-compute
# repository into your local repository.
$ git remote add upstream git@github.com:googleapis/python-compute.git
- # fetch and merge changes from upstream into master
+ # fetch and merge changes from upstream into main
$ git fetch upstream
- $ git merge upstream/master
+ $ git merge upstream/main
Now your local repo is set up such that you will push changes to your GitHub
repo, from which you can submit a pull request.
@@ -72,7 +72,7 @@ We use `nox `__ to instrument our tests.
- To run a single unit test::
- $ nox -s unit-3.9 -- -k
+ $ nox -s unit-3.10 -- -k
.. note::
@@ -110,12 +110,12 @@ Coding Style
variables::
export GOOGLE_CLOUD_TESTING_REMOTE="upstream"
- export GOOGLE_CLOUD_TESTING_BRANCH="master"
+ export GOOGLE_CLOUD_TESTING_BRANCH="main"
By doing this, you are specifying the location of the most up-to-date
- version of ``python-compute``. The the suggested remote name ``upstream``
- should point to the official ``googleapis`` checkout and the
- the branch should be the main branch on that remote (``master``).
+ version of ``python-compute``. The
+ remote name ``upstream`` should point to the official ``googleapis``
+ checkout and the branch should be the default branch on that remote (``main``).
- This repository contains configuration for the
`pre-commit `__ tool, which automates checking
@@ -209,7 +209,7 @@ The `description on PyPI`_ for the project comes directly from the
``README``. Due to the reStructuredText (``rst``) parser used by
PyPI, relative links which will work on GitHub (e.g. ``CONTRIBUTING.rst``
instead of
-``https://github.com/googleapis/python-compute/blob/master/CONTRIBUTING.rst``)
+``https://github.com/googleapis/python-compute/blob/main/CONTRIBUTING.rst``)
may cause problems creating links or rendering the description.
.. _description on PyPI: https://pypi.org/project/google-cloud-compute
@@ -225,16 +225,18 @@ We support:
- `Python 3.7`_
- `Python 3.8`_
- `Python 3.9`_
+- `Python 3.10`_
.. _Python 3.6: https://docs.python.org/3.6/
.. _Python 3.7: https://docs.python.org/3.7/
.. _Python 3.8: https://docs.python.org/3.8/
.. _Python 3.9: https://docs.python.org/3.9/
+.. _Python 3.10: https://docs.python.org/3.10/
Supported versions can be found in our ``noxfile.py`` `config`_.
-.. _config: https://github.com/googleapis/python-compute/blob/master/noxfile.py
+.. _config: https://github.com/googleapis/python-compute/blob/main/noxfile.py
We also explicitly decided to support Python 3 beginning with version 3.6.
diff --git a/README.rst b/README.rst
index 506ef9846..efa504065 100644
--- a/README.rst
+++ b/README.rst
@@ -9,7 +9,7 @@ Python Client for Compute Engine
- `Product Documentation`_
.. |alpha| image:: https://img.shields.io/badge/support-alpha-orange.svg
- :target: https://github.com/googleapis/google-cloud-python/blob/master/README.rst#alpha-support
+ :target: https://github.com/googleapis/google-cloud-python/blob/main/README.rst#alpha-support
.. |pypi| image:: https://img.shields.io/pypi/v/google-cloud-compute.svg
:target: https://pypi.org/project/google-cloud-compute/
.. |versions| image:: https://img.shields.io/pypi/pyversions/google-cloud-compute.svg
@@ -79,4 +79,4 @@ Next Steps
APIs that we cover.
.. _Compute Engine API Product documentation: https://cloud.google.com/compute/
-.. _README: https://github.com/googleapis/google-cloud-python/blob/master/README.rst
\ No newline at end of file
+.. _README: https://github.com/googleapis/google-cloud-python/blob/main/README.rst
\ No newline at end of file
diff --git a/docs/conf.py b/docs/conf.py
index 3eda874a8..14a089750 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -76,8 +76,8 @@
# The encoding of source files.
# source_encoding = 'utf-8-sig'
-# The master toctree document.
-master_doc = "index"
+# The root toctree document.
+root_doc = "index"
# General information about the project.
project = "google-cloud-compute"
@@ -110,6 +110,7 @@
# directories to ignore when looking for source files.
exclude_patterns = [
"_build",
+ "**/.nox/**/*",
"samples/AUTHORING_GUIDE.md",
"samples/CONTRIBUTING.md",
"samples/snippets/README.rst",
@@ -279,7 +280,7 @@
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(
- master_doc,
+ root_doc,
"google-cloud-compute.tex",
"google-cloud-compute Documentation",
author,
@@ -314,7 +315,7 @@
# (source start file, name, description, authors, manual section).
man_pages = [
(
- master_doc,
+ root_doc,
"google-cloud-compute",
"google-cloud-compute Documentation",
[author],
@@ -333,7 +334,7 @@
# dir menu entry, description, category)
texinfo_documents = [
(
- master_doc,
+ root_doc,
"google-cloud-compute",
"google-cloud-compute Documentation",
author,
diff --git a/noxfile.py b/noxfile.py
index 178f3a993..2353eb7e0 100644
--- a/noxfile.py
+++ b/noxfile.py
@@ -29,7 +29,7 @@
DEFAULT_PYTHON_VERSION = "3.8"
SYSTEM_TEST_PYTHON_VERSIONS = ["3.8"]
-UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9"]
+UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9", "3.10"]
CURRENT_DIRECTORY = pathlib.Path(__file__).parent.absolute()
@@ -84,9 +84,15 @@ def default(session):
constraints_path = str(
CURRENT_DIRECTORY / "testing" / f"constraints-{session.python}.txt"
)
- session.install("asyncmock", "pytest-asyncio", "-c", constraints_path)
-
- session.install("mock", "pytest", "pytest-cov", "-c", constraints_path)
+ session.install(
+ "mock",
+ "asyncmock",
+ "pytest",
+ "pytest-cov",
+ "pytest-asyncio",
+ "-c",
+ constraints_path,
+ )
session.install("-e", ".", "-c", constraints_path)
diff --git a/renovate.json b/renovate.json
index c04895563..c21036d38 100644
--- a/renovate.json
+++ b/renovate.json
@@ -1,6 +1,9 @@
{
"extends": [
- "config:base", ":preserveSemverRanges"
+ "config:base",
+ "group:all",
+ ":preserveSemverRanges",
+ ":disableDependencyDashboard"
],
"ignorePaths": [".pre-commit-config.yaml"],
"pip_requirements": {
diff --git a/samples/snippets/noxfile.py b/samples/snippets/noxfile.py
index 6a8ccdae2..93a9122cc 100644
--- a/samples/snippets/noxfile.py
+++ b/samples/snippets/noxfile.py
@@ -39,17 +39,15 @@
TEST_CONFIG = {
# You can opt out from the test for specific Python versions.
- 'ignored_versions': ["2.7"],
-
+ "ignored_versions": [],
# Old samples are opted out of enforcing Python type hints
# All new samples should feature them
- 'enforce_type_hints': False,
-
+ "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": "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
@@ -57,13 +55,13 @@
"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': {},
+ "envs": {},
}
try:
# Ensure we can import noxfile_config in the project's directory.
- sys.path.append('.')
+ sys.path.append(".")
from noxfile_config import TEST_CONFIG_OVERRIDE
except ImportError as e:
print("No user noxfile_config found: detail: {}".format(e))
@@ -78,25 +76,32 @@ def get_pytest_env_vars() -> Dict[str, str]:
ret = {}
# Override the GCLOUD_PROJECT and the alias.
- env_key = TEST_CONFIG['gcloud_project_env']
+ env_key = TEST_CONFIG["gcloud_project_env"]
# This should error out if not set.
- ret['GOOGLE_CLOUD_PROJECT'] = os.environ[env_key]
+ ret["GOOGLE_CLOUD_PROJECT"] = os.environ[env_key]
# Apply user supplied envs.
- ret.update(TEST_CONFIG['envs'])
+ ret.update(TEST_CONFIG["envs"])
return ret
# DO NOT EDIT - automatically generated.
-# All versions used to tested samples.
-ALL_VERSIONS = ["2.7", "3.6", "3.7", "3.8", "3.9"]
+# 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']
+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 = bool(os.environ.get("INSTALL_LIBRARY_FROM_SOURCE", False))
+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
#
@@ -141,7 +146,7 @@ def _determine_local_import_names(start_dir: str) -> List[str]:
@nox.session
def lint(session: nox.sessions.Session) -> None:
- if not TEST_CONFIG['enforce_type_hints']:
+ if not TEST_CONFIG["enforce_type_hints"]:
session.install("flake8", "flake8-import-order")
else:
session.install("flake8", "flake8-import-order", "flake8-annotations")
@@ -150,9 +155,11 @@ def lint(session: nox.sessions.Session) -> None:
args = FLAKE8_COMMON_ARGS + [
"--application-import-names",
",".join(local_names),
- "."
+ ".",
]
session.run("flake8", *args)
+
+
#
# Black
#
@@ -165,6 +172,7 @@ def blacken(session: nox.sessions.Session) -> None:
session.run("black", *python_files)
+
#
# Sample Tests
#
@@ -173,7 +181,9 @@ def blacken(session: nox.sessions.Session) -> None:
PYTEST_COMMON_ARGS = ["--junitxml=sponge_log.xml"]
-def _session_tests(session: nox.sessions.Session, post_install: Callable = None) -> None:
+def _session_tests(
+ session: nox.sessions.Session, post_install: Callable = None
+) -> None:
if TEST_CONFIG["pip_version_override"]:
pip_version = TEST_CONFIG["pip_version_override"]
session.install(f"pip=={pip_version}")
@@ -203,7 +213,7 @@ def _session_tests(session: nox.sessions.Session, post_install: Callable = None)
# 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()
+ env=get_pytest_env_vars(),
)
@@ -213,9 +223,9 @@ def py(session: nox.sessions.Session) -> None:
if session.python in TESTED_VERSIONS:
_session_tests(session)
else:
- session.skip("SKIPPED: {} tests are disabled for this sample.".format(
- session.python
- ))
+ session.skip(
+ "SKIPPED: {} tests are disabled for this sample.".format(session.python)
+ )
#
diff --git a/samples/snippets/quickstart.py b/samples/snippets/quickstart.py
index 341217e62..74226cda3 100644
--- a/samples/snippets/quickstart.py
+++ b/samples/snippets/quickstart.py
@@ -73,9 +73,14 @@ def list_all_instances(
iterable collections of Instance objects as values.
"""
instance_client = compute_v1.InstancesClient()
- agg_list = instance_client.aggregated_list(project=project_id)
+ # Use the `max_results` parameter to limit the number of results that the API returns per response page.
+ request = compute_v1.AggregatedListInstancesRequest(project=project_id, max_results=5)
+ agg_list = instance_client.aggregated_list(request=request)
all_instances = {}
print("Instances found:")
+ # Despite using the `max_results` parameter, you don't need to handle the pagination
+ # yourself. The returned `AggregatedListPager` object handles pagination
+ # automatically, returning separated pages as you iterate over the results.
for zone, response in agg_list:
if response.instances:
all_instances[zone] = response.instances
@@ -116,6 +121,7 @@ def create_instance(
Instance object.
"""
instance_client = compute_v1.InstancesClient()
+ operation_client = compute_v1.ZoneOperationsClient()
# Describe the size and source image of the boot disk to attach to the instance.
disk = compute_v1.AttachedDisk()
@@ -150,8 +156,7 @@ def create_instance(
# Wait for the create operation to complete.
print(f"Creating the {instance_name} instance in {zone}...")
operation = instance_client.insert(request=request)
- if operation.status == compute_v1.Operation.Status.RUNNING:
- operation_client = compute_v1.ZoneOperationsClient()
+ while operation.status != compute_v1.Operation.Status.DONE:
operation = operation_client.wait(
operation=operation.name, zone=zone, project=project_id
)
@@ -175,13 +180,13 @@ def delete_instance(project_id: str, zone: str, machine_name: str) -> None:
machine_name: name of the machine you want to delete.
"""
instance_client = compute_v1.InstancesClient()
+ operation_client = compute_v1.ZoneOperationsClient()
print(f"Deleting {machine_name} from {zone}...")
operation = instance_client.delete(
project=project_id, zone=zone, instance=machine_name
)
- if operation.status == compute_v1.Operation.Status.RUNNING:
- operation_client = compute_v1.ZoneOperationsClient()
+ while operation.status != compute_v1.Operation.Status.DONE:
operation = operation_client.wait(
operation=operation.name, zone=zone, project=project_id
)
diff --git a/samples/snippets/requirements-test.txt b/samples/snippets/requirements-test.txt
index 444dff8b3..db0c32744 100644
--- a/samples/snippets/requirements-test.txt
+++ b/samples/snippets/requirements-test.txt
@@ -1,2 +1,2 @@
-pytest==6.2.4
-google-cloud-storage==1.41.1
\ No newline at end of file
+pytest==6.2.5
+google-cloud-storage==1.42.3
\ No newline at end of file
diff --git a/samples/snippets/requirements.txt b/samples/snippets/requirements.txt
index 102dfdfe8..209ab22d7 100644
--- a/samples/snippets/requirements.txt
+++ b/samples/snippets/requirements.txt
@@ -1 +1 @@
-google-cloud-compute==0.4.2
\ No newline at end of file
+google-cloud-compute==0.5.0
\ No newline at end of file
diff --git a/samples/snippets/sample_default_values.py b/samples/snippets/sample_default_values.py
index 5f14e2a77..53dbaf62d 100644
--- a/samples/snippets/sample_default_values.py
+++ b/samples/snippets/sample_default_values.py
@@ -59,7 +59,12 @@ def set_usage_export_bucket(project_id: str, bucket_name: str,
project=project_id, usage_export_location_resource=usage_export_location)
op_client = compute_v1.GlobalOperationsClient()
- op_client.wait(project=project_id, operation=operation.name)
+
+ while operation.status != compute_v1.Operation.Status.DONE:
+ operation = op_client.wait(
+ operation=operation.name, project=project_id
+ )
+
# [END compute_usage_report_set]
@@ -113,5 +118,9 @@ def disable_usage_export(project_id: str) -> None:
project=project_id, usage_export_location_resource=None)
op_client = compute_v1.GlobalOperationsClient()
- op_client.wait(project=project_id, operation=operation.name)
+
+ while operation.status != compute_v1.Operation.Status.DONE:
+ operation = op_client.wait(
+ operation=operation.name, project=project_id
+ )
# [END compute_usage_report_disable]
diff --git a/samples/snippets/sample_firewall.py b/samples/snippets/sample_firewall.py
new file mode 100644
index 000000000..01a60c3d8
--- /dev/null
+++ b/samples/snippets/sample_firewall.py
@@ -0,0 +1,175 @@
+# Copyright 2021 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 Iterable
+
+# [START compute_firewall_list]
+# [START compute_firewall_create]
+# [START compute_firewall_patch]
+# [START compute_firewall_delete]
+import google.cloud.compute_v1 as compute_v1
+# [END compute_firewall_delete]
+# [END compute_firewall_patch]
+# [END compute_firewall_create]
+# [END compute_firewall_list]
+
+
+# [START compute_firewall_list]
+def list_firewall_rules(project_id: str) -> Iterable:
+ """
+ Return a list of all the firewall rules in specified project. Also prints the
+ list of firewall names and their descriptions.
+
+ Args:
+ project_id: project ID or project number of the Cloud project you want to use.
+
+ Returns:
+ A flat list of all firewall rules defined for given project.
+ """
+ firewall_client = compute_v1.FirewallsClient()
+ firewalls_list = firewall_client.list(project=project_id)
+
+ for firewall in firewalls_list:
+ print(f" - {firewall.name}: {firewall.description}")
+
+ return firewalls_list
+# [END compute_firewall_list]
+
+
+def print_firewall_rule(project_id: str, firewall_rule_name: str):
+ firewall_client = compute_v1.FirewallsClient()
+ print(firewall_client.get(project=project_id, firewall=firewall_rule_name))
+
+
+# [START compute_firewall_create]
+def create_firewall_rule(
+ project_id: str, firewall_rule_name: str, network: str = "global/networks/default"
+):
+ """
+ Creates a simple firewall rule allowing for incoming HTTP and HTTPS access from the entire Internet.
+
+ Args:
+ project_id: project ID or project number of the Cloud project you want to use.
+ firewall_rule_name: name of the rule that is created.
+ network: name of the network the rule will be applied to. Available name formats:
+ * https://www.googleapis.com/compute/v1/projects/{project_id}/global/networks/{network}
+ * projects/{project_id}/global/networks/{network}
+ * global/networks/{network}
+ """
+ firewall_rule = compute_v1.Firewall()
+ firewall_rule.name = firewall_rule_name
+ firewall_rule.direction = compute_v1.Firewall.Direction.INGRESS
+
+ tcp_80_443_allowed = compute_v1.Allowed()
+ tcp_80_443_allowed.I_p_protocol = "tcp"
+ tcp_80_443_allowed.ports = ["80", "443"]
+
+ firewall_rule.allowed = [tcp_80_443_allowed]
+ firewall_rule.source_ranges = ["0.0.0.0/0"]
+ firewall_rule.network = network
+ firewall_rule.description = "Allowing TCP traffic on port 80 and 443 from Internet."
+
+ # Note that the default value of priority for the firewall API is 1000.
+ # If you check the value of `firewall_rule.priority` at this point it
+ # will be equal to 0, however it is not treated as "set" by the library and thus
+ # the default will be applied to the new rule. If you want to create a rule that
+ # has priority == 0, you need to explicitly set it so:
+
+ # firewall_rule.priority = 0
+
+ firewall_client = compute_v1.FirewallsClient()
+ op = firewall_client.insert(project=project_id, firewall_resource=firewall_rule)
+
+ op_client = compute_v1.GlobalOperationsClient()
+ op_client.wait(project=project_id, operation=op.name)
+
+ return
+# [END compute_firewall_create]
+
+
+# [START compute_firewall_patch]
+def patch_firewall_priority(project_id: str, firewall_rule_name: str, priority: int):
+ """
+ Modifies the priority of a given firewall rule.
+
+ Args:
+ project_id: project ID or project number of the Cloud project you want to use.
+ firewall_rule_name: name of the rule you want to modify.
+ priority: the new priority to be set for the rule.
+ """
+ firewall_rule = compute_v1.Firewall()
+ firewall_rule.priority = priority
+
+ # The patch operation doesn't require the full definition of a Firewall object. It will only update
+ # the values that were set in it, in this case it will only change the priority.
+ firewall_client = compute_v1.FirewallsClient()
+ operation = firewall_client.patch(
+ project=project_id, firewall=firewall_rule_name, firewall_resource=firewall_rule
+ )
+
+ operation_client = compute_v1.GlobalOperationsClient()
+ operation_client.wait(project=project_id, operation=operation.name)
+ return
+# [END compute_firewall_patch]
+
+
+# [START compute_firewall_delete]
+def delete_firewall_rule(project_id: str, firewall_rule_name: str):
+ """
+ Deleted a firewall rule from the project.
+
+ Args:
+ project_id: project ID or project number of the Cloud project you want to use.
+ firewall_rule_name: name of the firewall rule you want to delete.
+ """
+ firewall_client = compute_v1.FirewallsClient()
+ operation = firewall_client.delete(project=project_id, firewall=firewall_rule_name)
+
+ operation_client = compute_v1.GlobalOperationsClient()
+ operation_client.wait(project=project_id, operation=operation.name)
+ return
+# [END compute_firewall_delete]
+
+
+if __name__ == "__main__":
+ import google.auth
+ import google.auth.exceptions
+
+ try:
+ default_project_id = google.auth.default()[1]
+ print(f"Using project {default_project_id}.")
+ except google.auth.exceptions.DefaultCredentialsError:
+ print(
+ "Please use `gcloud auth application-default login` "
+ "or set GOOGLE_APPLICATION_CREDENTIALS to use this script."
+ )
+ else:
+ import uuid
+
+ rule_name = "firewall-sample-" + uuid.uuid4().hex[:10]
+ print(f"Creating firewall rule {rule_name}...")
+ # The rule will be created with default priority of 1000.
+ create_firewall_rule(default_project_id, rule_name)
+ try:
+ print("Rule created:")
+ print_firewall_rule(default_project_id, rule_name)
+ print("Updating rule priority to 10...")
+ patch_firewall_priority(default_project_id, rule_name, 10)
+ print("Rule updated: ")
+ print_firewall_rule(default_project_id, rule_name)
+ print(f"Deleting rule {rule_name}...")
+ finally:
+ delete_firewall_rule(default_project_id, rule_name)
+ print("Done.")
diff --git a/samples/snippets/sample_pagination.py b/samples/snippets/sample_pagination.py
new file mode 100644
index 000000000..2782a3c3a
--- /dev/null
+++ b/samples/snippets/sample_pagination.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+
+# Copyright 2021 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 compute_images_list_page]
+# [START compute_images_list]
+import google.cloud.compute_v1 as compute_v1
+# [END compute_images_list]
+# [END compute_images_list_page]
+
+
+# [START compute_images_list]
+def print_images_list(project: str) -> None:
+ """
+ Prints a list of all non-deprecated image names available in given project.
+
+ Args:
+ project: project ID or project number of the Cloud project you want to list images from.
+
+ Returns:
+ None.
+ """
+ images_client = compute_v1.ImagesClient()
+ # Listing only non-deprecated images to reduce the size of the reply.
+ images_list_request = compute_v1.ListImagesRequest(project=project, max_results=100,
+ filter="deprecated.state != DEPRECATED")
+
+ # Although the `max_results` parameter is specified in the request, the iterable returned
+ # by the `list()` method hides the pagination mechanic. The library makes multiple
+ # requests to the API for you, so you can simply iterate over all the images.
+ for img in images_client.list(request=images_list_request):
+ print(f" - {img.name}")
+# [END compute_images_list]
+
+
+# [START compute_images_list_page]
+def print_images_list_by_page(project: str, page_size: int = 10) -> None:
+ """
+ Prints a list of all non-deprecated image names available in a given project,
+ divided into pages as returned by the Compute Engine API.
+
+ Args:
+ project: project ID or project number of the Cloud project you want to list images from.
+ page_size: size of the pages you want the API to return on each call.
+
+ Returns:
+ None.
+ """
+ images_client = compute_v1.ImagesClient()
+ # Listing only non-deprecated images to reduce the size of the reply.
+ images_list_request = compute_v1.ListImagesRequest(project=project, max_results=page_size,
+ filter="deprecated.state != DEPRECATED")
+
+ # Use the `pages` attribute of returned iterable to have more granular control of
+ # iteration over paginated results from the API. Each time you want to access the
+ # next page, the library retrieves that page from the API.
+ for page_num, page in enumerate(images_client.list(request=images_list_request).pages, start=1):
+ print(f"Page {page_num}: ")
+ for img in page.items:
+ print(f" - {img.name}")
+# [END compute_images_list_page]
+
+
+if __name__ == '__main__':
+ print("=================== Flat list of images ===================")
+ print_images_list('windows-sql-cloud')
+ print("================= Paginated list of images ================")
+ print_images_list_by_page('windows-sql-cloud', 5)
diff --git a/samples/snippets/sample_start_stop.py b/samples/snippets/sample_start_stop.py
index 815f84ce2..d5bee8f05 100644
--- a/samples/snippets/sample_start_stop.py
+++ b/samples/snippets/sample_start_stop.py
@@ -35,7 +35,10 @@ def start_instance(project_id: str, zone: str, instance_name: str):
op = instance_client.start(project=project_id, zone=zone, instance=instance_name)
- op_client.wait(project=project_id, zone=zone, operation=op.name)
+ while op.status != compute_v1.Operation.Status.DONE:
+ op = op_client.wait(
+ operation=op.name, zone=zone, project=project_id
+ )
return
# [END compute_start_instance]
@@ -71,7 +74,10 @@ def start_instance_with_encryption_key(project_id: str, zone: str, instance_name
op = instance_client.start_with_encryption_key(project=project_id, zone=zone, instance=instance_name,
instances_start_with_encryption_key_request_resource=enc_data)
- op_client.wait(project=project_id, zone=zone, operation=op.name)
+ while op.status != compute_v1.Operation.Status.DONE:
+ op = op_client.wait(
+ operation=op.name, zone=zone, project=project_id
+ )
return
# [END compute_start_enc_instance]
@@ -91,7 +97,10 @@ def stop_instance(project_id: str, zone: str, instance_name: str):
op = instance_client.stop(project=project_id, zone=zone, instance=instance_name)
- op_client.wait(project=project_id, zone=zone, operation=op.name)
+ while op.status != compute_v1.Operation.Status.DONE:
+ op = op_client.wait(
+ operation=op.name, zone=zone, project=project_id
+ )
return
# [END compute_stop_instance]
@@ -111,6 +120,9 @@ def reset_instance(project_id: str, zone: str, instance_name: str):
op = instance_client.reset(project=project_id, zone=zone, instance=instance_name)
- op_client.wait(project=project_id, zone=zone, operation=op.name)
+ while op.status != compute_v1.Operation.Status.DONE:
+ op = op_client.wait(
+ operation=op.name, zone=zone, project=project_id
+ )
return
# [END compute_reset_instance]
diff --git a/samples/snippets/test_sample_firewall.py b/samples/snippets/test_sample_firewall.py
new file mode 100644
index 000000000..4e7384648
--- /dev/null
+++ b/samples/snippets/test_sample_firewall.py
@@ -0,0 +1,71 @@
+# Copyright 2021 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 time
+import uuid
+
+import google.auth
+from google.cloud import compute_v1
+import pytest
+
+
+from sample_firewall import (
+ create_firewall_rule,
+ delete_firewall_rule,
+ list_firewall_rules,
+ patch_firewall_priority,
+)
+
+PROJECT = google.auth.default()[1]
+
+
+@pytest.fixture
+def firewall_rule():
+ firewall_rule = compute_v1.Firewall()
+ firewall_rule.name = "firewall-sample-test" + uuid.uuid4().hex[:10]
+ firewall_rule.direction = compute_v1.Firewall.Direction.INGRESS
+ tcp_80_443_allowed = compute_v1.Allowed()
+ tcp_80_443_allowed.I_p_protocol = "tcp"
+ tcp_80_443_allowed.ports = ["80"]
+ firewall_rule.allowed = [tcp_80_443_allowed]
+ firewall_rule.source_ranges = ["0.0.0.0/0"]
+ firewall_rule.network = "global/networks/default"
+ firewall_rule.description = "Rule generated by Python sample test fixture."
+
+ firewall_client = compute_v1.FirewallsClient()
+ op = firewall_client.insert(project=PROJECT, firewall_resource=firewall_rule)
+
+ op_client = compute_v1.GlobalOperationsClient()
+ op_client.wait(project=PROJECT, operation=op.name)
+
+ yield firewall_client.get(project=PROJECT, firewall=firewall_rule.name)
+
+ op = firewall_client.delete(project=PROJECT, firewall=firewall_rule.name)
+ op_client.wait(project=PROJECT, operation=op.name)
+
+
+def test_create_delete():
+ rule_name = "firewall-sample-test-" + uuid.uuid4().hex[:10]
+ create_firewall_rule(PROJECT, rule_name)
+ assert any(rule.name == rule_name for rule in list_firewall_rules(PROJECT))
+ delete_firewall_rule(PROJECT, rule_name)
+ assert all(rule.name != rule_name for rule in list_firewall_rules(PROJECT))
+
+
+def test_patch_rule(firewall_rule):
+ fw_client = compute_v1.FirewallsClient()
+ assert firewall_rule.priority == 1000
+ patch_firewall_priority(PROJECT, firewall_rule.name, 500)
+ time.sleep(2)
+ updated_firewall_rule = fw_client.get(project=PROJECT, firewall=firewall_rule.name)
+ assert updated_firewall_rule.priority == 500
diff --git a/samples/snippets/test_sample_pagination.py b/samples/snippets/test_sample_pagination.py
new file mode 100644
index 000000000..c881ccd1a
--- /dev/null
+++ b/samples/snippets/test_sample_pagination.py
@@ -0,0 +1,30 @@
+# Copyright 2021 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 typing
+
+from sample_pagination import print_images_list, print_images_list_by_page
+
+PROJECT = 'windows-sql-cloud'
+
+
+def test_pagination(capsys: typing.Any) -> None:
+ print_images_list(PROJECT)
+ out, _ = capsys.readouterr()
+ assert(len(out.splitlines()) > 2)
+
+
+def test_pagination_page(capsys: typing.Any) -> None:
+ print_images_list_by_page(PROJECT, 2)
+ out, _ = capsys.readouterr()
+ assert("Page 2" in out)
diff --git a/samples/snippets/test_sample_start_stop.py b/samples/snippets/test_sample_start_stop.py
index ba01dd9ee..a2f2bf377 100644
--- a/samples/snippets/test_sample_start_stop.py
+++ b/samples/snippets/test_sample_start_stop.py
@@ -77,7 +77,10 @@ def _create_instance(request: compute_v1.InsertInstanceRequest):
operation_client = compute_v1.ZoneOperationsClient()
operation = instance_client.insert(request=request)
- operation_client.wait(operation=operation.name, zone=INSTANCE_ZONE, project=PROJECT)
+ while operation.status != compute_v1.Operation.Status.DONE:
+ operation = operation_client.wait(
+ operation=operation.name, zone=INSTANCE_ZONE, project=PROJECT
+ )
return instance_client.get(project=PROJECT, zone=INSTANCE_ZONE, instance=request.instance_resource.name)
@@ -87,7 +90,10 @@ def _delete_instance(instance: compute_v1.Instance):
operation_client = compute_v1.ZoneOperationsClient()
operation = instance_client.delete(project=PROJECT, zone=INSTANCE_ZONE, instance=instance.name)
- operation_client.wait(operation=operation.name, zone=INSTANCE_ZONE, project=PROJECT)
+ while operation.status != compute_v1.Operation.Status.DONE:
+ operation = operation_client.wait(
+ operation=operation.name, zone=INSTANCE_ZONE, project=PROJECT
+ )
def _get_status(instance: compute_v1.Instance) -> compute_v1.Instance.Status:
diff --git a/scripts/readme-gen/templates/install_deps.tmpl.rst b/scripts/readme-gen/templates/install_deps.tmpl.rst
index a0406dba8..275d64989 100644
--- a/scripts/readme-gen/templates/install_deps.tmpl.rst
+++ b/scripts/readme-gen/templates/install_deps.tmpl.rst
@@ -12,7 +12,7 @@ Install Dependencies
.. _Python Development Environment Setup Guide:
https://cloud.google.com/python/setup
-#. Create a virtualenv. Samples are compatible with Python 2.7 and 3.4+.
+#. Create a virtualenv. Samples are compatible with Python 3.6+.
.. code-block:: bash
diff --git a/setup.py b/setup.py
index c4418e9db..f0cc00b99 100644
--- a/setup.py
+++ b/setup.py
@@ -19,7 +19,7 @@
import os
import setuptools # type: ignore
-version = "0.5.0"
+version = "0.6.0"
package_root = os.path.abspath(os.path.dirname(__file__))
@@ -56,9 +56,13 @@
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Operating System :: OS Independent",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
"Topic :: Internet",
"Topic :: Software Development :: Libraries :: Python Modules",
],
diff --git a/synth.metadata b/synth.metadata
index df26c6680..87bdfda69 100644
--- a/synth.metadata
+++ b/synth.metadata
@@ -4,7 +4,7 @@
"git": {
"name": ".",
"remote": "https://github.com/googleapis/python-compute.git",
- "sha": "fbc1a2869932883d0e7e8e498e16d2273fb25048"
+ "sha": "8e6293777e9197ed0ff795b3f74744c556777d07"
}
},
{
diff --git a/testing/constraints-3.10.txt b/testing/constraints-3.10.txt
new file mode 100644
index 000000000..e69de29bb
diff --git a/testing/constraints-3.11.txt b/testing/constraints-3.11.txt
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/system/test_instance_group.py b/tests/system/test_instance_group.py
index 3e6a37226..abb468047 100644
--- a/tests/system/test_instance_group.py
+++ b/tests/system/test_instance_group.py
@@ -135,10 +135,16 @@ def test_instance_group_resize(self):
)
self.assertEqual(instance_group.target_size, 1)
- # Resize to zero fails, uncomment once fixed b/189145532.
- # resize_0_op = self.igm_client.resize(project=self.DEFAULT_PROJECT,
- # zone=self.DEFAULT_ZONE, size=0, instance_group_manager=igm_name)
- # self.wait_for_zonal_operation(resize_0_op.name)
- # igm = self.igm_client.get(project=self.DEFAULT_PROJECT, zone=self.DEFAULT_ZONE,
- # instance_group_manager=igm_name)
- # self.assertEqual(igm.target_size, 0)
+ resize_0_op = self.igm_client.resize(
+ project=self.DEFAULT_PROJECT,
+ zone=self.DEFAULT_ZONE,
+ size=0,
+ instance_group_manager=igm_name,
+ )
+ self.wait_for_zonal_operation(resize_0_op.name)
+ igm = self.igm_client.get(
+ project=self.DEFAULT_PROJECT,
+ zone=self.DEFAULT_ZONE,
+ instance_group_manager=igm_name,
+ )
+ self.assertEqual(igm.target_size, 0)
diff --git a/tests/system/test_pagination.py b/tests/system/test_pagination.py
index 3f8f4e546..79781004b 100644
--- a/tests/system/test_pagination.py
+++ b/tests/system/test_pagination.py
@@ -12,8 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import collections
+from google.cloud.compute_v1.services.accelerator_types.client import (
+ AcceleratorTypesClient,
+)
from google.cloud.compute_v1.services.zones.client import ZonesClient
+from google.cloud.compute_v1.types import AggregatedListAcceleratorTypesRequest
from google.cloud.compute_v1.types import ListZonesRequest
from tests.system.base import TestBase
@@ -65,3 +70,20 @@ def test_auto_paging(self):
presented = True
break
self.assertTrue(presented)
+
+
+class TestPaginationAggregatedList(TestBase):
+ def setUp(self) -> None:
+ super().setUp()
+
+ def test_auto_paging_map_response(self):
+ client = AcceleratorTypesClient()
+ request = AggregatedListAcceleratorTypesRequest(
+ project=self.DEFAULT_PROJECT, max_results=3
+ )
+ result = client.aggregated_list(request=request)
+ zone_acc_types = collections.defaultdict(list)
+ for zone, types in result:
+ zone_acc_types[zone].extend(at.name for at in types.accelerator_types)
+ default_zone = "zones/" + self.DEFAULT_ZONE
+ self.assertIn("nvidia-tesla-t4", zone_acc_types[default_zone])
diff --git a/tests/system/test_smoke.py b/tests/system/test_smoke.py
index 36c6fbddf..0668cea6c 100644
--- a/tests/system/test_smoke.py
+++ b/tests/system/test_smoke.py
@@ -16,8 +16,14 @@
import time
import google.api_core.exceptions
+from google.cloud.compute_v1.services.firewalls.client import FirewallsClient
+from google.cloud.compute_v1.services.images.client import ImagesClient
from google.cloud.compute_v1.services.instances.client import InstancesClient
from google.cloud.compute_v1.types import (
+ Allowed,
+ Firewall,
+ Image,
+ InsertImageRequest,
InsertInstanceRequest,
Instance,
AttachedDisk,
@@ -189,3 +195,53 @@ def insert_instance(self):
operation = self.client.insert(request=request)
self.wait_for_zonal_operation(operation.name)
self.instances.append(self.name)
+
+
+class TestComputeImages(TestBase):
+ def setUp(self) -> None:
+ super().setUp()
+
+ def test_int64(self):
+ # we want to test a field with format:int64
+ name = self.get_unique_name("image")
+ license_codes = [5543610867827062957]
+ image = Image(
+ name=name,
+ license_codes=license_codes,
+ source_image="projects/debian-cloud/global/images/debian-10-buster-v20210721",
+ )
+ images_client = ImagesClient(transport="rest")
+ request = InsertImageRequest(project=self.DEFAULT_PROJECT, image_resource=image)
+ op = images_client.insert(request)
+ try:
+ self.wait_for_global_operation(op.name)
+
+ fetched = images_client.get(project=self.DEFAULT_PROJECT, image=name)
+ self.assertEqual(fetched.license_codes, license_codes)
+ self.assertEqual(fetched.name, name)
+ finally:
+ images_client.delete(project=self.DEFAULT_PROJECT, image=name)
+
+
+class TestComputeFirewalls(TestBase):
+ def setUp(self):
+ super().setUp()
+
+ def test_capital_letter_field(self):
+ # we want to test a field like "IPProtocol"
+ name = self.get_unique_name("firewall")
+ client = FirewallsClient()
+ firewall = Firewall(
+ name=name,
+ source_ranges=["0.0.0.0/0"],
+ allowed=[Allowed(I_p_protocol="tcp", ports=["80"])],
+ )
+ op = client.insert(project=self.DEFAULT_PROJECT, firewall_resource=firewall)
+ try:
+ self.wait_for_global_operation(op.name)
+
+ fetched = client.get(project=self.DEFAULT_PROJECT, firewall=name)
+ self.assertEqual(fetched.allowed[0].I_p_protocol, "tcp")
+ self.assertEqual(fetched.allowed[0].ports, ["80"])
+ finally:
+ client.delete(project=self.DEFAULT_PROJECT, firewall=name)