diff --git a/packages/google-cloud-billing/.flake8 b/packages/google-cloud-billing/.flake8
index 49e826987d8b..ed9316381c9c 100644
--- a/packages/google-cloud-billing/.flake8
+++ b/packages/google-cloud-billing/.flake8
@@ -16,11 +16,13 @@
# Generated by synthtool. DO NOT EDIT!
[flake8]
-ignore = E203, E266, E501, W503, F401, F841
+ignore = E203, E266, E501, W503
exclude =
# Exclude generated code.
**/proto/**
**/gapic/**
+ **/services/**
+ **/types/**
*_pb2.py
# Standard linting exemptions.
diff --git a/packages/google-cloud-billing/.github/snippet-bot.yml b/packages/google-cloud-billing/.github/snippet-bot.yml
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/packages/google-cloud-billing/.gitignore b/packages/google-cloud-billing/.gitignore
index df79b14445d3..72627b432237 100644
--- a/packages/google-cloud-billing/.gitignore
+++ b/packages/google-cloud-billing/.gitignore
@@ -10,6 +10,7 @@
dist
build
eggs
+.eggs
parts
bin
var
@@ -45,14 +46,16 @@ pip-log.txt
# Built documentation
docs/_build
htmlcov
+docs.metadata
# Virtual environment
env/
coverage.xml
+sponge_log.xml
# System test environment variables.
system_tests/local_test_setup
# Make sure a generated file isn't accidentally committed.
pylintrc
-pylintrc.test
\ No newline at end of file
+pylintrc.test
diff --git a/packages/google-cloud-billing/.kokoro/build.sh b/packages/google-cloud-billing/.kokoro/build.sh
index e0388fdda69c..d635855ca346 100755
--- a/packages/google-cloud-billing/.kokoro/build.sh
+++ b/packages/google-cloud-billing/.kokoro/build.sh
@@ -36,4 +36,10 @@ python3.6 -m pip uninstall --yes --quiet nox-automation
python3.6 -m pip install --upgrade --quiet nox
python3.6 -m nox --version
-python3.6 -m nox
+# If NOX_SESSION is set, it only runs the specified session,
+# otherwise run all the sessions.
+if [[ -n "${NOX_SESSION:-}" ]]; then
+ python3.6 -m nox -s "${NOX_SESSION:-}"
+else
+ python3.6 -m nox
+fi
diff --git a/packages/google-cloud-billing/.kokoro/docker/docs/Dockerfile b/packages/google-cloud-billing/.kokoro/docker/docs/Dockerfile
new file mode 100644
index 000000000000..412b0b56a921
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/docker/docs/Dockerfile
@@ -0,0 +1,98 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ubuntu:20.04
+
+ENV DEBIAN_FRONTEND noninteractive
+
+# Ensure local Python is preferred over distribution Python.
+ENV PATH /usr/local/bin:$PATH
+
+# Install dependencies.
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+ apt-transport-https \
+ build-essential \
+ ca-certificates \
+ curl \
+ dirmngr \
+ git \
+ gpg-agent \
+ graphviz \
+ libbz2-dev \
+ libdb5.3-dev \
+ libexpat1-dev \
+ libffi-dev \
+ liblzma-dev \
+ libreadline-dev \
+ libsnappy-dev \
+ libssl-dev \
+ libsqlite3-dev \
+ portaudio19-dev \
+ redis-server \
+ software-properties-common \
+ ssh \
+ sudo \
+ tcl \
+ tcl-dev \
+ tk \
+ tk-dev \
+ uuid-dev \
+ wget \
+ zlib1g-dev \
+ && add-apt-repository universe \
+ && apt-get update \
+ && apt-get -y install jq \
+ && apt-get clean autoclean \
+ && apt-get autoremove -y \
+ && rm -rf /var/lib/apt/lists/* \
+ && rm -f /var/cache/apt/archives/*.deb
+
+
+COPY fetch_gpg_keys.sh /tmp
+# Install the desired versions of Python.
+RUN set -ex \
+ && export GNUPGHOME="$(mktemp -d)" \
+ && echo "disable-ipv6" >> "${GNUPGHOME}/dirmngr.conf" \
+ && /tmp/fetch_gpg_keys.sh \
+ && for PYTHON_VERSION in 3.7.8 3.8.5; do \
+ wget --no-check-certificate -O python-${PYTHON_VERSION}.tar.xz "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz" \
+ && wget --no-check-certificate -O python-${PYTHON_VERSION}.tar.xz.asc "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc" \
+ && gpg --batch --verify python-${PYTHON_VERSION}.tar.xz.asc python-${PYTHON_VERSION}.tar.xz \
+ && rm -r python-${PYTHON_VERSION}.tar.xz.asc \
+ && mkdir -p /usr/src/python-${PYTHON_VERSION} \
+ && tar -xJC /usr/src/python-${PYTHON_VERSION} --strip-components=1 -f python-${PYTHON_VERSION}.tar.xz \
+ && rm python-${PYTHON_VERSION}.tar.xz \
+ && cd /usr/src/python-${PYTHON_VERSION} \
+ && ./configure \
+ --enable-shared \
+ # This works only on Python 2.7 and throws a warning on every other
+ # version, but seems otherwise harmless.
+ --enable-unicode=ucs4 \
+ --with-system-ffi \
+ --without-ensurepip \
+ && make -j$(nproc) \
+ && make install \
+ && ldconfig \
+ ; done \
+ && rm -rf "${GNUPGHOME}" \
+ && rm -rf /usr/src/python* \
+ && rm -rf ~/.cache/
+
+RUN wget -O /tmp/get-pip.py 'https://bootstrap.pypa.io/get-pip.py' \
+ && python3.7 /tmp/get-pip.py \
+ && python3.8 /tmp/get-pip.py \
+ && rm /tmp/get-pip.py
+
+CMD ["python3.7"]
diff --git a/packages/google-cloud-billing/.kokoro/docker/docs/fetch_gpg_keys.sh b/packages/google-cloud-billing/.kokoro/docker/docs/fetch_gpg_keys.sh
new file mode 100755
index 000000000000..d653dd868e4b
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/docker/docs/fetch_gpg_keys.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# A script to fetch gpg keys with retry.
+# Avoid jinja parsing the file.
+#
+
+function retry {
+ if [[ "${#}" -le 1 ]]; then
+ echo "Usage: ${0} retry_count commands.."
+ exit 1
+ fi
+ local retries=${1}
+ local command="${@:2}"
+ until [[ "${retries}" -le 0 ]]; do
+ $command && return 0
+ if [[ $? -ne 0 ]]; then
+ echo "command failed, retrying"
+ ((retries--))
+ fi
+ done
+ return 1
+}
+
+# 3.6.9, 3.7.5 (Ned Deily)
+retry 3 gpg --keyserver ha.pool.sks-keyservers.net --recv-keys \
+ 0D96DF4D4110E5C43FBFB17F2D347EA6AA65421D
+
+# 3.8.0 (Łukasz Langa)
+retry 3 gpg --keyserver ha.pool.sks-keyservers.net --recv-keys \
+ E3FF2839C048B25C084DEBE9B26995E310250568
+
+#
diff --git a/packages/google-cloud-billing/.kokoro/docs/common.cfg b/packages/google-cloud-billing/.kokoro/docs/common.cfg
index 93d9f86d6084..eef34560e4c2 100644
--- a/packages/google-cloud-billing/.kokoro/docs/common.cfg
+++ b/packages/google-cloud-billing/.kokoro/docs/common.cfg
@@ -11,12 +11,12 @@ action {
gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline"
# Use the trampoline script to run in docker.
-build_file: "python-billing/.kokoro/trampoline.sh"
+build_file: "python-billing/.kokoro/trampoline_v2.sh"
# Configure the docker image for kokoro-trampoline.
env_vars: {
key: "TRAMPOLINE_IMAGE"
- value: "gcr.io/cloud-devrel-kokoro-resources/python-multi"
+ value: "gcr.io/cloud-devrel-kokoro-resources/python-lib-docs"
}
env_vars: {
key: "TRAMPOLINE_BUILD_FILE"
@@ -28,6 +28,23 @@ env_vars: {
value: "docs-staging"
}
+env_vars: {
+ key: "V2_STAGING_BUCKET"
+ value: "docs-staging-v2"
+}
+
+# It will upload the docker image after successful builds.
+env_vars: {
+ key: "TRAMPOLINE_IMAGE_UPLOAD"
+ value: "true"
+}
+
+# It will always build the docker image.
+env_vars: {
+ key: "TRAMPOLINE_DOCKERFILE"
+ value: ".kokoro/docker/docs/Dockerfile"
+}
+
# Fetch the token needed for reporting release status to GitHub
before_action {
fetch_keystore {
diff --git a/packages/google-cloud-billing/.kokoro/docs/docs-presubmit.cfg b/packages/google-cloud-billing/.kokoro/docs/docs-presubmit.cfg
new file mode 100644
index 000000000000..1118107829b7
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/docs/docs-presubmit.cfg
@@ -0,0 +1,17 @@
+# Format: //devtools/kokoro/config/proto/build.proto
+
+env_vars: {
+ key: "STAGING_BUCKET"
+ value: "gcloud-python-test"
+}
+
+env_vars: {
+ key: "V2_STAGING_BUCKET"
+ value: "gcloud-python-test"
+}
+
+# We only upload the image in the main `docs` build.
+env_vars: {
+ key: "TRAMPOLINE_IMAGE_UPLOAD"
+ value: "false"
+}
diff --git a/packages/google-cloud-billing/.kokoro/populate-secrets.sh b/packages/google-cloud-billing/.kokoro/populate-secrets.sh
new file mode 100755
index 000000000000..f52514257ef0
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/populate-secrets.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# Copyright 2020 Google LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -eo pipefail
+
+function now { date +"%Y-%m-%d %H:%M:%S" | tr -d '\n' ;}
+function msg { println "$*" >&2 ;}
+function println { printf '%s\n' "$(now) $*" ;}
+
+
+# Populates requested secrets set in SECRET_MANAGER_KEYS from service account:
+# kokoro-trampoline@cloud-devrel-kokoro-resources.iam.gserviceaccount.com
+SECRET_LOCATION="${KOKORO_GFILE_DIR}/secret_manager"
+msg "Creating folder on disk for secrets: ${SECRET_LOCATION}"
+mkdir -p ${SECRET_LOCATION}
+for key in $(echo ${SECRET_MANAGER_KEYS} | sed "s/,/ /g")
+do
+ msg "Retrieving secret ${key}"
+ docker run --entrypoint=gcloud \
+ --volume=${KOKORO_GFILE_DIR}:${KOKORO_GFILE_DIR} \
+ gcr.io/google.com/cloudsdktool/cloud-sdk \
+ secrets versions access latest \
+ --project cloud-devrel-kokoro-resources \
+ --secret ${key} > \
+ "${SECRET_LOCATION}/${key}"
+ if [[ $? == 0 ]]; then
+ msg "Secret written to ${SECRET_LOCATION}/${key}"
+ else
+ msg "Error retrieving secret ${key}"
+ fi
+done
diff --git a/packages/google-cloud-billing/.kokoro/publish-docs.sh b/packages/google-cloud-billing/.kokoro/publish-docs.sh
index 9801da8fe968..8acb14e802b0 100755
--- a/packages/google-cloud-billing/.kokoro/publish-docs.sh
+++ b/packages/google-cloud-billing/.kokoro/publish-docs.sh
@@ -18,26 +18,16 @@ set -eo pipefail
# Disable buffering, so that the logs stream through.
export PYTHONUNBUFFERED=1
-cd github/python-billing
-
-# Remove old nox
-python3.6 -m pip uninstall --yes --quiet nox-automation
+export PATH="${HOME}/.local/bin:${PATH}"
# Install nox
-python3.6 -m pip install --upgrade --quiet nox
-python3.6 -m nox --version
+python3 -m pip install --user --upgrade --quiet nox
+python3 -m nox --version
# build docs
nox -s docs
-python3 -m pip install gcp-docuploader
-
-# install a json parser
-sudo apt-get update
-sudo apt-get -y install software-properties-common
-sudo add-apt-repository universe
-sudo apt-get update
-sudo apt-get -y install jq
+python3 -m pip install --user gcp-docuploader
# create metadata
python3 -m docuploader create-metadata \
@@ -52,4 +42,23 @@ python3 -m docuploader create-metadata \
cat docs.metadata
# upload docs
-python3 -m docuploader upload docs/_build/html --metadata-file docs.metadata --staging-bucket docs-staging
+python3 -m docuploader upload docs/_build/html --metadata-file docs.metadata --staging-bucket "${STAGING_BUCKET}"
+
+
+# docfx yaml files
+nox -s docfx
+
+# create metadata.
+python3 -m docuploader create-metadata \
+ --name=$(jq --raw-output '.name // empty' .repo-metadata.json) \
+ --version=$(python3 setup.py --version) \
+ --language=$(jq --raw-output '.language // empty' .repo-metadata.json) \
+ --distribution-name=$(python3 setup.py --name) \
+ --product-page=$(jq --raw-output '.product_documentation // empty' .repo-metadata.json) \
+ --github-repository=$(jq --raw-output '.repo // empty' .repo-metadata.json) \
+ --issue-tracker=$(jq --raw-output '.issue_tracker // empty' .repo-metadata.json)
+
+cat docs.metadata
+
+# upload docs
+python3 -m docuploader upload docs/_build/html/docfx_yaml --metadata-file docs.metadata --destination-prefix docfx --staging-bucket "${V2_STAGING_BUCKET}"
diff --git a/packages/google-cloud-billing/.kokoro/release/common.cfg b/packages/google-cloud-billing/.kokoro/release/common.cfg
index ff5319b7a368..81cd544f2ac2 100644
--- a/packages/google-cloud-billing/.kokoro/release/common.cfg
+++ b/packages/google-cloud-billing/.kokoro/release/common.cfg
@@ -23,42 +23,18 @@ env_vars: {
value: "github/python-billing/.kokoro/release.sh"
}
-# Fetch the token needed for reporting release status to GitHub
-before_action {
- fetch_keystore {
- keystore_resource {
- keystore_config_id: 73713
- keyname: "yoshi-automation-github-key"
- }
- }
-}
-
-# Fetch PyPI password
-before_action {
- fetch_keystore {
- keystore_resource {
- keystore_config_id: 73713
- keyname: "google_cloud_pypi_password"
- }
- }
-}
-
-# Fetch magictoken to use with Magic Github Proxy
-before_action {
- fetch_keystore {
- keystore_resource {
- keystore_config_id: 73713
- keyname: "releasetool-magictoken"
- }
- }
+# Fetch PyPI password
+before_action {
+ fetch_keystore {
+ keystore_resource {
+ keystore_config_id: 73713
+ keyname: "google_cloud_pypi_password"
+ }
+ }
}
-# Fetch api key to use with Magic Github Proxy
-before_action {
- fetch_keystore {
- keystore_resource {
- keystore_config_id: 73713
- keyname: "magic-github-proxy-api-key"
- }
- }
-}
+# Tokens needed to report release status back to GitHub
+env_vars: {
+ key: "SECRET_MANAGER_KEYS"
+ value: "releasetool-publish-reporter-app,releasetool-publish-reporter-googleapis-installation,releasetool-publish-reporter-pem"
+}
\ No newline at end of file
diff --git a/packages/google-cloud-billing/.kokoro/samples/lint/common.cfg b/packages/google-cloud-billing/.kokoro/samples/lint/common.cfg
new file mode 100644
index 000000000000..598ae00bc54e
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/samples/lint/common.cfg
@@ -0,0 +1,34 @@
+# 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: "lint"
+}
+
+env_vars: {
+ key: "TRAMPOLINE_BUILD_FILE"
+ value: "github/python-billing/.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-billing/.kokoro/trampoline.sh"
\ No newline at end of file
diff --git a/packages/google-cloud-billing/.kokoro/samples/lint/continuous.cfg b/packages/google-cloud-billing/.kokoro/samples/lint/continuous.cfg
new file mode 100644
index 000000000000..a1c8d9759c88
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/samples/lint/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/packages/google-cloud-billing/.kokoro/samples/lint/periodic.cfg b/packages/google-cloud-billing/.kokoro/samples/lint/periodic.cfg
new file mode 100644
index 000000000000..50fec9649732
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/samples/lint/periodic.cfg
@@ -0,0 +1,6 @@
+# Format: //devtools/kokoro/config/proto/build.proto
+
+env_vars: {
+ key: "INSTALL_LIBRARY_FROM_SOURCE"
+ value: "False"
+}
\ No newline at end of file
diff --git a/packages/google-cloud-billing/.kokoro/samples/lint/presubmit.cfg b/packages/google-cloud-billing/.kokoro/samples/lint/presubmit.cfg
new file mode 100644
index 000000000000..a1c8d9759c88
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/samples/lint/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/packages/google-cloud-billing/.kokoro/samples/python3.6/common.cfg b/packages/google-cloud-billing/.kokoro/samples/python3.6/common.cfg
new file mode 100644
index 000000000000..2892427e27a2
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/samples/python3.6/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.6"
+}
+
+# Declare build specific Cloud project.
+env_vars: {
+ key: "BUILD_SPECIFIC_GCLOUD_PROJECT"
+ value: "python-docs-samples-tests-py36"
+}
+
+env_vars: {
+ key: "TRAMPOLINE_BUILD_FILE"
+ value: "github/python-billing/.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-billing/.kokoro/trampoline.sh"
\ No newline at end of file
diff --git a/packages/google-cloud-billing/.kokoro/samples/python3.6/continuous.cfg b/packages/google-cloud-billing/.kokoro/samples/python3.6/continuous.cfg
new file mode 100644
index 000000000000..7218af1499e5
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/samples/python3.6/continuous.cfg
@@ -0,0 +1,7 @@
+# Format: //devtools/kokoro/config/proto/build.proto
+
+env_vars: {
+ key: "INSTALL_LIBRARY_FROM_SOURCE"
+ value: "True"
+}
+
diff --git a/packages/google-cloud-billing/.kokoro/samples/python3.6/periodic.cfg b/packages/google-cloud-billing/.kokoro/samples/python3.6/periodic.cfg
new file mode 100644
index 000000000000..50fec9649732
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/samples/python3.6/periodic.cfg
@@ -0,0 +1,6 @@
+# Format: //devtools/kokoro/config/proto/build.proto
+
+env_vars: {
+ key: "INSTALL_LIBRARY_FROM_SOURCE"
+ value: "False"
+}
\ No newline at end of file
diff --git a/packages/google-cloud-billing/.kokoro/samples/python3.6/presubmit.cfg b/packages/google-cloud-billing/.kokoro/samples/python3.6/presubmit.cfg
new file mode 100644
index 000000000000..a1c8d9759c88
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/samples/python3.6/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/packages/google-cloud-billing/.kokoro/samples/python3.7/common.cfg b/packages/google-cloud-billing/.kokoro/samples/python3.7/common.cfg
new file mode 100644
index 000000000000..61fad4c378a6
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/samples/python3.7/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.7"
+}
+
+# Declare build specific Cloud project.
+env_vars: {
+ key: "BUILD_SPECIFIC_GCLOUD_PROJECT"
+ value: "python-docs-samples-tests-py37"
+}
+
+env_vars: {
+ key: "TRAMPOLINE_BUILD_FILE"
+ value: "github/python-billing/.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-billing/.kokoro/trampoline.sh"
\ No newline at end of file
diff --git a/packages/google-cloud-billing/.kokoro/samples/python3.7/continuous.cfg b/packages/google-cloud-billing/.kokoro/samples/python3.7/continuous.cfg
new file mode 100644
index 000000000000..a1c8d9759c88
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/samples/python3.7/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/packages/google-cloud-billing/.kokoro/samples/python3.7/periodic.cfg b/packages/google-cloud-billing/.kokoro/samples/python3.7/periodic.cfg
new file mode 100644
index 000000000000..50fec9649732
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/samples/python3.7/periodic.cfg
@@ -0,0 +1,6 @@
+# Format: //devtools/kokoro/config/proto/build.proto
+
+env_vars: {
+ key: "INSTALL_LIBRARY_FROM_SOURCE"
+ value: "False"
+}
\ No newline at end of file
diff --git a/packages/google-cloud-billing/.kokoro/samples/python3.7/presubmit.cfg b/packages/google-cloud-billing/.kokoro/samples/python3.7/presubmit.cfg
new file mode 100644
index 000000000000..a1c8d9759c88
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/samples/python3.7/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/packages/google-cloud-billing/.kokoro/samples/python3.8/common.cfg b/packages/google-cloud-billing/.kokoro/samples/python3.8/common.cfg
new file mode 100644
index 000000000000..ab21a480648f
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/samples/python3.8/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.8"
+}
+
+# Declare build specific Cloud project.
+env_vars: {
+ key: "BUILD_SPECIFIC_GCLOUD_PROJECT"
+ value: "python-docs-samples-tests-py38"
+}
+
+env_vars: {
+ key: "TRAMPOLINE_BUILD_FILE"
+ value: "github/python-billing/.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-billing/.kokoro/trampoline.sh"
\ No newline at end of file
diff --git a/packages/google-cloud-billing/.kokoro/samples/python3.8/continuous.cfg b/packages/google-cloud-billing/.kokoro/samples/python3.8/continuous.cfg
new file mode 100644
index 000000000000..a1c8d9759c88
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/samples/python3.8/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/packages/google-cloud-billing/.kokoro/samples/python3.8/periodic.cfg b/packages/google-cloud-billing/.kokoro/samples/python3.8/periodic.cfg
new file mode 100644
index 000000000000..50fec9649732
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/samples/python3.8/periodic.cfg
@@ -0,0 +1,6 @@
+# Format: //devtools/kokoro/config/proto/build.proto
+
+env_vars: {
+ key: "INSTALL_LIBRARY_FROM_SOURCE"
+ value: "False"
+}
\ No newline at end of file
diff --git a/packages/google-cloud-billing/.kokoro/samples/python3.8/presubmit.cfg b/packages/google-cloud-billing/.kokoro/samples/python3.8/presubmit.cfg
new file mode 100644
index 000000000000..a1c8d9759c88
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/samples/python3.8/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/packages/google-cloud-billing/.kokoro/test-samples.sh b/packages/google-cloud-billing/.kokoro/test-samples.sh
new file mode 100755
index 000000000000..94851433a2d5
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/test-samples.sh
@@ -0,0 +1,110 @@
+#!/bin/bash
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://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.
+
+
+# `-e` enables the script to automatically fail when a command fails
+# `-o pipefail` sets the exit code to the rightmost comment to exit with a non-zero
+set -eo pipefail
+# Enables `**` to include files nested inside sub-folders
+shopt -s globstar
+
+cd github/python-billing
+
+# Run periodic samples tests at latest release
+if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then
+ LATEST_RELEASE=$(git describe --abbrev=0 --tags)
+ git checkout $LATEST_RELEASE
+fi
+
+# Exit early if samples directory doesn't exist
+if [ ! -d "./samples" ]; then
+ echo "No tests run. `./samples` not found"
+ exit 0
+fi
+
+# Disable buffering, so that the logs stream through.
+export PYTHONUNBUFFERED=1
+
+# Debug: show build environment
+env | grep KOKORO
+
+# Install nox
+python3.6 -m pip install --upgrade --quiet nox
+
+# Use secrets acessor service account to get secrets
+if [[ -f "${KOKORO_GFILE_DIR}/secrets_viewer_service_account.json" ]]; then
+ gcloud auth activate-service-account \
+ --key-file="${KOKORO_GFILE_DIR}/secrets_viewer_service_account.json" \
+ --project="cloud-devrel-kokoro-resources"
+fi
+
+# This script will create 3 files:
+# - testing/test-env.sh
+# - testing/service-account.json
+# - testing/client-secrets.json
+./scripts/decrypt-secrets.sh
+
+source ./testing/test-env.sh
+export GOOGLE_APPLICATION_CREDENTIALS=$(pwd)/testing/service-account.json
+
+# For cloud-run session, we activate the service account for gcloud sdk.
+gcloud auth activate-service-account \
+ --key-file "${GOOGLE_APPLICATION_CREDENTIALS}"
+
+export GOOGLE_CLIENT_SECRETS=$(pwd)/testing/client-secrets.json
+
+echo -e "\n******************** TESTING PROJECTS ********************"
+
+# Switch to 'fail at end' to allow all tests to complete before exiting.
+set +e
+# Use RTN to return a non-zero value if the test fails.
+RTN=0
+ROOT=$(pwd)
+# Find all requirements.txt in the samples directory (may break on whitespace).
+for file in samples/**/requirements.txt; do
+ cd "$ROOT"
+ # Navigate to the project folder.
+ file=$(dirname "$file")
+ cd "$file"
+
+ echo "------------------------------------------------------------"
+ echo "- testing $file"
+ echo "------------------------------------------------------------"
+
+ # Use nox to execute the tests for the project.
+ python3.6 -m nox -s "$RUN_TESTS_SESSION"
+ EXIT=$?
+
+ # If this is a periodic build, send the test log to the Build Cop Bot.
+ # See https://github.com/googleapis/repo-automation-bots/tree/master/packages/buildcop.
+ if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then
+ chmod +x $KOKORO_GFILE_DIR/linux_amd64/buildcop
+ $KOKORO_GFILE_DIR/linux_amd64/buildcop
+ fi
+
+ if [[ $EXIT -ne 0 ]]; then
+ RTN=1
+ echo -e "\n Testing failed: Nox returned a non-zero exit code. \n"
+ else
+ echo -e "\n Testing completed.\n"
+ fi
+
+done
+cd "$ROOT"
+
+# Workaround for Kokoro permissions issue: delete secrets
+rm testing/{test-env.sh,client-secrets.json,service-account.json}
+
+exit "$RTN"
diff --git a/packages/google-cloud-billing/.kokoro/trampoline.sh b/packages/google-cloud-billing/.kokoro/trampoline.sh
index e8c4251f3ed4..f39236e943a8 100755
--- a/packages/google-cloud-billing/.kokoro/trampoline.sh
+++ b/packages/google-cloud-billing/.kokoro/trampoline.sh
@@ -15,9 +15,14 @@
set -eo pipefail
-python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py" || ret_code=$?
+# Always run the cleanup script, regardless of the success of bouncing into
+# the container.
+function cleanup() {
+ chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh
+ ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh
+ echo "cleanup";
+}
+trap cleanup EXIT
-chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh
-${KOKORO_GFILE_DIR}/trampoline_cleanup.sh || true
-
-exit ${ret_code}
+$(dirname $0)/populate-secrets.sh # Secret Manager secrets.
+python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py"
\ No newline at end of file
diff --git a/packages/google-cloud-billing/.kokoro/trampoline_v2.sh b/packages/google-cloud-billing/.kokoro/trampoline_v2.sh
new file mode 100755
index 000000000000..719bcd5ba84d
--- /dev/null
+++ b/packages/google-cloud-billing/.kokoro/trampoline_v2.sh
@@ -0,0 +1,487 @@
+#!/usr/bin/env bash
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# trampoline_v2.sh
+#
+# This script does 3 things.
+#
+# 1. Prepare the Docker image for the test
+# 2. Run the Docker with appropriate flags to run the test
+# 3. Upload the newly built Docker image
+#
+# in a way that is somewhat compatible with trampoline_v1.
+#
+# To run this script, first download few files from gcs to /dev/shm.
+# (/dev/shm is passed into the container as KOKORO_GFILE_DIR).
+#
+# gsutil cp gs://cloud-devrel-kokoro-resources/python-docs-samples/secrets_viewer_service_account.json /dev/shm
+# gsutil cp gs://cloud-devrel-kokoro-resources/python-docs-samples/automl_secrets.txt /dev/shm
+#
+# Then run the script.
+# .kokoro/trampoline_v2.sh
+#
+# These environment variables are required:
+# TRAMPOLINE_IMAGE: The docker image to use.
+# TRAMPOLINE_DOCKERFILE: The location of the Dockerfile.
+#
+# You can optionally change these environment variables:
+# TRAMPOLINE_IMAGE_UPLOAD:
+# (true|false): Whether to upload the Docker image after the
+# successful builds.
+# TRAMPOLINE_BUILD_FILE: The script to run in the docker container.
+# TRAMPOLINE_WORKSPACE: The workspace path in the docker container.
+# Defaults to /workspace.
+# Potentially there are some repo specific envvars in .trampolinerc in
+# the project root.
+
+
+set -euo pipefail
+
+TRAMPOLINE_VERSION="2.0.5"
+
+if command -v tput >/dev/null && [[ -n "${TERM:-}" ]]; then
+ readonly IO_COLOR_RED="$(tput setaf 1)"
+ readonly IO_COLOR_GREEN="$(tput setaf 2)"
+ readonly IO_COLOR_YELLOW="$(tput setaf 3)"
+ readonly IO_COLOR_RESET="$(tput sgr0)"
+else
+ readonly IO_COLOR_RED=""
+ readonly IO_COLOR_GREEN=""
+ readonly IO_COLOR_YELLOW=""
+ readonly IO_COLOR_RESET=""
+fi
+
+function function_exists {
+ [ $(LC_ALL=C type -t $1)"" == "function" ]
+}
+
+# Logs a message using the given color. The first argument must be one
+# of the IO_COLOR_* variables defined above, such as
+# "${IO_COLOR_YELLOW}". The remaining arguments will be logged in the
+# given color. The log message will also have an RFC-3339 timestamp
+# prepended (in UTC). You can disable the color output by setting
+# TERM=vt100.
+function log_impl() {
+ local color="$1"
+ shift
+ local timestamp="$(date -u "+%Y-%m-%dT%H:%M:%SZ")"
+ echo "================================================================"
+ echo "${color}${timestamp}:" "$@" "${IO_COLOR_RESET}"
+ echo "================================================================"
+}
+
+# Logs the given message with normal coloring and a timestamp.
+function log() {
+ log_impl "${IO_COLOR_RESET}" "$@"
+}
+
+# Logs the given message in green with a timestamp.
+function log_green() {
+ log_impl "${IO_COLOR_GREEN}" "$@"
+}
+
+# Logs the given message in yellow with a timestamp.
+function log_yellow() {
+ log_impl "${IO_COLOR_YELLOW}" "$@"
+}
+
+# Logs the given message in red with a timestamp.
+function log_red() {
+ log_impl "${IO_COLOR_RED}" "$@"
+}
+
+readonly tmpdir=$(mktemp -d -t ci-XXXXXXXX)
+readonly tmphome="${tmpdir}/h"
+mkdir -p "${tmphome}"
+
+function cleanup() {
+ rm -rf "${tmpdir}"
+}
+trap cleanup EXIT
+
+RUNNING_IN_CI="${RUNNING_IN_CI:-false}"
+
+# The workspace in the container, defaults to /workspace.
+TRAMPOLINE_WORKSPACE="${TRAMPOLINE_WORKSPACE:-/workspace}"
+
+pass_down_envvars=(
+ # TRAMPOLINE_V2 variables.
+ # Tells scripts whether they are running as part of CI or not.
+ "RUNNING_IN_CI"
+ # Indicates which CI system we're in.
+ "TRAMPOLINE_CI"
+ # Indicates the version of the script.
+ "TRAMPOLINE_VERSION"
+)
+
+log_yellow "Building with Trampoline ${TRAMPOLINE_VERSION}"
+
+# Detect which CI systems we're in. If we're in any of the CI systems
+# we support, `RUNNING_IN_CI` will be true and `TRAMPOLINE_CI` will be
+# the name of the CI system. Both envvars will be passing down to the
+# container for telling which CI system we're in.
+if [[ -n "${KOKORO_BUILD_ID:-}" ]]; then
+ # descriptive env var for indicating it's on CI.
+ RUNNING_IN_CI="true"
+ TRAMPOLINE_CI="kokoro"
+ if [[ "${TRAMPOLINE_USE_LEGACY_SERVICE_ACCOUNT:-}" == "true" ]]; then
+ if [[ ! -f "${KOKORO_GFILE_DIR}/kokoro-trampoline.service-account.json" ]]; then
+ log_red "${KOKORO_GFILE_DIR}/kokoro-trampoline.service-account.json does not exist. Did you forget to mount cloud-devrel-kokoro-resources/trampoline? Aborting."
+ exit 1
+ fi
+ # This service account will be activated later.
+ TRAMPOLINE_SERVICE_ACCOUNT="${KOKORO_GFILE_DIR}/kokoro-trampoline.service-account.json"
+ else
+ if [[ "${TRAMPOLINE_VERBOSE:-}" == "true" ]]; then
+ gcloud auth list
+ fi
+ log_yellow "Configuring Container Registry access"
+ gcloud auth configure-docker --quiet
+ fi
+ pass_down_envvars+=(
+ # KOKORO dynamic variables.
+ "KOKORO_BUILD_NUMBER"
+ "KOKORO_BUILD_ID"
+ "KOKORO_JOB_NAME"
+ "KOKORO_GIT_COMMIT"
+ "KOKORO_GITHUB_COMMIT"
+ "KOKORO_GITHUB_PULL_REQUEST_NUMBER"
+ "KOKORO_GITHUB_PULL_REQUEST_COMMIT"
+ # For Build Cop Bot
+ "KOKORO_GITHUB_COMMIT_URL"
+ "KOKORO_GITHUB_PULL_REQUEST_URL"
+ )
+elif [[ "${TRAVIS:-}" == "true" ]]; then
+ RUNNING_IN_CI="true"
+ TRAMPOLINE_CI="travis"
+ pass_down_envvars+=(
+ "TRAVIS_BRANCH"
+ "TRAVIS_BUILD_ID"
+ "TRAVIS_BUILD_NUMBER"
+ "TRAVIS_BUILD_WEB_URL"
+ "TRAVIS_COMMIT"
+ "TRAVIS_COMMIT_MESSAGE"
+ "TRAVIS_COMMIT_RANGE"
+ "TRAVIS_JOB_NAME"
+ "TRAVIS_JOB_NUMBER"
+ "TRAVIS_JOB_WEB_URL"
+ "TRAVIS_PULL_REQUEST"
+ "TRAVIS_PULL_REQUEST_BRANCH"
+ "TRAVIS_PULL_REQUEST_SHA"
+ "TRAVIS_PULL_REQUEST_SLUG"
+ "TRAVIS_REPO_SLUG"
+ "TRAVIS_SECURE_ENV_VARS"
+ "TRAVIS_TAG"
+ )
+elif [[ -n "${GITHUB_RUN_ID:-}" ]]; then
+ RUNNING_IN_CI="true"
+ TRAMPOLINE_CI="github-workflow"
+ pass_down_envvars+=(
+ "GITHUB_WORKFLOW"
+ "GITHUB_RUN_ID"
+ "GITHUB_RUN_NUMBER"
+ "GITHUB_ACTION"
+ "GITHUB_ACTIONS"
+ "GITHUB_ACTOR"
+ "GITHUB_REPOSITORY"
+ "GITHUB_EVENT_NAME"
+ "GITHUB_EVENT_PATH"
+ "GITHUB_SHA"
+ "GITHUB_REF"
+ "GITHUB_HEAD_REF"
+ "GITHUB_BASE_REF"
+ )
+elif [[ "${CIRCLECI:-}" == "true" ]]; then
+ RUNNING_IN_CI="true"
+ TRAMPOLINE_CI="circleci"
+ pass_down_envvars+=(
+ "CIRCLE_BRANCH"
+ "CIRCLE_BUILD_NUM"
+ "CIRCLE_BUILD_URL"
+ "CIRCLE_COMPARE_URL"
+ "CIRCLE_JOB"
+ "CIRCLE_NODE_INDEX"
+ "CIRCLE_NODE_TOTAL"
+ "CIRCLE_PREVIOUS_BUILD_NUM"
+ "CIRCLE_PROJECT_REPONAME"
+ "CIRCLE_PROJECT_USERNAME"
+ "CIRCLE_REPOSITORY_URL"
+ "CIRCLE_SHA1"
+ "CIRCLE_STAGE"
+ "CIRCLE_USERNAME"
+ "CIRCLE_WORKFLOW_ID"
+ "CIRCLE_WORKFLOW_JOB_ID"
+ "CIRCLE_WORKFLOW_UPSTREAM_JOB_IDS"
+ "CIRCLE_WORKFLOW_WORKSPACE_ID"
+ )
+fi
+
+# Configure the service account for pulling the docker image.
+function repo_root() {
+ local dir="$1"
+ while [[ ! -d "${dir}/.git" ]]; do
+ dir="$(dirname "$dir")"
+ done
+ echo "${dir}"
+}
+
+# Detect the project root. In CI builds, we assume the script is in
+# the git tree and traverse from there, otherwise, traverse from `pwd`
+# to find `.git` directory.
+if [[ "${RUNNING_IN_CI:-}" == "true" ]]; then
+ PROGRAM_PATH="$(realpath "$0")"
+ PROGRAM_DIR="$(dirname "${PROGRAM_PATH}")"
+ PROJECT_ROOT="$(repo_root "${PROGRAM_DIR}")"
+else
+ PROJECT_ROOT="$(repo_root $(pwd))"
+fi
+
+log_yellow "Changing to the project root: ${PROJECT_ROOT}."
+cd "${PROJECT_ROOT}"
+
+# To support relative path for `TRAMPOLINE_SERVICE_ACCOUNT`, we need
+# to use this environment variable in `PROJECT_ROOT`.
+if [[ -n "${TRAMPOLINE_SERVICE_ACCOUNT:-}" ]]; then
+
+ mkdir -p "${tmpdir}/gcloud"
+ gcloud_config_dir="${tmpdir}/gcloud"
+
+ log_yellow "Using isolated gcloud config: ${gcloud_config_dir}."
+ export CLOUDSDK_CONFIG="${gcloud_config_dir}"
+
+ log_yellow "Using ${TRAMPOLINE_SERVICE_ACCOUNT} for authentication."
+ gcloud auth activate-service-account \
+ --key-file "${TRAMPOLINE_SERVICE_ACCOUNT}"
+ log_yellow "Configuring Container Registry access"
+ gcloud auth configure-docker --quiet
+fi
+
+required_envvars=(
+ # The basic trampoline configurations.
+ "TRAMPOLINE_IMAGE"
+ "TRAMPOLINE_BUILD_FILE"
+)
+
+if [[ -f "${PROJECT_ROOT}/.trampolinerc" ]]; then
+ source "${PROJECT_ROOT}/.trampolinerc"
+fi
+
+log_yellow "Checking environment variables."
+for e in "${required_envvars[@]}"
+do
+ if [[ -z "${!e:-}" ]]; then
+ log "Missing ${e} env var. Aborting."
+ exit 1
+ fi
+done
+
+# We want to support legacy style TRAMPOLINE_BUILD_FILE used with V1
+# script: e.g. "github/repo-name/.kokoro/run_tests.sh"
+TRAMPOLINE_BUILD_FILE="${TRAMPOLINE_BUILD_FILE#github/*/}"
+log_yellow "Using TRAMPOLINE_BUILD_FILE: ${TRAMPOLINE_BUILD_FILE}"
+
+# ignore error on docker operations and test execution
+set +e
+
+log_yellow "Preparing Docker image."
+# We only download the docker image in CI builds.
+if [[ "${RUNNING_IN_CI:-}" == "true" ]]; then
+ # Download the docker image specified by `TRAMPOLINE_IMAGE`
+
+ # We may want to add --max-concurrent-downloads flag.
+
+ log_yellow "Start pulling the Docker image: ${TRAMPOLINE_IMAGE}."
+ if docker pull "${TRAMPOLINE_IMAGE}"; then
+ log_green "Finished pulling the Docker image: ${TRAMPOLINE_IMAGE}."
+ has_image="true"
+ else
+ log_red "Failed pulling the Docker image: ${TRAMPOLINE_IMAGE}."
+ has_image="false"
+ fi
+else
+ # For local run, check if we have the image.
+ if docker images "${TRAMPOLINE_IMAGE}:latest" | grep "${TRAMPOLINE_IMAGE}"; then
+ has_image="true"
+ else
+ has_image="false"
+ fi
+fi
+
+
+# The default user for a Docker container has uid 0 (root). To avoid
+# creating root-owned files in the build directory we tell docker to
+# use the current user ID.
+user_uid="$(id -u)"
+user_gid="$(id -g)"
+user_name="$(id -un)"
+
+# To allow docker in docker, we add the user to the docker group in
+# the host os.
+docker_gid=$(cut -d: -f3 < <(getent group docker))
+
+update_cache="false"
+if [[ "${TRAMPOLINE_DOCKERFILE:-none}" != "none" ]]; then
+ # Build the Docker image from the source.
+ context_dir=$(dirname "${TRAMPOLINE_DOCKERFILE}")
+ docker_build_flags=(
+ "-f" "${TRAMPOLINE_DOCKERFILE}"
+ "-t" "${TRAMPOLINE_IMAGE}"
+ "--build-arg" "UID=${user_uid}"
+ "--build-arg" "USERNAME=${user_name}"
+ )
+ if [[ "${has_image}" == "true" ]]; then
+ docker_build_flags+=("--cache-from" "${TRAMPOLINE_IMAGE}")
+ fi
+
+ log_yellow "Start building the docker image."
+ if [[ "${TRAMPOLINE_VERBOSE:-false}" == "true" ]]; then
+ echo "docker build" "${docker_build_flags[@]}" "${context_dir}"
+ fi
+
+ # ON CI systems, we want to suppress docker build logs, only
+ # output the logs when it fails.
+ if [[ "${RUNNING_IN_CI:-}" == "true" ]]; then
+ if docker build "${docker_build_flags[@]}" "${context_dir}" \
+ > "${tmpdir}/docker_build.log" 2>&1; then
+ if [[ "${TRAMPOLINE_VERBOSE:-}" == "true" ]]; then
+ cat "${tmpdir}/docker_build.log"
+ fi
+
+ log_green "Finished building the docker image."
+ update_cache="true"
+ else
+ log_red "Failed to build the Docker image, aborting."
+ log_yellow "Dumping the build logs:"
+ cat "${tmpdir}/docker_build.log"
+ exit 1
+ fi
+ else
+ if docker build "${docker_build_flags[@]}" "${context_dir}"; then
+ log_green "Finished building the docker image."
+ update_cache="true"
+ else
+ log_red "Failed to build the Docker image, aborting."
+ exit 1
+ fi
+ fi
+else
+ if [[ "${has_image}" != "true" ]]; then
+ log_red "We do not have ${TRAMPOLINE_IMAGE} locally, aborting."
+ exit 1
+ fi
+fi
+
+# We use an array for the flags so they are easier to document.
+docker_flags=(
+ # Remove the container after it exists.
+ "--rm"
+
+ # Use the host network.
+ "--network=host"
+
+ # Run in priviledged mode. We are not using docker for sandboxing or
+ # isolation, just for packaging our dev tools.
+ "--privileged"
+
+ # Run the docker script with the user id. Because the docker image gets to
+ # write in ${PWD} you typically want this to be your user id.
+ # To allow docker in docker, we need to use docker gid on the host.
+ "--user" "${user_uid}:${docker_gid}"
+
+ # Pass down the USER.
+ "--env" "USER=${user_name}"
+
+ # Mount the project directory inside the Docker container.
+ "--volume" "${PROJECT_ROOT}:${TRAMPOLINE_WORKSPACE}"
+ "--workdir" "${TRAMPOLINE_WORKSPACE}"
+ "--env" "PROJECT_ROOT=${TRAMPOLINE_WORKSPACE}"
+
+ # Mount the temporary home directory.
+ "--volume" "${tmphome}:/h"
+ "--env" "HOME=/h"
+
+ # Allow docker in docker.
+ "--volume" "/var/run/docker.sock:/var/run/docker.sock"
+
+ # Mount the /tmp so that docker in docker can mount the files
+ # there correctly.
+ "--volume" "/tmp:/tmp"
+ # Pass down the KOKORO_GFILE_DIR and KOKORO_KEYSTORE_DIR
+ # TODO(tmatsuo): This part is not portable.
+ "--env" "TRAMPOLINE_SECRET_DIR=/secrets"
+ "--volume" "${KOKORO_GFILE_DIR:-/dev/shm}:/secrets/gfile"
+ "--env" "KOKORO_GFILE_DIR=/secrets/gfile"
+ "--volume" "${KOKORO_KEYSTORE_DIR:-/dev/shm}:/secrets/keystore"
+ "--env" "KOKORO_KEYSTORE_DIR=/secrets/keystore"
+)
+
+# Add an option for nicer output if the build gets a tty.
+if [[ -t 0 ]]; then
+ docker_flags+=("-it")
+fi
+
+# Passing down env vars
+for e in "${pass_down_envvars[@]}"
+do
+ if [[ -n "${!e:-}" ]]; then
+ docker_flags+=("--env" "${e}=${!e}")
+ fi
+done
+
+# If arguments are given, all arguments will become the commands run
+# in the container, otherwise run TRAMPOLINE_BUILD_FILE.
+if [[ $# -ge 1 ]]; then
+ log_yellow "Running the given commands '" "${@:1}" "' in the container."
+ readonly commands=("${@:1}")
+ if [[ "${TRAMPOLINE_VERBOSE:-}" == "true" ]]; then
+ echo docker run "${docker_flags[@]}" "${TRAMPOLINE_IMAGE}" "${commands[@]}"
+ fi
+ docker run "${docker_flags[@]}" "${TRAMPOLINE_IMAGE}" "${commands[@]}"
+else
+ log_yellow "Running the tests in a Docker container."
+ docker_flags+=("--entrypoint=${TRAMPOLINE_BUILD_FILE}")
+ if [[ "${TRAMPOLINE_VERBOSE:-}" == "true" ]]; then
+ echo docker run "${docker_flags[@]}" "${TRAMPOLINE_IMAGE}"
+ fi
+ docker run "${docker_flags[@]}" "${TRAMPOLINE_IMAGE}"
+fi
+
+
+test_retval=$?
+
+if [[ ${test_retval} -eq 0 ]]; then
+ log_green "Build finished with ${test_retval}"
+else
+ log_red "Build finished with ${test_retval}"
+fi
+
+# Only upload it when the test passes.
+if [[ "${update_cache}" == "true" ]] && \
+ [[ $test_retval == 0 ]] && \
+ [[ "${TRAMPOLINE_IMAGE_UPLOAD:-false}" == "true" ]]; then
+ log_yellow "Uploading the Docker image."
+ if docker push "${TRAMPOLINE_IMAGE}"; then
+ log_green "Finished uploading the Docker image."
+ else
+ log_red "Failed uploading the Docker image."
+ fi
+ # Call trampoline_after_upload_hook if it's defined.
+ if function_exists trampoline_after_upload_hook; then
+ trampoline_after_upload_hook
+ fi
+
+fi
+
+exit "${test_retval}"
diff --git a/packages/google-cloud-billing/.trampolinerc b/packages/google-cloud-billing/.trampolinerc
new file mode 100644
index 000000000000..995ee29111e1
--- /dev/null
+++ b/packages/google-cloud-billing/.trampolinerc
@@ -0,0 +1,51 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Template for .trampolinerc
+
+# 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+=(
+ "STAGING_BUCKET"
+ "V2_STAGING_BUCKET"
+)
+
+# Prevent unintentional override on the default image.
+if [[ "${TRAMPOLINE_IMAGE_UPLOAD:-false}" == "true" ]] && \
+ [[ -z "${TRAMPOLINE_IMAGE:-}" ]]; then
+ echo "Please set TRAMPOLINE_IMAGE if you want to upload the Docker image."
+ exit 1
+fi
+
+# Define the default value if it makes sense.
+if [[ -z "${TRAMPOLINE_IMAGE_UPLOAD:-}" ]]; then
+ TRAMPOLINE_IMAGE_UPLOAD=""
+fi
+
+if [[ -z "${TRAMPOLINE_IMAGE:-}" ]]; then
+ TRAMPOLINE_IMAGE=""
+fi
+
+if [[ -z "${TRAMPOLINE_DOCKERFILE:-}" ]]; then
+ TRAMPOLINE_DOCKERFILE=""
+fi
+
+if [[ -z "${TRAMPOLINE_BUILD_FILE:-}" ]]; then
+ TRAMPOLINE_BUILD_FILE=""
+fi
diff --git a/packages/google-cloud-billing/CODE_OF_CONDUCT.md b/packages/google-cloud-billing/CODE_OF_CONDUCT.md
index b3d1f6029849..039f43681204 100644
--- a/packages/google-cloud-billing/CODE_OF_CONDUCT.md
+++ b/packages/google-cloud-billing/CODE_OF_CONDUCT.md
@@ -1,44 +1,95 @@
-# Contributor Code of Conduct
+# Code of Conduct
-As contributors and maintainers of this project,
-and in the interest of fostering an open and welcoming community,
-we pledge to respect all people who contribute through reporting issues,
-posting feature requests, updating documentation,
-submitting pull requests or patches, and other activities.
+## Our Pledge
-We are committed to making participation in this project
-a harassment-free experience for everyone,
-regardless of level of experience, gender, gender identity and expression,
-sexual orientation, disability, personal appearance,
-body size, race, ethnicity, age, religion, or nationality.
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of
+experience, education, socio-economic status, nationality, personal appearance,
+race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
-* The use of sexualized language or imagery
-* Personal attacks
-* Trolling or insulting/derogatory comments
-* Public or private harassment
-* Publishing other's private information,
-such as physical or electronic
-addresses, without explicit permission
-* Other unethical or unprofessional conduct.
+* The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject
-comments, commits, code, wiki edits, issues, and other contributions
-that are not aligned to this Code of Conduct.
-By adopting this Code of Conduct,
-project maintainers commit themselves to fairly and consistently
-applying these principles to every aspect of managing this project.
-Project maintainers who do not follow or enforce the Code of Conduct
-may be permanently removed from the project team.
-
-This code of conduct applies both within project spaces and in public spaces
-when an individual is representing the project or its community.
-
-Instances of abusive, harassing, or otherwise unacceptable behavior
-may be reported by opening an issue
-or contacting one or more of the project maintainers.
-
-This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0,
-available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, or to ban temporarily or permanently any
+contributor for other behaviors that they deem inappropriate, threatening,
+offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+This Code of Conduct also applies outside the project spaces when the Project
+Steward has a reasonable belief that an individual's behavior may have a
+negative impact on the project or its community.
+
+## Conflict Resolution
+
+We do not believe that all conflict is bad; healthy debate and disagreement
+often yield positive results. However, it is never okay to be disrespectful or
+to engage in behavior that violates the project’s code of conduct.
+
+If you see someone violating the code of conduct, you are encouraged to address
+the behavior directly with those involved. Many issues can be resolved quickly
+and easily, and this gives people more control over the outcome of their
+dispute. If you are unable to resolve the matter for any reason, or if the
+behavior is threatening or harassing, report it. We are dedicated to providing
+an environment where participants feel welcome and safe.
+
+
+Reports should be directed to *googleapis-stewards@google.com*, the
+Project Steward(s) for *Google Cloud Client Libraries*. It is the Project Steward’s duty to
+receive and address reported violations of the code of conduct. They will then
+work with a committee consisting of representatives from the Open Source
+Programs Office and the Google Open Source Strategy team. If for any reason you
+are uncomfortable reaching out to the Project Steward, please email
+opensource@google.com.
+
+We will investigate every complaint, but you may not receive a direct response.
+We will use our discretion in determining when and how to follow up on reported
+incidents, which may range from not taking action to permanent expulsion from
+the project and project-sponsored spaces. We will notify the accused of the
+report and provide them an opportunity to discuss it before any action is taken.
+The identity of the reporter will be omitted from the details of the report
+supplied to the accused. In potentially harmful situations, such as ongoing
+harassment or threats to anyone's safety, we may take action without notice.
+
+## Attribution
+
+This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
+available at
+https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
\ No newline at end of file
diff --git a/packages/google-cloud-billing/CONTRIBUTING.rst b/packages/google-cloud-billing/CONTRIBUTING.rst
index e6c10ae0b259..bdde88f61065 100644
--- a/packages/google-cloud-billing/CONTRIBUTING.rst
+++ b/packages/google-cloud-billing/CONTRIBUTING.rst
@@ -80,25 +80,6 @@ We use `nox `__ to instrument our tests.
.. nox: https://pypi.org/project/nox/
-Note on Editable Installs / Develop Mode
-========================================
-
-- As mentioned previously, using ``setuptools`` in `develop mode`_
- or a ``pip`` `editable install`_ is not possible with this
- library. This is because this library uses `namespace packages`_.
- For context see `Issue #2316`_ and the relevant `PyPA issue`_.
-
- Since ``editable`` / ``develop`` mode can't be used, packages
- need to be installed directly. Hence your changes to the source
- tree don't get incorporated into the **already installed**
- package.
-
-.. _namespace packages: https://www.python.org/dev/peps/pep-0420/
-.. _Issue #2316: https://github.com/GoogleCloudPlatform/google-cloud-python/issues/2316
-.. _PyPA issue: https://github.com/pypa/packaging-problems/issues/12
-.. _develop mode: https://setuptools.readthedocs.io/en/latest/setuptools.html#development-mode
-.. _editable install: https://pip.pypa.io/en/stable/reference/pip_install/#editable-installs
-
*****************************************
I'm getting weird errors... Can you help?
*****************************************
diff --git a/packages/google-cloud-billing/MANIFEST.in b/packages/google-cloud-billing/MANIFEST.in
index 68855abc3f02..e9e29d12033d 100644
--- a/packages/google-cloud-billing/MANIFEST.in
+++ b/packages/google-cloud-billing/MANIFEST.in
@@ -20,3 +20,6 @@ recursive-include google *.json *.proto
recursive-include tests *
global-exclude *.py[co]
global-exclude __pycache__
+
+# Exclude scripts for samples readmegen
+prune scripts/readme-gen
\ No newline at end of file
diff --git a/packages/google-cloud-billing/docs/_templates/layout.html b/packages/google-cloud-billing/docs/_templates/layout.html
index 228529efe2d2..6316a537f72b 100644
--- a/packages/google-cloud-billing/docs/_templates/layout.html
+++ b/packages/google-cloud-billing/docs/_templates/layout.html
@@ -21,8 +21,8 @@
- On January 1, 2020 this library will no longer support Python 2 on the latest released version.
- Previously released library versions will continue to be available. For more information please
+ As of January 1, 2020 this library no longer supports Python 2 on the latest released version.
+ Library versions released prior to that date will continue to be available. For more information please
visit
Python 2 support on Google Cloud.
{% block body %} {% endblock %}
diff --git a/packages/google-cloud-billing/docs/billing_v1/services.rst b/packages/google-cloud-billing/docs/billing_v1/services.rst
index 5d0891ad9bf0..b7511c4b8f0f 100644
--- a/packages/google-cloud-billing/docs/billing_v1/services.rst
+++ b/packages/google-cloud-billing/docs/billing_v1/services.rst
@@ -1,6 +1,9 @@
-Client for Google Cloud Billing API
-===================================
+Services for Google Cloud Billing v1 API
+========================================
-.. automodule:: google.cloud.billing_v1
+.. automodule:: google.cloud.billing_v1.services.cloud_billing
+ :members:
+ :inherited-members:
+.. automodule:: google.cloud.billing_v1.services.cloud_catalog
:members:
:inherited-members:
diff --git a/packages/google-cloud-billing/docs/billing_v1/types.rst b/packages/google-cloud-billing/docs/billing_v1/types.rst
index 4333d16ad752..75c1f9f0fdc2 100644
--- a/packages/google-cloud-billing/docs/billing_v1/types.rst
+++ b/packages/google-cloud-billing/docs/billing_v1/types.rst
@@ -1,5 +1,6 @@
-Types for Google Cloud Billing API
-==================================
+Types for Google Cloud Billing v1 API
+=====================================
.. automodule:: google.cloud.billing_v1.types
:members:
+ :show-inheritance:
diff --git a/packages/google-cloud-billing/docs/conf.py b/packages/google-cloud-billing/docs/conf.py
index 298c1b6c9a7f..798112f79cdb 100644
--- a/packages/google-cloud-billing/docs/conf.py
+++ b/packages/google-cloud-billing/docs/conf.py
@@ -20,12 +20,16 @@
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath(".."))
+# For plugins that can not read conf.py.
+# See also: https://github.com/docascode/sphinx-docfx-yaml/issues/85
+sys.path.insert(0, os.path.abspath("."))
+
__version__ = ""
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
-needs_sphinx = "1.6.3"
+needs_sphinx = "1.5.5"
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
@@ -35,6 +39,7 @@
"sphinx.ext.autosummary",
"sphinx.ext.intersphinx",
"sphinx.ext.coverage",
+ "sphinx.ext.doctest",
"sphinx.ext.napoleon",
"sphinx.ext.todo",
"sphinx.ext.viewcode",
@@ -43,7 +48,7 @@
# autodoc/autosummary flags
autoclass_content = "both"
-autodoc_default_flags = ["members"]
+autodoc_default_options = {"members": True}
autosummary_generate = True
@@ -90,7 +95,12 @@
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
-exclude_patterns = ["_build"]
+exclude_patterns = [
+ "_build",
+ "samples/AUTHORING_GUIDE.md",
+ "samples/CONTRIBUTING.md",
+ "samples/snippets/README.rst",
+]
# The reST default role (used for this markup: `text`) to use for all
# documents.
@@ -337,8 +347,9 @@
intersphinx_mapping = {
"python": ("http://python.readthedocs.org/en/latest/", None),
"google-auth": ("https://google-auth.readthedocs.io/en/stable", None),
- "google.api_core": ("https://googleapis.dev/python/google-api-core/latest/", None),
+ "google.api_core": ("https://googleapis.dev/python/google-api-core/latest/", None,),
"grpc": ("https://grpc.io/grpc/python/", None),
+ "proto-plus": ("https://proto-plus-python.readthedocs.io/en/latest/", None),
}
diff --git a/packages/google-cloud-billing/google/cloud/billing/__init__.py b/packages/google-cloud-billing/google/cloud/billing/__init__.py
index 73508b8e0409..56b06a377f31 100644
--- a/packages/google-cloud-billing/google/cloud/billing/__init__.py
+++ b/packages/google-cloud-billing/google/cloud/billing/__init__.py
@@ -15,8 +15,13 @@
# limitations under the License.
#
-
+from google.cloud.billing_v1.services.cloud_billing.async_client import (
+ CloudBillingAsyncClient,
+)
from google.cloud.billing_v1.services.cloud_billing.client import CloudBillingClient
+from google.cloud.billing_v1.services.cloud_catalog.async_client import (
+ CloudCatalogAsyncClient,
+)
from google.cloud.billing_v1.services.cloud_catalog.client import CloudCatalogClient
from google.cloud.billing_v1.types.cloud_billing import BillingAccount
from google.cloud.billing_v1.types.cloud_billing import CreateBillingAccountRequest
@@ -44,7 +49,9 @@
"AggregationInfo",
"BillingAccount",
"Category",
+ "CloudBillingAsyncClient",
"CloudBillingClient",
+ "CloudCatalogAsyncClient",
"CloudCatalogClient",
"CreateBillingAccountRequest",
"GetBillingAccountRequest",
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/__init__.py b/packages/google-cloud-billing/google/cloud/billing_v1/__init__.py
index 02776c62f8fa..b01022904764 100644
--- a/packages/google-cloud-billing/google/cloud/billing_v1/__init__.py
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/__init__.py
@@ -15,7 +15,6 @@
# limitations under the License.
#
-
from .services.cloud_billing import CloudBillingClient
from .services.cloud_catalog import CloudCatalogClient
from .types.cloud_billing import BillingAccount
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/__init__.py b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/__init__.py
index 3ff9f58cd2ad..82ba3783e1b6 100644
--- a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/__init__.py
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/__init__.py
@@ -16,5 +16,9 @@
#
from .client import CloudBillingClient
+from .async_client import CloudBillingAsyncClient
-__all__ = ("CloudBillingClient",)
+__all__ = (
+ "CloudBillingClient",
+ "CloudBillingAsyncClient",
+)
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/async_client.py b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/async_client.py
new file mode 100644
index 000000000000..d04579c9da7f
--- /dev/null
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/async_client.py
@@ -0,0 +1,1100 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+from collections import OrderedDict
+import functools
+import re
+from typing import Dict, Sequence, Tuple, Type, Union
+import pkg_resources
+
+import google.api_core.client_options as ClientOptions # type: ignore
+from google.api_core import exceptions # type: ignore
+from google.api_core import gapic_v1 # type: ignore
+from google.api_core import retry as retries # type: ignore
+from google.auth import credentials # type: ignore
+from google.oauth2 import service_account # type: ignore
+
+from google.cloud.billing_v1.services.cloud_billing import pagers
+from google.cloud.billing_v1.types import cloud_billing
+from google.iam.v1 import iam_policy_pb2 as iam_policy # type: ignore
+from google.iam.v1 import policy_pb2 as policy # type: ignore
+
+from .transports.base import CloudBillingTransport, DEFAULT_CLIENT_INFO
+from .transports.grpc_asyncio import CloudBillingGrpcAsyncIOTransport
+from .client import CloudBillingClient
+
+
+class CloudBillingAsyncClient:
+ """Retrieves GCP Console billing accounts and associates them
+ with projects.
+ """
+
+ _client: CloudBillingClient
+
+ DEFAULT_ENDPOINT = CloudBillingClient.DEFAULT_ENDPOINT
+ DEFAULT_MTLS_ENDPOINT = CloudBillingClient.DEFAULT_MTLS_ENDPOINT
+
+ common_billing_account_path = staticmethod(
+ CloudBillingClient.common_billing_account_path
+ )
+ parse_common_billing_account_path = staticmethod(
+ CloudBillingClient.parse_common_billing_account_path
+ )
+
+ common_folder_path = staticmethod(CloudBillingClient.common_folder_path)
+ parse_common_folder_path = staticmethod(CloudBillingClient.parse_common_folder_path)
+
+ common_organization_path = staticmethod(CloudBillingClient.common_organization_path)
+ parse_common_organization_path = staticmethod(
+ CloudBillingClient.parse_common_organization_path
+ )
+
+ common_project_path = staticmethod(CloudBillingClient.common_project_path)
+ parse_common_project_path = staticmethod(
+ CloudBillingClient.parse_common_project_path
+ )
+
+ common_location_path = staticmethod(CloudBillingClient.common_location_path)
+ parse_common_location_path = staticmethod(
+ CloudBillingClient.parse_common_location_path
+ )
+
+ from_service_account_file = CloudBillingClient.from_service_account_file
+ from_service_account_json = from_service_account_file
+
+ @property
+ def transport(self) -> CloudBillingTransport:
+ """Return the transport used by the client instance.
+
+ Returns:
+ CloudBillingTransport: The transport used by the client instance.
+ """
+ return self._client.transport
+
+ get_transport_class = functools.partial(
+ type(CloudBillingClient).get_transport_class, type(CloudBillingClient)
+ )
+
+ def __init__(
+ self,
+ *,
+ credentials: credentials.Credentials = None,
+ transport: Union[str, CloudBillingTransport] = "grpc_asyncio",
+ client_options: ClientOptions = None,
+ client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
+ ) -> None:
+ """Instantiate the cloud billing client.
+
+ Args:
+ credentials (Optional[google.auth.credentials.Credentials]): The
+ authorization credentials to attach to requests. These
+ credentials identify the application to the service; if none
+ are specified, the client will attempt to ascertain the
+ credentials from the environment.
+ transport (Union[str, ~.CloudBillingTransport]): The
+ transport to use. If set to None, a transport is chosen
+ automatically.
+ client_options (ClientOptions): Custom options for the client. It
+ won't take effect if a ``transport`` instance is provided.
+ (1) The ``api_endpoint`` property can be used to override the
+ default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT
+ environment variable can also be used to override the endpoint:
+ "always" (always use the default mTLS endpoint), "never" (always
+ use the default regular endpoint) and "auto" (auto switch to the
+ default mTLS endpoint if client certificate is present, this is
+ the default value). However, the ``api_endpoint`` property takes
+ precedence if provided.
+ (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable
+ is "true", then the ``client_cert_source`` property can be used
+ to provide client certificate for mutual TLS transport. If
+ not provided, the default SSL client certificate will be used if
+ present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not
+ set, no client certificate will be used.
+
+ Raises:
+ google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
+ creation failed for any reason.
+ """
+
+ self._client = CloudBillingClient(
+ credentials=credentials,
+ transport=transport,
+ client_options=client_options,
+ client_info=client_info,
+ )
+
+ async def get_billing_account(
+ self,
+ request: cloud_billing.GetBillingAccountRequest = None,
+ *,
+ name: str = None,
+ retry: retries.Retry = gapic_v1.method.DEFAULT,
+ timeout: float = None,
+ metadata: Sequence[Tuple[str, str]] = (),
+ ) -> cloud_billing.BillingAccount:
+ r"""Gets information about a billing account. The current
+ authenticated user must be a `viewer of the billing
+ account
`__.
+
+ Args:
+ request (:class:`~.cloud_billing.GetBillingAccountRequest`):
+ The request object. Request message for
+ `GetBillingAccount`.
+ name (:class:`str`):
+ Required. The resource name of the billing account to
+ retrieve. For example,
+ ``billingAccounts/012345-567890-ABCDEF``.
+ This corresponds to the ``name`` field
+ on the ``request`` instance; if ``request`` is provided, this
+ should not be set.
+
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
+ should be retried.
+ timeout (float): The timeout for this request.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
+
+ Returns:
+ ~.cloud_billing.BillingAccount:
+ A billing account in `GCP
+ Console `__. You can
+ assign a billing account to one or more projects.
+
+ """
+ # Create or coerce a protobuf request object.
+ # Sanity check: If we got a request object, we should *not* have
+ # gotten any keyword arguments that map to the request.
+ has_flattened_params = any([name])
+ if request is not None and has_flattened_params:
+ raise ValueError(
+ "If the `request` argument is set, then none of "
+ "the individual field arguments should be set."
+ )
+
+ request = cloud_billing.GetBillingAccountRequest(request)
+
+ # If we have keyword arguments corresponding to fields on the
+ # request, apply these.
+
+ if name is not None:
+ request.name = name
+
+ # Wrap the RPC method; this adds retry and timeout information,
+ # and friendly error handling.
+ rpc = gapic_v1.method_async.wrap_method(
+ self._client._transport.get_billing_account,
+ default_timeout=None,
+ client_info=DEFAULT_CLIENT_INFO,
+ )
+
+ # Certain fields should be provided within the metadata header;
+ # add these here.
+ metadata = tuple(metadata) + (
+ gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
+ )
+
+ # Send the request.
+ response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
+
+ # Done; return the response.
+ return response
+
+ async def list_billing_accounts(
+ self,
+ request: cloud_billing.ListBillingAccountsRequest = None,
+ *,
+ retry: retries.Retry = gapic_v1.method.DEFAULT,
+ timeout: float = None,
+ metadata: Sequence[Tuple[str, str]] = (),
+ ) -> pagers.ListBillingAccountsAsyncPager:
+ r"""Lists the billing accounts that the current authenticated user
+ has permission to
+ `view `__.
+
+ Args:
+ request (:class:`~.cloud_billing.ListBillingAccountsRequest`):
+ The request object. Request message for
+ `ListBillingAccounts`.
+
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
+ should be retried.
+ timeout (float): The timeout for this request.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
+
+ Returns:
+ ~.pagers.ListBillingAccountsAsyncPager:
+ Response message for ``ListBillingAccounts``.
+
+ Iterating over this object will yield results and
+ resolve additional pages automatically.
+
+ """
+ # Create or coerce a protobuf request object.
+
+ request = cloud_billing.ListBillingAccountsRequest(request)
+
+ # Wrap the RPC method; this adds retry and timeout information,
+ # and friendly error handling.
+ rpc = gapic_v1.method_async.wrap_method(
+ self._client._transport.list_billing_accounts,
+ default_timeout=None,
+ client_info=DEFAULT_CLIENT_INFO,
+ )
+
+ # Send the request.
+ response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
+
+ # This method is paged; wrap the response in a pager, which provides
+ # an `__aiter__` convenience method.
+ response = pagers.ListBillingAccountsAsyncPager(
+ method=rpc, request=request, response=response, metadata=metadata,
+ )
+
+ # Done; return the response.
+ return response
+
+ async def update_billing_account(
+ self,
+ request: cloud_billing.UpdateBillingAccountRequest = None,
+ *,
+ name: str = None,
+ account: cloud_billing.BillingAccount = None,
+ retry: retries.Retry = gapic_v1.method.DEFAULT,
+ timeout: float = None,
+ metadata: Sequence[Tuple[str, str]] = (),
+ ) -> cloud_billing.BillingAccount:
+ r"""Updates a billing account's fields. Currently the only field
+ that can be edited is ``display_name``. The current
+ authenticated user must have the ``billing.accounts.update`` IAM
+ permission, which is typically given to the
+ `administrator `__
+ of the billing account.
+
+ Args:
+ request (:class:`~.cloud_billing.UpdateBillingAccountRequest`):
+ The request object. Request message for
+ `UpdateBillingAccount`.
+ name (:class:`str`):
+ Required. The name of the billing
+ account resource to be updated.
+ This corresponds to the ``name`` field
+ on the ``request`` instance; if ``request`` is provided, this
+ should not be set.
+ account (:class:`~.cloud_billing.BillingAccount`):
+ Required. The billing account
+ resource to replace the resource on the
+ server.
+ This corresponds to the ``account`` field
+ on the ``request`` instance; if ``request`` is provided, this
+ should not be set.
+
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
+ should be retried.
+ timeout (float): The timeout for this request.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
+
+ Returns:
+ ~.cloud_billing.BillingAccount:
+ A billing account in `GCP
+ Console `__. You can
+ assign a billing account to one or more projects.
+
+ """
+ # Create or coerce a protobuf request object.
+ # Sanity check: If we got a request object, we should *not* have
+ # gotten any keyword arguments that map to the request.
+ has_flattened_params = any([name, account])
+ if request is not None and has_flattened_params:
+ raise ValueError(
+ "If the `request` argument is set, then none of "
+ "the individual field arguments should be set."
+ )
+
+ request = cloud_billing.UpdateBillingAccountRequest(request)
+
+ # If we have keyword arguments corresponding to fields on the
+ # request, apply these.
+
+ if name is not None:
+ request.name = name
+ if account is not None:
+ request.account = account
+
+ # Wrap the RPC method; this adds retry and timeout information,
+ # and friendly error handling.
+ rpc = gapic_v1.method_async.wrap_method(
+ self._client._transport.update_billing_account,
+ default_timeout=None,
+ client_info=DEFAULT_CLIENT_INFO,
+ )
+
+ # Certain fields should be provided within the metadata header;
+ # add these here.
+ metadata = tuple(metadata) + (
+ gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
+ )
+
+ # Send the request.
+ response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
+
+ # Done; return the response.
+ return response
+
+ async def create_billing_account(
+ self,
+ request: cloud_billing.CreateBillingAccountRequest = None,
+ *,
+ billing_account: cloud_billing.BillingAccount = None,
+ retry: retries.Retry = gapic_v1.method.DEFAULT,
+ timeout: float = None,
+ metadata: Sequence[Tuple[str, str]] = (),
+ ) -> cloud_billing.BillingAccount:
+ r"""Creates a billing account. This method can only be used to
+ create `billing
+ subaccounts `__
+ by GCP resellers. When creating a subaccount, the current
+ authenticated user must have the ``billing.accounts.update`` IAM
+ permission on the master account, which is typically given to
+ billing account
+ `administrators `__.
+ This method will return an error if the master account has not
+ been provisioned as a reseller account.
+
+ Args:
+ request (:class:`~.cloud_billing.CreateBillingAccountRequest`):
+ The request object. Request message for
+ `CreateBillingAccount`.
+ billing_account (:class:`~.cloud_billing.BillingAccount`):
+ Required. The billing account
+ resource to create. Currently
+ CreateBillingAccount only supports
+ subaccount creation, so any created
+ billing accounts must be under a
+ provided master billing account.
+ This corresponds to the ``billing_account`` field
+ on the ``request`` instance; if ``request`` is provided, this
+ should not be set.
+
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
+ should be retried.
+ timeout (float): The timeout for this request.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
+
+ Returns:
+ ~.cloud_billing.BillingAccount:
+ A billing account in `GCP
+ Console `__. You can
+ assign a billing account to one or more projects.
+
+ """
+ # Create or coerce a protobuf request object.
+ # Sanity check: If we got a request object, we should *not* have
+ # gotten any keyword arguments that map to the request.
+ has_flattened_params = any([billing_account])
+ if request is not None and has_flattened_params:
+ raise ValueError(
+ "If the `request` argument is set, then none of "
+ "the individual field arguments should be set."
+ )
+
+ request = cloud_billing.CreateBillingAccountRequest(request)
+
+ # If we have keyword arguments corresponding to fields on the
+ # request, apply these.
+
+ if billing_account is not None:
+ request.billing_account = billing_account
+
+ # Wrap the RPC method; this adds retry and timeout information,
+ # and friendly error handling.
+ rpc = gapic_v1.method_async.wrap_method(
+ self._client._transport.create_billing_account,
+ default_timeout=None,
+ client_info=DEFAULT_CLIENT_INFO,
+ )
+
+ # Send the request.
+ response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
+
+ # Done; return the response.
+ return response
+
+ async def list_project_billing_info(
+ self,
+ request: cloud_billing.ListProjectBillingInfoRequest = None,
+ *,
+ name: str = None,
+ retry: retries.Retry = gapic_v1.method.DEFAULT,
+ timeout: float = None,
+ metadata: Sequence[Tuple[str, str]] = (),
+ ) -> pagers.ListProjectBillingInfoAsyncPager:
+ r"""Lists the projects associated with a billing account. The
+ current authenticated user must have the
+ ``billing.resourceAssociations.list`` IAM permission, which is
+ often given to billing account
+ `viewers `__.
+
+ Args:
+ request (:class:`~.cloud_billing.ListProjectBillingInfoRequest`):
+ The request object. Request message for
+ `ListProjectBillingInfo`.
+ name (:class:`str`):
+ Required. The resource name of the billing account
+ associated with the projects that you want to list. For
+ example, ``billingAccounts/012345-567890-ABCDEF``.
+ This corresponds to the ``name`` field
+ on the ``request`` instance; if ``request`` is provided, this
+ should not be set.
+
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
+ should be retried.
+ timeout (float): The timeout for this request.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
+
+ Returns:
+ ~.pagers.ListProjectBillingInfoAsyncPager:
+ Request message for ``ListProjectBillingInfoResponse``.
+
+ Iterating over this object will yield results and
+ resolve additional pages automatically.
+
+ """
+ # Create or coerce a protobuf request object.
+ # Sanity check: If we got a request object, we should *not* have
+ # gotten any keyword arguments that map to the request.
+ has_flattened_params = any([name])
+ if request is not None and has_flattened_params:
+ raise ValueError(
+ "If the `request` argument is set, then none of "
+ "the individual field arguments should be set."
+ )
+
+ request = cloud_billing.ListProjectBillingInfoRequest(request)
+
+ # If we have keyword arguments corresponding to fields on the
+ # request, apply these.
+
+ if name is not None:
+ request.name = name
+
+ # Wrap the RPC method; this adds retry and timeout information,
+ # and friendly error handling.
+ rpc = gapic_v1.method_async.wrap_method(
+ self._client._transport.list_project_billing_info,
+ default_timeout=None,
+ client_info=DEFAULT_CLIENT_INFO,
+ )
+
+ # Certain fields should be provided within the metadata header;
+ # add these here.
+ metadata = tuple(metadata) + (
+ gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
+ )
+
+ # Send the request.
+ response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
+
+ # This method is paged; wrap the response in a pager, which provides
+ # an `__aiter__` convenience method.
+ response = pagers.ListProjectBillingInfoAsyncPager(
+ method=rpc, request=request, response=response, metadata=metadata,
+ )
+
+ # Done; return the response.
+ return response
+
+ async def get_project_billing_info(
+ self,
+ request: cloud_billing.GetProjectBillingInfoRequest = None,
+ *,
+ name: str = None,
+ retry: retries.Retry = gapic_v1.method.DEFAULT,
+ timeout: float = None,
+ metadata: Sequence[Tuple[str, str]] = (),
+ ) -> cloud_billing.ProjectBillingInfo:
+ r"""Gets the billing information for a project. The current
+ authenticated user must have `permission to view the
+ project `__.
+
+ Args:
+ request (:class:`~.cloud_billing.GetProjectBillingInfoRequest`):
+ The request object. Request message for
+ `GetProjectBillingInfo`.
+ name (:class:`str`):
+ Required. The resource name of the project for which
+ billing information is retrieved. For example,
+ ``projects/tokyo-rain-123``.
+ This corresponds to the ``name`` field
+ on the ``request`` instance; if ``request`` is provided, this
+ should not be set.
+
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
+ should be retried.
+ timeout (float): The timeout for this request.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
+
+ Returns:
+ ~.cloud_billing.ProjectBillingInfo:
+ Encapsulation of billing information
+ for a GCP Console project. A project has
+ at most one associated billing account
+ at a time (but a billing account can be
+ assigned to multiple projects).
+
+ """
+ # Create or coerce a protobuf request object.
+ # Sanity check: If we got a request object, we should *not* have
+ # gotten any keyword arguments that map to the request.
+ has_flattened_params = any([name])
+ if request is not None and has_flattened_params:
+ raise ValueError(
+ "If the `request` argument is set, then none of "
+ "the individual field arguments should be set."
+ )
+
+ request = cloud_billing.GetProjectBillingInfoRequest(request)
+
+ # If we have keyword arguments corresponding to fields on the
+ # request, apply these.
+
+ if name is not None:
+ request.name = name
+
+ # Wrap the RPC method; this adds retry and timeout information,
+ # and friendly error handling.
+ rpc = gapic_v1.method_async.wrap_method(
+ self._client._transport.get_project_billing_info,
+ default_timeout=None,
+ client_info=DEFAULT_CLIENT_INFO,
+ )
+
+ # Certain fields should be provided within the metadata header;
+ # add these here.
+ metadata = tuple(metadata) + (
+ gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
+ )
+
+ # Send the request.
+ response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
+
+ # Done; return the response.
+ return response
+
+ async def update_project_billing_info(
+ self,
+ request: cloud_billing.UpdateProjectBillingInfoRequest = None,
+ *,
+ name: str = None,
+ project_billing_info: cloud_billing.ProjectBillingInfo = None,
+ retry: retries.Retry = gapic_v1.method.DEFAULT,
+ timeout: float = None,
+ metadata: Sequence[Tuple[str, str]] = (),
+ ) -> cloud_billing.ProjectBillingInfo:
+ r"""Sets or updates the billing account associated with a project.
+ You specify the new billing account by setting the
+ ``billing_account_name`` in the ``ProjectBillingInfo`` resource
+ to the resource name of a billing account. Associating a project
+ with an open billing account enables billing on the project and
+ allows charges for resource usage. If the project already had a
+ billing account, this method changes the billing account used
+ for resource usage charges.
+
+ *Note:* Incurred charges that have not yet been reported in the
+ transaction history of the GCP Console might be billed to the
+ new billing account, even if the charge occurred before the new
+ billing account was assigned to the project.
+
+ The current authenticated user must have ownership privileges
+ for both the
+ `project `__
+ and the `billing
+ account `__.
+
+ You can disable billing on the project by setting the
+ ``billing_account_name`` field to empty. This action
+ disassociates the current billing account from the project. Any
+ billable activity of your in-use services will stop, and your
+ application could stop functioning as expected. Any unbilled
+ charges to date will be billed to the previously associated
+ account. The current authenticated user must be either an owner
+ of the project or an owner of the billing account for the
+ project.
+
+ Note that associating a project with a *closed* billing account
+ will have much the same effect as disabling billing on the
+ project: any paid resources used by the project will be shut
+ down. Thus, unless you wish to disable billing, you should
+ always call this method with the name of an *open* billing
+ account.
+
+ Args:
+ request (:class:`~.cloud_billing.UpdateProjectBillingInfoRequest`):
+ The request object. Request message for
+ `UpdateProjectBillingInfo`.
+ name (:class:`str`):
+ Required. The resource name of the project associated
+ with the billing information that you want to update.
+ For example, ``projects/tokyo-rain-123``.
+ This corresponds to the ``name`` field
+ on the ``request`` instance; if ``request`` is provided, this
+ should not be set.
+ project_billing_info (:class:`~.cloud_billing.ProjectBillingInfo`):
+ The new billing information for the project. Read-only
+ fields are ignored; thus, you can leave empty all fields
+ except ``billing_account_name``.
+ This corresponds to the ``project_billing_info`` field
+ on the ``request`` instance; if ``request`` is provided, this
+ should not be set.
+
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
+ should be retried.
+ timeout (float): The timeout for this request.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
+
+ Returns:
+ ~.cloud_billing.ProjectBillingInfo:
+ Encapsulation of billing information
+ for a GCP Console project. A project has
+ at most one associated billing account
+ at a time (but a billing account can be
+ assigned to multiple projects).
+
+ """
+ # Create or coerce a protobuf request object.
+ # Sanity check: If we got a request object, we should *not* have
+ # gotten any keyword arguments that map to the request.
+ has_flattened_params = any([name, project_billing_info])
+ if request is not None and has_flattened_params:
+ raise ValueError(
+ "If the `request` argument is set, then none of "
+ "the individual field arguments should be set."
+ )
+
+ request = cloud_billing.UpdateProjectBillingInfoRequest(request)
+
+ # If we have keyword arguments corresponding to fields on the
+ # request, apply these.
+
+ if name is not None:
+ request.name = name
+ if project_billing_info is not None:
+ request.project_billing_info = project_billing_info
+
+ # Wrap the RPC method; this adds retry and timeout information,
+ # and friendly error handling.
+ rpc = gapic_v1.method_async.wrap_method(
+ self._client._transport.update_project_billing_info,
+ default_timeout=None,
+ client_info=DEFAULT_CLIENT_INFO,
+ )
+
+ # Certain fields should be provided within the metadata header;
+ # add these here.
+ metadata = tuple(metadata) + (
+ gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
+ )
+
+ # Send the request.
+ response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
+
+ # Done; return the response.
+ return response
+
+ async def get_iam_policy(
+ self,
+ request: iam_policy.GetIamPolicyRequest = None,
+ *,
+ resource: str = None,
+ retry: retries.Retry = gapic_v1.method.DEFAULT,
+ timeout: float = None,
+ metadata: Sequence[Tuple[str, str]] = (),
+ ) -> policy.Policy:
+ r"""Gets the access control policy for a billing account. The caller
+ must have the ``billing.accounts.getIamPolicy`` permission on
+ the account, which is often given to billing account
+ `viewers `__.
+
+ Args:
+ request (:class:`~.iam_policy.GetIamPolicyRequest`):
+ The request object. Request message for `GetIamPolicy`
+ method.
+ resource (:class:`str`):
+ REQUIRED: The resource for which the
+ policy is being requested. See the
+ operation documentation for the
+ appropriate value for this field.
+ This corresponds to the ``resource`` field
+ on the ``request`` instance; if ``request`` is provided, this
+ should not be set.
+
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
+ should be retried.
+ timeout (float): The timeout for this request.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
+
+ Returns:
+ ~.policy.Policy:
+ Defines an Identity and Access Management (IAM) policy.
+ It is used to specify access control policies for Cloud
+ Platform resources.
+
+ A ``Policy`` is a collection of ``bindings``. A
+ ``binding`` binds one or more ``members`` to a single
+ ``role``. Members can be user accounts, service
+ accounts, Google groups, and domains (such as G Suite).
+ A ``role`` is a named list of permissions (defined by
+ IAM or configured by users). A ``binding`` can
+ optionally specify a ``condition``, which is a logic
+ expression that further constrains the role binding
+ based on attributes about the request and/or target
+ resource.
+
+ **JSON Example**
+
+ ::
+
+ {
+ "bindings": [
+ {
+ "role": "roles/resourcemanager.organizationAdmin",
+ "members": [
+ "user:mike@example.com",
+ "group:admins@example.com",
+ "domain:google.com",
+ "serviceAccount:my-project-id@appspot.gserviceaccount.com"
+ ]
+ },
+ {
+ "role": "roles/resourcemanager.organizationViewer",
+ "members": ["user:eve@example.com"],
+ "condition": {
+ "title": "expirable access",
+ "description": "Does not grant access after Sep 2020",
+ "expression": "request.time <
+ timestamp('2020-10-01T00:00:00.000Z')",
+ }
+ }
+ ]
+ }
+
+ **YAML Example**
+
+ ::
+
+ bindings:
+ - members:
+ - user:mike@example.com
+ - group:admins@example.com
+ - domain:google.com
+ - serviceAccount:my-project-id@appspot.gserviceaccount.com
+ role: roles/resourcemanager.organizationAdmin
+ - members:
+ - user:eve@example.com
+ role: roles/resourcemanager.organizationViewer
+ condition:
+ title: expirable access
+ description: Does not grant access after Sep 2020
+ expression: request.time < timestamp('2020-10-01T00:00:00.000Z')
+
+ For a description of IAM and its features, see the `IAM
+ developer's
+ guide `__.
+
+ """
+ # Create or coerce a protobuf request object.
+ # Sanity check: If we got a request object, we should *not* have
+ # gotten any keyword arguments that map to the request.
+ has_flattened_params = any([resource])
+ if request is not None and has_flattened_params:
+ raise ValueError(
+ "If the `request` argument is set, then none of "
+ "the individual field arguments should be set."
+ )
+
+ # The request isn't a proto-plus wrapped type,
+ # so it must be constructed via keyword expansion.
+ if isinstance(request, dict):
+ request = iam_policy.GetIamPolicyRequest(**request)
+
+ elif not request:
+ request = iam_policy.GetIamPolicyRequest(resource=resource,)
+
+ # Wrap the RPC method; this adds retry and timeout information,
+ # and friendly error handling.
+ rpc = gapic_v1.method_async.wrap_method(
+ self._client._transport.get_iam_policy,
+ default_timeout=None,
+ client_info=DEFAULT_CLIENT_INFO,
+ )
+
+ # Certain fields should be provided within the metadata header;
+ # add these here.
+ metadata = tuple(metadata) + (
+ gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)),
+ )
+
+ # Send the request.
+ response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
+
+ # Done; return the response.
+ return response
+
+ async def set_iam_policy(
+ self,
+ request: iam_policy.SetIamPolicyRequest = None,
+ *,
+ resource: str = None,
+ retry: retries.Retry = gapic_v1.method.DEFAULT,
+ timeout: float = None,
+ metadata: Sequence[Tuple[str, str]] = (),
+ ) -> policy.Policy:
+ r"""Sets the access control policy for a billing account. Replaces
+ any existing policy. The caller must have the
+ ``billing.accounts.setIamPolicy`` permission on the account,
+ which is often given to billing account
+ `administrators `__.
+
+ Args:
+ request (:class:`~.iam_policy.SetIamPolicyRequest`):
+ The request object. Request message for `SetIamPolicy`
+ method.
+ resource (:class:`str`):
+ REQUIRED: The resource for which the
+ policy is being specified. See the
+ operation documentation for the
+ appropriate value for this field.
+ This corresponds to the ``resource`` field
+ on the ``request`` instance; if ``request`` is provided, this
+ should not be set.
+
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
+ should be retried.
+ timeout (float): The timeout for this request.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
+
+ Returns:
+ ~.policy.Policy:
+ Defines an Identity and Access Management (IAM) policy.
+ It is used to specify access control policies for Cloud
+ Platform resources.
+
+ A ``Policy`` is a collection of ``bindings``. A
+ ``binding`` binds one or more ``members`` to a single
+ ``role``. Members can be user accounts, service
+ accounts, Google groups, and domains (such as G Suite).
+ A ``role`` is a named list of permissions (defined by
+ IAM or configured by users). A ``binding`` can
+ optionally specify a ``condition``, which is a logic
+ expression that further constrains the role binding
+ based on attributes about the request and/or target
+ resource.
+
+ **JSON Example**
+
+ ::
+
+ {
+ "bindings": [
+ {
+ "role": "roles/resourcemanager.organizationAdmin",
+ "members": [
+ "user:mike@example.com",
+ "group:admins@example.com",
+ "domain:google.com",
+ "serviceAccount:my-project-id@appspot.gserviceaccount.com"
+ ]
+ },
+ {
+ "role": "roles/resourcemanager.organizationViewer",
+ "members": ["user:eve@example.com"],
+ "condition": {
+ "title": "expirable access",
+ "description": "Does not grant access after Sep 2020",
+ "expression": "request.time <
+ timestamp('2020-10-01T00:00:00.000Z')",
+ }
+ }
+ ]
+ }
+
+ **YAML Example**
+
+ ::
+
+ bindings:
+ - members:
+ - user:mike@example.com
+ - group:admins@example.com
+ - domain:google.com
+ - serviceAccount:my-project-id@appspot.gserviceaccount.com
+ role: roles/resourcemanager.organizationAdmin
+ - members:
+ - user:eve@example.com
+ role: roles/resourcemanager.organizationViewer
+ condition:
+ title: expirable access
+ description: Does not grant access after Sep 2020
+ expression: request.time < timestamp('2020-10-01T00:00:00.000Z')
+
+ For a description of IAM and its features, see the `IAM
+ developer's
+ guide `__.
+
+ """
+ # Create or coerce a protobuf request object.
+ # Sanity check: If we got a request object, we should *not* have
+ # gotten any keyword arguments that map to the request.
+ has_flattened_params = any([resource])
+ if request is not None and has_flattened_params:
+ raise ValueError(
+ "If the `request` argument is set, then none of "
+ "the individual field arguments should be set."
+ )
+
+ # The request isn't a proto-plus wrapped type,
+ # so it must be constructed via keyword expansion.
+ if isinstance(request, dict):
+ request = iam_policy.SetIamPolicyRequest(**request)
+
+ elif not request:
+ request = iam_policy.SetIamPolicyRequest(resource=resource,)
+
+ # Wrap the RPC method; this adds retry and timeout information,
+ # and friendly error handling.
+ rpc = gapic_v1.method_async.wrap_method(
+ self._client._transport.set_iam_policy,
+ default_timeout=None,
+ client_info=DEFAULT_CLIENT_INFO,
+ )
+
+ # Certain fields should be provided within the metadata header;
+ # add these here.
+ metadata = tuple(metadata) + (
+ gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)),
+ )
+
+ # Send the request.
+ response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
+
+ # Done; return the response.
+ return response
+
+ async def test_iam_permissions(
+ self,
+ request: iam_policy.TestIamPermissionsRequest = None,
+ *,
+ resource: str = None,
+ permissions: Sequence[str] = None,
+ retry: retries.Retry = gapic_v1.method.DEFAULT,
+ timeout: float = None,
+ metadata: Sequence[Tuple[str, str]] = (),
+ ) -> iam_policy.TestIamPermissionsResponse:
+ r"""Tests the access control policy for a billing
+ account. This method takes the resource and a set of
+ permissions as input and returns the subset of the input
+ permissions that the caller is allowed for that
+ resource.
+
+ Args:
+ request (:class:`~.iam_policy.TestIamPermissionsRequest`):
+ The request object. Request message for
+ `TestIamPermissions` method.
+ resource (:class:`str`):
+ REQUIRED: The resource for which the
+ policy detail is being requested. See
+ the operation documentation for the
+ appropriate value for this field.
+ This corresponds to the ``resource`` field
+ on the ``request`` instance; if ``request`` is provided, this
+ should not be set.
+ permissions (:class:`Sequence[str]`):
+ The set of permissions to check for the ``resource``.
+ Permissions with wildcards (such as '*' or 'storage.*')
+ are not allowed. For more information see `IAM
+ Overview `__.
+ This corresponds to the ``permissions`` field
+ on the ``request`` instance; if ``request`` is provided, this
+ should not be set.
+
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
+ should be retried.
+ timeout (float): The timeout for this request.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
+
+ Returns:
+ ~.iam_policy.TestIamPermissionsResponse:
+ Response message for ``TestIamPermissions`` method.
+ """
+ # Create or coerce a protobuf request object.
+ # Sanity check: If we got a request object, we should *not* have
+ # gotten any keyword arguments that map to the request.
+ has_flattened_params = any([resource, permissions])
+ if request is not None and has_flattened_params:
+ raise ValueError(
+ "If the `request` argument is set, then none of "
+ "the individual field arguments should be set."
+ )
+
+ # The request isn't a proto-plus wrapped type,
+ # so it must be constructed via keyword expansion.
+ if isinstance(request, dict):
+ request = iam_policy.TestIamPermissionsRequest(**request)
+
+ elif not request:
+ request = iam_policy.TestIamPermissionsRequest(
+ resource=resource, permissions=permissions,
+ )
+
+ # Wrap the RPC method; this adds retry and timeout information,
+ # and friendly error handling.
+ rpc = gapic_v1.method_async.wrap_method(
+ self._client._transport.test_iam_permissions,
+ default_timeout=None,
+ client_info=DEFAULT_CLIENT_INFO,
+ )
+
+ # Certain fields should be provided within the metadata header;
+ # add these here.
+ metadata = tuple(metadata) + (
+ gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)),
+ )
+
+ # Send the request.
+ response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
+
+ # Done; return the response.
+ return response
+
+
+try:
+ DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
+ gapic_version=pkg_resources.get_distribution("google-cloud-billing",).version,
+ )
+except pkg_resources.DistributionNotFound:
+ DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo()
+
+
+__all__ = ("CloudBillingAsyncClient",)
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/client.py b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/client.py
index cba969dd66f6..1db4189912e6 100644
--- a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/client.py
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/client.py
@@ -16,15 +16,20 @@
#
from collections import OrderedDict
+from distutils import util
+import os
import re
-from typing import Callable, Dict, Sequence, Tuple, Type, Union
+from typing import Callable, Dict, Optional, Sequence, Tuple, Type, Union
import pkg_resources
-import google.api_core.client_options as ClientOptions # type: ignore
+from google.api_core import client_options as client_options_lib # type: ignore
from google.api_core import exceptions # type: ignore
from google.api_core import gapic_v1 # type: ignore
from google.api_core import retry as retries # type: ignore
from google.auth import credentials # type: ignore
+from google.auth.transport import mtls # type: ignore
+from google.auth.transport.grpc import SslCredentials # type: ignore
+from google.auth.exceptions import MutualTLSChannelError # type: ignore
from google.oauth2 import service_account # type: ignore
from google.cloud.billing_v1.services.cloud_billing import pagers
@@ -32,8 +37,9 @@
from google.iam.v1 import iam_policy_pb2 as iam_policy # type: ignore
from google.iam.v1 import policy_pb2 as policy # type: ignore
-from .transports.base import CloudBillingTransport
+from .transports.base import CloudBillingTransport, DEFAULT_CLIENT_INFO
from .transports.grpc import CloudBillingGrpcTransport
+from .transports.grpc_asyncio import CloudBillingGrpcAsyncIOTransport
class CloudBillingClientMeta(type):
@@ -46,8 +52,9 @@ class CloudBillingClientMeta(type):
_transport_registry = OrderedDict() # type: Dict[str, Type[CloudBillingTransport]]
_transport_registry["grpc"] = CloudBillingGrpcTransport
+ _transport_registry["grpc_asyncio"] = CloudBillingGrpcAsyncIOTransport
- def get_transport_class(cls, label: str = None) -> Type[CloudBillingTransport]:
+ def get_transport_class(cls, label: str = None,) -> Type[CloudBillingTransport]:
"""Return an appropriate transport class.
Args:
@@ -125,12 +132,81 @@ def from_service_account_file(cls, filename: str, *args, **kwargs):
from_service_account_json = from_service_account_file
+ @property
+ def transport(self) -> CloudBillingTransport:
+ """Return the transport used by the client instance.
+
+ Returns:
+ CloudBillingTransport: The transport used by the client instance.
+ """
+ return self._transport
+
+ @staticmethod
+ def common_billing_account_path(billing_account: str,) -> str:
+ """Return a fully-qualified billing_account string."""
+ return "billingAccounts/{billing_account}".format(
+ billing_account=billing_account,
+ )
+
+ @staticmethod
+ def parse_common_billing_account_path(path: str) -> Dict[str, str]:
+ """Parse a billing_account path into its component segments."""
+ m = re.match(r"^billingAccounts/(?P.+?)$", path)
+ return m.groupdict() if m else {}
+
+ @staticmethod
+ def common_folder_path(folder: str,) -> str:
+ """Return a fully-qualified folder string."""
+ return "folders/{folder}".format(folder=folder,)
+
+ @staticmethod
+ def parse_common_folder_path(path: str) -> Dict[str, str]:
+ """Parse a folder path into its component segments."""
+ m = re.match(r"^folders/(?P.+?)$", path)
+ return m.groupdict() if m else {}
+
+ @staticmethod
+ def common_organization_path(organization: str,) -> str:
+ """Return a fully-qualified organization string."""
+ return "organizations/{organization}".format(organization=organization,)
+
+ @staticmethod
+ def parse_common_organization_path(path: str) -> Dict[str, str]:
+ """Parse a organization path into its component segments."""
+ m = re.match(r"^organizations/(?P.+?)$", path)
+ return m.groupdict() if m else {}
+
+ @staticmethod
+ def common_project_path(project: str,) -> str:
+ """Return a fully-qualified project string."""
+ return "projects/{project}".format(project=project,)
+
+ @staticmethod
+ def parse_common_project_path(path: str) -> Dict[str, str]:
+ """Parse a project path into its component segments."""
+ m = re.match(r"^projects/(?P.+?)$", path)
+ return m.groupdict() if m else {}
+
+ @staticmethod
+ def common_location_path(project: str, location: str,) -> str:
+ """Return a fully-qualified location string."""
+ return "projects/{project}/locations/{location}".format(
+ project=project, location=location,
+ )
+
+ @staticmethod
+ def parse_common_location_path(path: str) -> Dict[str, str]:
+ """Parse a location path into its component segments."""
+ m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path)
+ return m.groupdict() if m else {}
+
def __init__(
self,
*,
- credentials: credentials.Credentials = None,
- transport: Union[str, CloudBillingTransport] = None,
- client_options: ClientOptions = None,
+ credentials: Optional[credentials.Credentials] = None,
+ transport: Union[str, CloudBillingTransport, None] = None,
+ client_options: Optional[client_options_lib.ClientOptions] = None,
+ client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
) -> None:
"""Instantiate the cloud billing client.
@@ -143,66 +219,102 @@ def __init__(
transport (Union[str, ~.CloudBillingTransport]): The
transport to use. If set to None, a transport is chosen
automatically.
- client_options (ClientOptions): Custom options for the client.
+ client_options (client_options_lib.ClientOptions): Custom options for the
+ client. It won't take effect if a ``transport`` instance is provided.
(1) The ``api_endpoint`` property can be used to override the
- default endpoint provided by the client.
- (2) If ``transport`` argument is None, ``client_options`` can be
- used to create a mutual TLS transport. If ``client_cert_source``
- is provided, mutual TLS transport will be created with the given
- ``api_endpoint`` or the default mTLS endpoint, and the client
- SSL credentials obtained from ``client_cert_source``.
+ default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT
+ environment variable can also be used to override the endpoint:
+ "always" (always use the default mTLS endpoint), "never" (always
+ use the default regular endpoint) and "auto" (auto switch to the
+ default mTLS endpoint if client certificate is present, this is
+ the default value). However, the ``api_endpoint`` property takes
+ precedence if provided.
+ (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable
+ is "true", then the ``client_cert_source`` property can be used
+ to provide client certificate for mutual TLS transport. If
+ not provided, the default SSL client certificate will be used if
+ present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not
+ set, no client certificate will be used.
+ client_info (google.api_core.gapic_v1.client_info.ClientInfo):
+ The client info used to send a user-agent string along with
+ API requests. If ``None``, then default info will be used.
+ Generally, you only need to set this if you're developing
+ your own client library.
Raises:
- google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
+ google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport
creation failed for any reason.
"""
if isinstance(client_options, dict):
- client_options = ClientOptions.from_dict(client_options)
+ client_options = client_options_lib.from_dict(client_options)
+ if client_options is None:
+ client_options = client_options_lib.ClientOptions()
+
+ # Create SSL credentials for mutual TLS if needed.
+ use_client_cert = bool(
+ util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"))
+ )
+
+ ssl_credentials = None
+ is_mtls = False
+ if use_client_cert:
+ if client_options.client_cert_source:
+ import grpc # type: ignore
+
+ cert, key = client_options.client_cert_source()
+ ssl_credentials = grpc.ssl_channel_credentials(
+ certificate_chain=cert, private_key=key
+ )
+ is_mtls = True
+ else:
+ creds = SslCredentials()
+ is_mtls = creds.is_mtls
+ ssl_credentials = creds.ssl_credentials if is_mtls else None
+
+ # Figure out which api endpoint to use.
+ if client_options.api_endpoint is not None:
+ api_endpoint = client_options.api_endpoint
+ else:
+ use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
+ if use_mtls_env == "never":
+ api_endpoint = self.DEFAULT_ENDPOINT
+ elif use_mtls_env == "always":
+ api_endpoint = self.DEFAULT_MTLS_ENDPOINT
+ elif use_mtls_env == "auto":
+ api_endpoint = (
+ self.DEFAULT_MTLS_ENDPOINT if is_mtls else self.DEFAULT_ENDPOINT
+ )
+ else:
+ raise MutualTLSChannelError(
+ "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always"
+ )
# Save or instantiate the transport.
# Ordinarily, we provide the transport, but allowing a custom transport
# instance provides an extensibility point for unusual situations.
if isinstance(transport, CloudBillingTransport):
# transport is a CloudBillingTransport instance.
- if credentials:
+ if credentials or client_options.credentials_file:
raise ValueError(
"When providing a transport instance, "
"provide its credentials directly."
)
+ if client_options.scopes:
+ raise ValueError(
+ "When providing a transport instance, "
+ "provide its scopes directly."
+ )
self._transport = transport
- elif client_options is None or (
- client_options.api_endpoint is None
- and client_options.client_cert_source is None
- ):
- # Don't trigger mTLS if we get an empty ClientOptions.
+ else:
Transport = type(self).get_transport_class(transport)
self._transport = Transport(
- credentials=credentials, host=self.DEFAULT_ENDPOINT
- )
- else:
- # We have a non-empty ClientOptions. If client_cert_source is
- # provided, trigger mTLS with user provided endpoint or the default
- # mTLS endpoint.
- if client_options.client_cert_source:
- api_mtls_endpoint = (
- client_options.api_endpoint
- if client_options.api_endpoint
- else self.DEFAULT_MTLS_ENDPOINT
- )
- else:
- api_mtls_endpoint = None
-
- api_endpoint = (
- client_options.api_endpoint
- if client_options.api_endpoint
- else self.DEFAULT_ENDPOINT
- )
-
- self._transport = CloudBillingGrpcTransport(
credentials=credentials,
+ credentials_file=client_options.credentials_file,
host=api_endpoint,
- api_mtls_endpoint=api_mtls_endpoint,
- client_cert_source=client_options.client_cert_source,
+ scopes=client_options.scopes,
+ ssl_channel_credentials=ssl_credentials,
+ quota_project_id=client_options.quota_project_id,
+ client_info=client_info,
)
def get_billing_account(
@@ -246,27 +358,29 @@ def get_billing_account(
# Create or coerce a protobuf request object.
# Sanity check: If we got a request object, we should *not* have
# gotten any keyword arguments that map to the request.
- if request is not None and any([name]):
+ has_flattened_params = any([name])
+ if request is not None and has_flattened_params:
raise ValueError(
"If the `request` argument is set, then none of "
"the individual field arguments should be set."
)
- request = cloud_billing.GetBillingAccountRequest(request)
+ # Minor optimization to avoid making a copy if the user passes
+ # in a cloud_billing.GetBillingAccountRequest.
+ # There's no risk of modifying the input as we've already verified
+ # there are no flattened fields.
+ if not isinstance(request, cloud_billing.GetBillingAccountRequest):
+ request = cloud_billing.GetBillingAccountRequest(request)
- # If we have keyword arguments corresponding to fields on the
- # request, apply these.
+ # If we have keyword arguments corresponding to fields on the
+ # request, apply these.
- if name is not None:
- request.name = name
+ if name is not None:
+ request.name = name
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
- rpc = gapic_v1.method.wrap_method(
- self._transport.get_billing_account,
- default_timeout=None,
- client_info=_client_info,
- )
+ rpc = self._transport._wrapped_methods[self._transport.get_billing_account]
# Certain fields should be provided within the metadata header;
# add these here.
@@ -275,7 +389,7 @@ def get_billing_account(
)
# Send the request.
- response = rpc(request, retry=retry, timeout=timeout, metadata=metadata)
+ response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
# Done; return the response.
return response
@@ -313,23 +427,24 @@ def list_billing_accounts(
"""
# Create or coerce a protobuf request object.
- request = cloud_billing.ListBillingAccountsRequest(request)
+ # Minor optimization to avoid making a copy if the user passes
+ # in a cloud_billing.ListBillingAccountsRequest.
+ # There's no risk of modifying the input as we've already verified
+ # there are no flattened fields.
+ if not isinstance(request, cloud_billing.ListBillingAccountsRequest):
+ request = cloud_billing.ListBillingAccountsRequest(request)
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
- rpc = gapic_v1.method.wrap_method(
- self._transport.list_billing_accounts,
- default_timeout=None,
- client_info=_client_info,
- )
+ rpc = self._transport._wrapped_methods[self._transport.list_billing_accounts]
# Send the request.
- response = rpc(request, retry=retry, timeout=timeout, metadata=metadata)
+ response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
# This method is paged; wrap the response in a pager, which provides
# an `__iter__` convenience method.
response = pagers.ListBillingAccountsPager(
- method=rpc, request=request, response=response
+ method=rpc, request=request, response=response, metadata=metadata,
)
# Done; return the response.
@@ -386,32 +501,40 @@ def update_billing_account(
# Create or coerce a protobuf request object.
# Sanity check: If we got a request object, we should *not* have
# gotten any keyword arguments that map to the request.
- if request is not None and any([name, account]):
+ has_flattened_params = any([name, account])
+ if request is not None and has_flattened_params:
raise ValueError(
"If the `request` argument is set, then none of "
"the individual field arguments should be set."
)
- request = cloud_billing.UpdateBillingAccountRequest(request)
+ # Minor optimization to avoid making a copy if the user passes
+ # in a cloud_billing.UpdateBillingAccountRequest.
+ # There's no risk of modifying the input as we've already verified
+ # there are no flattened fields.
+ if not isinstance(request, cloud_billing.UpdateBillingAccountRequest):
+ request = cloud_billing.UpdateBillingAccountRequest(request)
- # If we have keyword arguments corresponding to fields on the
- # request, apply these.
+ # If we have keyword arguments corresponding to fields on the
+ # request, apply these.
- if name is not None:
- request.name = name
- if account is not None:
- request.account = account
+ if name is not None:
+ request.name = name
+ if account is not None:
+ request.account = account
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
- rpc = gapic_v1.method.wrap_method(
- self._transport.update_billing_account,
- default_timeout=None,
- client_info=_client_info,
+ rpc = self._transport._wrapped_methods[self._transport.update_billing_account]
+
+ # Certain fields should be provided within the metadata header;
+ # add these here.
+ metadata = tuple(metadata) + (
+ gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
)
# Send the request.
- response = rpc(request, retry=retry, timeout=timeout, metadata=metadata)
+ response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
# Done; return the response.
return response
@@ -467,30 +590,32 @@ def create_billing_account(
# Create or coerce a protobuf request object.
# Sanity check: If we got a request object, we should *not* have
# gotten any keyword arguments that map to the request.
- if request is not None and any([billing_account]):
+ has_flattened_params = any([billing_account])
+ if request is not None and has_flattened_params:
raise ValueError(
"If the `request` argument is set, then none of "
"the individual field arguments should be set."
)
- request = cloud_billing.CreateBillingAccountRequest(request)
+ # Minor optimization to avoid making a copy if the user passes
+ # in a cloud_billing.CreateBillingAccountRequest.
+ # There's no risk of modifying the input as we've already verified
+ # there are no flattened fields.
+ if not isinstance(request, cloud_billing.CreateBillingAccountRequest):
+ request = cloud_billing.CreateBillingAccountRequest(request)
- # If we have keyword arguments corresponding to fields on the
- # request, apply these.
+ # If we have keyword arguments corresponding to fields on the
+ # request, apply these.
- if billing_account is not None:
- request.billing_account = billing_account
+ if billing_account is not None:
+ request.billing_account = billing_account
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
- rpc = gapic_v1.method.wrap_method(
- self._transport.create_billing_account,
- default_timeout=None,
- client_info=_client_info,
- )
+ rpc = self._transport._wrapped_methods[self._transport.create_billing_account]
# Send the request.
- response = rpc(request, retry=retry, timeout=timeout, metadata=metadata)
+ response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
# Done; return the response.
return response
@@ -539,27 +664,31 @@ def list_project_billing_info(
# Create or coerce a protobuf request object.
# Sanity check: If we got a request object, we should *not* have
# gotten any keyword arguments that map to the request.
- if request is not None and any([name]):
+ has_flattened_params = any([name])
+ if request is not None and has_flattened_params:
raise ValueError(
"If the `request` argument is set, then none of "
"the individual field arguments should be set."
)
- request = cloud_billing.ListProjectBillingInfoRequest(request)
+ # Minor optimization to avoid making a copy if the user passes
+ # in a cloud_billing.ListProjectBillingInfoRequest.
+ # There's no risk of modifying the input as we've already verified
+ # there are no flattened fields.
+ if not isinstance(request, cloud_billing.ListProjectBillingInfoRequest):
+ request = cloud_billing.ListProjectBillingInfoRequest(request)
- # If we have keyword arguments corresponding to fields on the
- # request, apply these.
+ # If we have keyword arguments corresponding to fields on the
+ # request, apply these.
- if name is not None:
- request.name = name
+ if name is not None:
+ request.name = name
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
- rpc = gapic_v1.method.wrap_method(
- self._transport.list_project_billing_info,
- default_timeout=None,
- client_info=_client_info,
- )
+ rpc = self._transport._wrapped_methods[
+ self._transport.list_project_billing_info
+ ]
# Certain fields should be provided within the metadata header;
# add these here.
@@ -568,12 +697,12 @@ def list_project_billing_info(
)
# Send the request.
- response = rpc(request, retry=retry, timeout=timeout, metadata=metadata)
+ response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
# This method is paged; wrap the response in a pager, which provides
# an `__iter__` convenience method.
response = pagers.ListProjectBillingInfoPager(
- method=rpc, request=request, response=response
+ method=rpc, request=request, response=response, metadata=metadata,
)
# Done; return the response.
@@ -622,27 +751,29 @@ def get_project_billing_info(
# Create or coerce a protobuf request object.
# Sanity check: If we got a request object, we should *not* have
# gotten any keyword arguments that map to the request.
- if request is not None and any([name]):
+ has_flattened_params = any([name])
+ if request is not None and has_flattened_params:
raise ValueError(
"If the `request` argument is set, then none of "
"the individual field arguments should be set."
)
- request = cloud_billing.GetProjectBillingInfoRequest(request)
+ # Minor optimization to avoid making a copy if the user passes
+ # in a cloud_billing.GetProjectBillingInfoRequest.
+ # There's no risk of modifying the input as we've already verified
+ # there are no flattened fields.
+ if not isinstance(request, cloud_billing.GetProjectBillingInfoRequest):
+ request = cloud_billing.GetProjectBillingInfoRequest(request)
- # If we have keyword arguments corresponding to fields on the
- # request, apply these.
+ # If we have keyword arguments corresponding to fields on the
+ # request, apply these.
- if name is not None:
- request.name = name
+ if name is not None:
+ request.name = name
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
- rpc = gapic_v1.method.wrap_method(
- self._transport.get_project_billing_info,
- default_timeout=None,
- client_info=_client_info,
- )
+ rpc = self._transport._wrapped_methods[self._transport.get_project_billing_info]
# Certain fields should be provided within the metadata header;
# add these here.
@@ -651,7 +782,7 @@ def get_project_billing_info(
)
# Send the request.
- response = rpc(request, retry=retry, timeout=timeout, metadata=metadata)
+ response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
# Done; return the response.
return response
@@ -740,32 +871,42 @@ def update_project_billing_info(
# Create or coerce a protobuf request object.
# Sanity check: If we got a request object, we should *not* have
# gotten any keyword arguments that map to the request.
- if request is not None and any([name, project_billing_info]):
+ has_flattened_params = any([name, project_billing_info])
+ if request is not None and has_flattened_params:
raise ValueError(
"If the `request` argument is set, then none of "
"the individual field arguments should be set."
)
- request = cloud_billing.UpdateProjectBillingInfoRequest(request)
+ # Minor optimization to avoid making a copy if the user passes
+ # in a cloud_billing.UpdateProjectBillingInfoRequest.
+ # There's no risk of modifying the input as we've already verified
+ # there are no flattened fields.
+ if not isinstance(request, cloud_billing.UpdateProjectBillingInfoRequest):
+ request = cloud_billing.UpdateProjectBillingInfoRequest(request)
- # If we have keyword arguments corresponding to fields on the
- # request, apply these.
+ # If we have keyword arguments corresponding to fields on the
+ # request, apply these.
- if name is not None:
- request.name = name
- if project_billing_info is not None:
- request.project_billing_info = project_billing_info
+ if name is not None:
+ request.name = name
+ if project_billing_info is not None:
+ request.project_billing_info = project_billing_info
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
- rpc = gapic_v1.method.wrap_method(
- self._transport.update_project_billing_info,
- default_timeout=None,
- client_info=_client_info,
+ rpc = self._transport._wrapped_methods[
+ self._transport.update_project_billing_info
+ ]
+
+ # Certain fields should be provided within the metadata header;
+ # add these here.
+ metadata = tuple(metadata) + (
+ gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
)
# Send the request.
- response = rpc(request, retry=retry, timeout=timeout, metadata=metadata)
+ response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
# Done; return the response.
return response
@@ -875,7 +1016,8 @@ def get_iam_policy(
# Create or coerce a protobuf request object.
# Sanity check: If we got a request object, we should *not* have
# gotten any keyword arguments that map to the request.
- if request is not None and any([resource]):
+ has_flattened_params = any([resource])
+ if request is not None and has_flattened_params:
raise ValueError(
"If the `request` argument is set, then none of "
"the individual field arguments should be set."
@@ -887,21 +1029,11 @@ def get_iam_policy(
request = iam_policy.GetIamPolicyRequest(**request)
elif not request:
- request = iam_policy.GetIamPolicyRequest()
-
- # If we have keyword arguments corresponding to fields on the
- # request, apply these.
-
- if resource is not None:
- request.resource = resource
+ request = iam_policy.GetIamPolicyRequest(resource=resource,)
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
- rpc = gapic_v1.method.wrap_method(
- self._transport.get_iam_policy,
- default_timeout=None,
- client_info=_client_info,
- )
+ rpc = self._transport._wrapped_methods[self._transport.get_iam_policy]
# Certain fields should be provided within the metadata header;
# add these here.
@@ -910,7 +1042,7 @@ def get_iam_policy(
)
# Send the request.
- response = rpc(request, retry=retry, timeout=timeout, metadata=metadata)
+ response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
# Done; return the response.
return response
@@ -1021,7 +1153,8 @@ def set_iam_policy(
# Create or coerce a protobuf request object.
# Sanity check: If we got a request object, we should *not* have
# gotten any keyword arguments that map to the request.
- if request is not None and any([resource]):
+ has_flattened_params = any([resource])
+ if request is not None and has_flattened_params:
raise ValueError(
"If the `request` argument is set, then none of "
"the individual field arguments should be set."
@@ -1033,24 +1166,20 @@ def set_iam_policy(
request = iam_policy.SetIamPolicyRequest(**request)
elif not request:
- request = iam_policy.SetIamPolicyRequest()
-
- # If we have keyword arguments corresponding to fields on the
- # request, apply these.
-
- if resource is not None:
- request.resource = resource
+ request = iam_policy.SetIamPolicyRequest(resource=resource,)
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
- rpc = gapic_v1.method.wrap_method(
- self._transport.set_iam_policy,
- default_timeout=None,
- client_info=_client_info,
+ rpc = self._transport._wrapped_methods[self._transport.set_iam_policy]
+
+ # Certain fields should be provided within the metadata header;
+ # add these here.
+ metadata = tuple(metadata) + (
+ gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)),
)
# Send the request.
- response = rpc(request, retry=retry, timeout=timeout, metadata=metadata)
+ response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
# Done; return the response.
return response
@@ -1105,7 +1234,8 @@ def test_iam_permissions(
# Create or coerce a protobuf request object.
# Sanity check: If we got a request object, we should *not* have
# gotten any keyword arguments that map to the request.
- if request is not None and any([resource, permissions]):
+ has_flattened_params = any([resource, permissions])
+ if request is not None and has_flattened_params:
raise ValueError(
"If the `request` argument is set, then none of "
"the individual field arguments should be set."
@@ -1117,38 +1247,33 @@ def test_iam_permissions(
request = iam_policy.TestIamPermissionsRequest(**request)
elif not request:
- request = iam_policy.TestIamPermissionsRequest()
-
- # If we have keyword arguments corresponding to fields on the
- # request, apply these.
-
- if resource is not None:
- request.resource = resource
-
- if permissions:
- request.permissions.extend(permissions)
+ request = iam_policy.TestIamPermissionsRequest(
+ resource=resource, permissions=permissions,
+ )
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
- rpc = gapic_v1.method.wrap_method(
- self._transport.test_iam_permissions,
- default_timeout=None,
- client_info=_client_info,
+ rpc = self._transport._wrapped_methods[self._transport.test_iam_permissions]
+
+ # Certain fields should be provided within the metadata header;
+ # add these here.
+ metadata = tuple(metadata) + (
+ gapic_v1.routing_header.to_grpc_metadata((("resource", request.resource),)),
)
# Send the request.
- response = rpc(request, retry=retry, timeout=timeout, metadata=metadata)
+ response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
# Done; return the response.
return response
try:
- _client_info = gapic_v1.client_info.ClientInfo(
- gapic_version=pkg_resources.get_distribution("google-cloud-billing").version
+ DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
+ gapic_version=pkg_resources.get_distribution("google-cloud-billing",).version,
)
except pkg_resources.DistributionNotFound:
- _client_info = gapic_v1.client_info.ClientInfo()
+ DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo()
__all__ = ("CloudBillingClient",)
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/pagers.py b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/pagers.py
index b335a6f06afd..d20271468a14 100644
--- a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/pagers.py
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/pagers.py
@@ -15,7 +15,7 @@
# limitations under the License.
#
-from typing import Any, Callable, Iterable
+from typing import Any, AsyncIterable, Awaitable, Callable, Iterable, Sequence, Tuple
from google.cloud.billing_v1.types import cloud_billing
@@ -40,12 +40,11 @@ class ListBillingAccountsPager:
def __init__(
self,
- method: Callable[
- [cloud_billing.ListBillingAccountsRequest],
- cloud_billing.ListBillingAccountsResponse,
- ],
+ method: Callable[..., cloud_billing.ListBillingAccountsResponse],
request: cloud_billing.ListBillingAccountsRequest,
response: cloud_billing.ListBillingAccountsResponse,
+ *,
+ metadata: Sequence[Tuple[str, str]] = ()
):
"""Instantiate the pager.
@@ -56,10 +55,13 @@ def __init__(
The initial request object.
response (:class:`~.cloud_billing.ListBillingAccountsResponse`):
The initial response object.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
"""
self._method = method
self._request = cloud_billing.ListBillingAccountsRequest(request)
self._response = response
+ self._metadata = metadata
def __getattr__(self, name: str) -> Any:
return getattr(self._response, name)
@@ -69,7 +71,7 @@ def pages(self) -> Iterable[cloud_billing.ListBillingAccountsResponse]:
yield self._response
while self._response.next_page_token:
self._request.page_token = self._response.next_page_token
- self._response = self._method(self._request)
+ self._response = self._method(self._request, metadata=self._metadata)
yield self._response
def __iter__(self) -> Iterable[cloud_billing.BillingAccount]:
@@ -80,6 +82,72 @@ def __repr__(self) -> str:
return "{0}<{1!r}>".format(self.__class__.__name__, self._response)
+class ListBillingAccountsAsyncPager:
+ """A pager for iterating through ``list_billing_accounts`` requests.
+
+ This class thinly wraps an initial
+ :class:`~.cloud_billing.ListBillingAccountsResponse` object, and
+ provides an ``__aiter__`` method to iterate through its
+ ``billing_accounts`` field.
+
+ If there are more pages, the ``__aiter__`` method will make additional
+ ``ListBillingAccounts`` requests and continue to iterate
+ through the ``billing_accounts`` field on the
+ corresponding responses.
+
+ All the usual :class:`~.cloud_billing.ListBillingAccountsResponse`
+ attributes are available on the pager. If multiple requests are made, only
+ the most recent response is retained, and thus used for attribute lookup.
+ """
+
+ def __init__(
+ self,
+ method: Callable[..., Awaitable[cloud_billing.ListBillingAccountsResponse]],
+ request: cloud_billing.ListBillingAccountsRequest,
+ response: cloud_billing.ListBillingAccountsResponse,
+ *,
+ metadata: Sequence[Tuple[str, str]] = ()
+ ):
+ """Instantiate the pager.
+
+ Args:
+ method (Callable): The method that was originally called, and
+ which instantiated this pager.
+ request (:class:`~.cloud_billing.ListBillingAccountsRequest`):
+ The initial request object.
+ response (:class:`~.cloud_billing.ListBillingAccountsResponse`):
+ The initial response object.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
+ """
+ self._method = method
+ self._request = cloud_billing.ListBillingAccountsRequest(request)
+ self._response = response
+ self._metadata = metadata
+
+ def __getattr__(self, name: str) -> Any:
+ return getattr(self._response, name)
+
+ @property
+ async def pages(self) -> AsyncIterable[cloud_billing.ListBillingAccountsResponse]:
+ yield self._response
+ while self._response.next_page_token:
+ self._request.page_token = self._response.next_page_token
+ self._response = await self._method(self._request, metadata=self._metadata)
+ yield self._response
+
+ def __aiter__(self) -> AsyncIterable[cloud_billing.BillingAccount]:
+ async def async_generator():
+ async for page in self.pages:
+ for response in page.billing_accounts:
+ yield response
+
+ return async_generator()
+
+ def __repr__(self) -> str:
+ return "{0}<{1!r}>".format(self.__class__.__name__, self._response)
+
+
class ListProjectBillingInfoPager:
"""A pager for iterating through ``list_project_billing_info`` requests.
@@ -100,12 +168,11 @@ class ListProjectBillingInfoPager:
def __init__(
self,
- method: Callable[
- [cloud_billing.ListProjectBillingInfoRequest],
- cloud_billing.ListProjectBillingInfoResponse,
- ],
+ method: Callable[..., cloud_billing.ListProjectBillingInfoResponse],
request: cloud_billing.ListProjectBillingInfoRequest,
response: cloud_billing.ListProjectBillingInfoResponse,
+ *,
+ metadata: Sequence[Tuple[str, str]] = ()
):
"""Instantiate the pager.
@@ -116,10 +183,13 @@ def __init__(
The initial request object.
response (:class:`~.cloud_billing.ListProjectBillingInfoResponse`):
The initial response object.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
"""
self._method = method
self._request = cloud_billing.ListProjectBillingInfoRequest(request)
self._response = response
+ self._metadata = metadata
def __getattr__(self, name: str) -> Any:
return getattr(self._response, name)
@@ -129,7 +199,7 @@ def pages(self) -> Iterable[cloud_billing.ListProjectBillingInfoResponse]:
yield self._response
while self._response.next_page_token:
self._request.page_token = self._response.next_page_token
- self._response = self._method(self._request)
+ self._response = self._method(self._request, metadata=self._metadata)
yield self._response
def __iter__(self) -> Iterable[cloud_billing.ProjectBillingInfo]:
@@ -138,3 +208,71 @@ def __iter__(self) -> Iterable[cloud_billing.ProjectBillingInfo]:
def __repr__(self) -> str:
return "{0}<{1!r}>".format(self.__class__.__name__, self._response)
+
+
+class ListProjectBillingInfoAsyncPager:
+ """A pager for iterating through ``list_project_billing_info`` requests.
+
+ This class thinly wraps an initial
+ :class:`~.cloud_billing.ListProjectBillingInfoResponse` object, and
+ provides an ``__aiter__`` method to iterate through its
+ ``project_billing_info`` field.
+
+ If there are more pages, the ``__aiter__`` method will make additional
+ ``ListProjectBillingInfo`` requests and continue to iterate
+ through the ``project_billing_info`` field on the
+ corresponding responses.
+
+ All the usual :class:`~.cloud_billing.ListProjectBillingInfoResponse`
+ attributes are available on the pager. If multiple requests are made, only
+ the most recent response is retained, and thus used for attribute lookup.
+ """
+
+ def __init__(
+ self,
+ method: Callable[..., Awaitable[cloud_billing.ListProjectBillingInfoResponse]],
+ request: cloud_billing.ListProjectBillingInfoRequest,
+ response: cloud_billing.ListProjectBillingInfoResponse,
+ *,
+ metadata: Sequence[Tuple[str, str]] = ()
+ ):
+ """Instantiate the pager.
+
+ Args:
+ method (Callable): The method that was originally called, and
+ which instantiated this pager.
+ request (:class:`~.cloud_billing.ListProjectBillingInfoRequest`):
+ The initial request object.
+ response (:class:`~.cloud_billing.ListProjectBillingInfoResponse`):
+ The initial response object.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
+ """
+ self._method = method
+ self._request = cloud_billing.ListProjectBillingInfoRequest(request)
+ self._response = response
+ self._metadata = metadata
+
+ def __getattr__(self, name: str) -> Any:
+ return getattr(self._response, name)
+
+ @property
+ async def pages(
+ self,
+ ) -> AsyncIterable[cloud_billing.ListProjectBillingInfoResponse]:
+ yield self._response
+ while self._response.next_page_token:
+ self._request.page_token = self._response.next_page_token
+ self._response = await self._method(self._request, metadata=self._metadata)
+ yield self._response
+
+ def __aiter__(self) -> AsyncIterable[cloud_billing.ProjectBillingInfo]:
+ async def async_generator():
+ async for page in self.pages:
+ for response in page.project_billing_info:
+ yield response
+
+ return async_generator()
+
+ def __repr__(self) -> str:
+ return "{0}<{1!r}>".format(self.__class__.__name__, self._response)
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/transports/__init__.py b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/transports/__init__.py
index e8cfecae594d..e80f5b8c5ded 100644
--- a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/transports/__init__.py
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/transports/__init__.py
@@ -20,11 +20,16 @@
from .base import CloudBillingTransport
from .grpc import CloudBillingGrpcTransport
+from .grpc_asyncio import CloudBillingGrpcAsyncIOTransport
# Compile a registry of transports.
_transport_registry = OrderedDict() # type: Dict[str, Type[CloudBillingTransport]]
_transport_registry["grpc"] = CloudBillingGrpcTransport
+_transport_registry["grpc_asyncio"] = CloudBillingGrpcAsyncIOTransport
-
-__all__ = ("CloudBillingTransport", "CloudBillingGrpcTransport")
+__all__ = (
+ "CloudBillingTransport",
+ "CloudBillingGrpcTransport",
+ "CloudBillingGrpcAsyncIOTransport",
+)
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/transports/base.py b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/transports/base.py
index a11bcc4f722d..ee8d2d170a80 100644
--- a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/transports/base.py
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/transports/base.py
@@ -17,8 +17,12 @@
import abc
import typing
+import pkg_resources
-from google import auth
+from google import auth # type: ignore
+from google.api_core import exceptions # type: ignore
+from google.api_core import gapic_v1 # type: ignore
+from google.api_core import retry as retries # type: ignore
from google.auth import credentials # type: ignore
from google.cloud.billing_v1.types import cloud_billing
@@ -26,7 +30,15 @@
from google.iam.v1 import policy_pb2 as policy # type: ignore
-class CloudBillingTransport(metaclass=abc.ABCMeta):
+try:
+ DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
+ gapic_version=pkg_resources.get_distribution("google-cloud-billing",).version,
+ )
+except pkg_resources.DistributionNotFound:
+ DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo()
+
+
+class CloudBillingTransport(abc.ABC):
"""Abstract transport class for CloudBilling."""
AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",)
@@ -36,6 +48,11 @@ def __init__(
*,
host: str = "cloudbilling.googleapis.com",
credentials: credentials.Credentials = None,
+ credentials_file: typing.Optional[str] = None,
+ scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES,
+ quota_project_id: typing.Optional[str] = None,
+ client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
+ **kwargs,
) -> None:
"""Instantiate the transport.
@@ -46,6 +63,17 @@ def __init__(
credentials identify the application to the service; if none
are specified, the client will attempt to ascertain the
credentials from the environment.
+ credentials_file (Optional[str]): A file with credentials that can
+ be loaded with :func:`google.auth.load_credentials_from_file`.
+ This argument is mutually exclusive with credentials.
+ scope (Optional[Sequence[str]]): A list of scopes.
+ quota_project_id (Optional[str]): An optional project to use for billing
+ and quota.
+ client_info (google.api_core.gapic_v1.client_info.ClientInfo):
+ The client info used to send a user-agent string along with
+ API requests. If ``None``, then default info will be used.
+ Generally, you only need to set this if you're developing
+ your own client library.
"""
# Save the hostname. Default to port 443 (HTTPS) if none is specified.
if ":" not in host:
@@ -54,90 +82,186 @@ def __init__(
# If no credentials are provided, then determine the appropriate
# defaults.
- if credentials is None:
- credentials, _ = auth.default(scopes=self.AUTH_SCOPES)
+ if credentials and credentials_file:
+ raise exceptions.DuplicateCredentialArgs(
+ "'credentials_file' and 'credentials' are mutually exclusive"
+ )
+
+ if credentials_file is not None:
+ credentials, _ = auth.load_credentials_from_file(
+ credentials_file, scopes=scopes, quota_project_id=quota_project_id
+ )
+
+ elif credentials is None:
+ credentials, _ = auth.default(
+ scopes=scopes, quota_project_id=quota_project_id
+ )
# Save the credentials.
self._credentials = credentials
+ # Lifted into its own function so it can be stubbed out during tests.
+ self._prep_wrapped_messages(client_info)
+
+ def _prep_wrapped_messages(self, client_info):
+ # Precompute the wrapped methods.
+ self._wrapped_methods = {
+ self.get_billing_account: gapic_v1.method.wrap_method(
+ self.get_billing_account, default_timeout=None, client_info=client_info,
+ ),
+ self.list_billing_accounts: gapic_v1.method.wrap_method(
+ self.list_billing_accounts,
+ default_timeout=None,
+ client_info=client_info,
+ ),
+ self.update_billing_account: gapic_v1.method.wrap_method(
+ self.update_billing_account,
+ default_timeout=None,
+ client_info=client_info,
+ ),
+ self.create_billing_account: gapic_v1.method.wrap_method(
+ self.create_billing_account,
+ default_timeout=None,
+ client_info=client_info,
+ ),
+ self.list_project_billing_info: gapic_v1.method.wrap_method(
+ self.list_project_billing_info,
+ default_timeout=None,
+ client_info=client_info,
+ ),
+ self.get_project_billing_info: gapic_v1.method.wrap_method(
+ self.get_project_billing_info,
+ default_timeout=None,
+ client_info=client_info,
+ ),
+ self.update_project_billing_info: gapic_v1.method.wrap_method(
+ self.update_project_billing_info,
+ default_timeout=None,
+ client_info=client_info,
+ ),
+ self.get_iam_policy: gapic_v1.method.wrap_method(
+ self.get_iam_policy, default_timeout=None, client_info=client_info,
+ ),
+ self.set_iam_policy: gapic_v1.method.wrap_method(
+ self.set_iam_policy, default_timeout=None, client_info=client_info,
+ ),
+ self.test_iam_permissions: gapic_v1.method.wrap_method(
+ self.test_iam_permissions,
+ default_timeout=None,
+ client_info=client_info,
+ ),
+ }
+
@property
def get_billing_account(
- self
+ self,
) -> typing.Callable[
- [cloud_billing.GetBillingAccountRequest], cloud_billing.BillingAccount
+ [cloud_billing.GetBillingAccountRequest],
+ typing.Union[
+ cloud_billing.BillingAccount, typing.Awaitable[cloud_billing.BillingAccount]
+ ],
]:
- raise NotImplementedError
+ raise NotImplementedError()
@property
def list_billing_accounts(
- self
+ self,
) -> typing.Callable[
[cloud_billing.ListBillingAccountsRequest],
- cloud_billing.ListBillingAccountsResponse,
+ typing.Union[
+ cloud_billing.ListBillingAccountsResponse,
+ typing.Awaitable[cloud_billing.ListBillingAccountsResponse],
+ ],
]:
- raise NotImplementedError
+ raise NotImplementedError()
@property
def update_billing_account(
- self
+ self,
) -> typing.Callable[
- [cloud_billing.UpdateBillingAccountRequest], cloud_billing.BillingAccount
+ [cloud_billing.UpdateBillingAccountRequest],
+ typing.Union[
+ cloud_billing.BillingAccount, typing.Awaitable[cloud_billing.BillingAccount]
+ ],
]:
- raise NotImplementedError
+ raise NotImplementedError()
@property
def create_billing_account(
- self
+ self,
) -> typing.Callable[
- [cloud_billing.CreateBillingAccountRequest], cloud_billing.BillingAccount
+ [cloud_billing.CreateBillingAccountRequest],
+ typing.Union[
+ cloud_billing.BillingAccount, typing.Awaitable[cloud_billing.BillingAccount]
+ ],
]:
- raise NotImplementedError
+ raise NotImplementedError()
@property
def list_project_billing_info(
- self
+ self,
) -> typing.Callable[
[cloud_billing.ListProjectBillingInfoRequest],
- cloud_billing.ListProjectBillingInfoResponse,
+ typing.Union[
+ cloud_billing.ListProjectBillingInfoResponse,
+ typing.Awaitable[cloud_billing.ListProjectBillingInfoResponse],
+ ],
]:
- raise NotImplementedError
+ raise NotImplementedError()
@property
def get_project_billing_info(
- self
+ self,
) -> typing.Callable[
- [cloud_billing.GetProjectBillingInfoRequest], cloud_billing.ProjectBillingInfo
+ [cloud_billing.GetProjectBillingInfoRequest],
+ typing.Union[
+ cloud_billing.ProjectBillingInfo,
+ typing.Awaitable[cloud_billing.ProjectBillingInfo],
+ ],
]:
- raise NotImplementedError
+ raise NotImplementedError()
@property
def update_project_billing_info(
- self
+ self,
) -> typing.Callable[
[cloud_billing.UpdateProjectBillingInfoRequest],
- cloud_billing.ProjectBillingInfo,
+ typing.Union[
+ cloud_billing.ProjectBillingInfo,
+ typing.Awaitable[cloud_billing.ProjectBillingInfo],
+ ],
]:
- raise NotImplementedError
+ raise NotImplementedError()
@property
def get_iam_policy(
- self
- ) -> typing.Callable[[iam_policy.GetIamPolicyRequest], policy.Policy]:
- raise NotImplementedError
+ self,
+ ) -> typing.Callable[
+ [iam_policy.GetIamPolicyRequest],
+ typing.Union[policy.Policy, typing.Awaitable[policy.Policy]],
+ ]:
+ raise NotImplementedError()
@property
def set_iam_policy(
- self
- ) -> typing.Callable[[iam_policy.SetIamPolicyRequest], policy.Policy]:
- raise NotImplementedError
+ self,
+ ) -> typing.Callable[
+ [iam_policy.SetIamPolicyRequest],
+ typing.Union[policy.Policy, typing.Awaitable[policy.Policy]],
+ ]:
+ raise NotImplementedError()
@property
def test_iam_permissions(
- self
+ self,
) -> typing.Callable[
- [iam_policy.TestIamPermissionsRequest], iam_policy.TestIamPermissionsResponse
+ [iam_policy.TestIamPermissionsRequest],
+ typing.Union[
+ iam_policy.TestIamPermissionsResponse,
+ typing.Awaitable[iam_policy.TestIamPermissionsResponse],
+ ],
]:
- raise NotImplementedError
+ raise NotImplementedError()
__all__ = ("CloudBillingTransport",)
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/transports/grpc.py b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/transports/grpc.py
index 0edc1bf4097d..44511c8fe673 100644
--- a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/transports/grpc.py
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/transports/grpc.py
@@ -15,20 +15,22 @@
# limitations under the License.
#
-from typing import Callable, Dict, Tuple
+import warnings
+from typing import Callable, Dict, Optional, Sequence, Tuple
from google.api_core import grpc_helpers # type: ignore
+from google.api_core import gapic_v1 # type: ignore
+from google import auth # type: ignore
from google.auth import credentials # type: ignore
from google.auth.transport.grpc import SslCredentials # type: ignore
-
import grpc # type: ignore
from google.cloud.billing_v1.types import cloud_billing
from google.iam.v1 import iam_policy_pb2 as iam_policy # type: ignore
from google.iam.v1 import policy_pb2 as policy # type: ignore
-from .base import CloudBillingTransport
+from .base import CloudBillingTransport, DEFAULT_CLIENT_INFO
class CloudBillingGrpcTransport(CloudBillingTransport):
@@ -45,14 +47,21 @@ class CloudBillingGrpcTransport(CloudBillingTransport):
top of HTTP/2); the ``grpcio`` package must be installed.
"""
+ _stubs: Dict[str, Callable]
+
def __init__(
self,
*,
host: str = "cloudbilling.googleapis.com",
credentials: credentials.Credentials = None,
+ credentials_file: str = None,
+ scopes: Sequence[str] = None,
channel: grpc.Channel = None,
api_mtls_endpoint: str = None,
- client_cert_source: Callable[[], Tuple[bytes, bytes]] = None
+ client_cert_source: Callable[[], Tuple[bytes, bytes]] = None,
+ ssl_channel_credentials: grpc.ChannelCredentials = None,
+ quota_project_id: Optional[str] = None,
+ client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
) -> None:
"""Instantiate the transport.
@@ -64,21 +73,39 @@ def __init__(
are specified, the client will attempt to ascertain the
credentials from the environment.
This argument is ignored if ``channel`` is provided.
+ credentials_file (Optional[str]): A file with credentials that can
+ be loaded with :func:`google.auth.load_credentials_from_file`.
+ This argument is ignored if ``channel`` is provided.
+ scopes (Optional(Sequence[str])): A list of scopes. This argument is
+ ignored if ``channel`` is provided.
channel (Optional[grpc.Channel]): A ``Channel`` instance through
which to make calls.
- api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If
- provided, it overrides the ``host`` argument and tries to create
+ api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint.
+ If provided, it overrides the ``host`` argument and tries to create
a mutual TLS channel with client SSL credentials from
``client_cert_source`` or applicatin default SSL credentials.
- client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A
- callback to provide client SSL certificate bytes and private key
- bytes, both in PEM format. It is ignored if ``api_mtls_endpoint``
- is None.
+ client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]):
+ Deprecated. A callback to provide client SSL certificate bytes and
+ private key bytes, both in PEM format. It is ignored if
+ ``api_mtls_endpoint`` is None.
+ ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials
+ for grpc channel. It is ignored if ``channel`` is provided.
+ quota_project_id (Optional[str]): An optional project to use for billing
+ and quota.
+ client_info (google.api_core.gapic_v1.client_info.ClientInfo):
+ The client info used to send a user-agent string along with
+ API requests. If ``None``, then default info will be used.
+ Generally, you only need to set this if you're developing
+ your own client library.
Raises:
- google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
+ google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport
creation failed for any reason.
+ google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials``
+ and ``credentials_file`` are passed.
"""
+ self._ssl_channel_credentials = ssl_channel_credentials
+
if channel:
# Sanity check: Ensure that channel and credentials are not both
# provided.
@@ -86,13 +113,24 @@ def __init__(
# If a channel was explicitly provided, set it.
self._grpc_channel = channel
+ self._ssl_channel_credentials = None
elif api_mtls_endpoint:
+ warnings.warn(
+ "api_mtls_endpoint and client_cert_source are deprecated",
+ DeprecationWarning,
+ )
+
host = (
api_mtls_endpoint
if ":" in api_mtls_endpoint
else api_mtls_endpoint + ":443"
)
+ if credentials is None:
+ credentials, _ = auth.default(
+ scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id
+ )
+
# Create SSL credentials with client_cert_source or application
# default SSL credentials.
if client_cert_source:
@@ -104,61 +142,99 @@ def __init__(
ssl_credentials = SslCredentials().ssl_credentials
# create a new channel. The provided one is ignored.
- self._grpc_channel = grpc_helpers.create_channel(
+ self._grpc_channel = type(self).create_channel(
host,
credentials=credentials,
+ credentials_file=credentials_file,
ssl_credentials=ssl_credentials,
- scopes=self.AUTH_SCOPES,
+ scopes=scopes or self.AUTH_SCOPES,
+ quota_project_id=quota_project_id,
+ )
+ self._ssl_channel_credentials = ssl_credentials
+ else:
+ host = host if ":" in host else host + ":443"
+
+ if credentials is None:
+ credentials, _ = auth.default(
+ scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id
+ )
+
+ # create a new channel. The provided one is ignored.
+ self._grpc_channel = type(self).create_channel(
+ host,
+ credentials=credentials,
+ credentials_file=credentials_file,
+ ssl_credentials=ssl_channel_credentials,
+ scopes=scopes or self.AUTH_SCOPES,
+ quota_project_id=quota_project_id,
)
- # Run the base constructor.
- super().__init__(host=host, credentials=credentials)
self._stubs = {} # type: Dict[str, Callable]
+ # Run the base constructor.
+ super().__init__(
+ host=host,
+ credentials=credentials,
+ credentials_file=credentials_file,
+ scopes=scopes or self.AUTH_SCOPES,
+ quota_project_id=quota_project_id,
+ client_info=client_info,
+ )
+
@classmethod
def create_channel(
cls,
host: str = "cloudbilling.googleapis.com",
credentials: credentials.Credentials = None,
- **kwargs
+ credentials_file: str = None,
+ scopes: Optional[Sequence[str]] = None,
+ quota_project_id: Optional[str] = None,
+ **kwargs,
) -> grpc.Channel:
"""Create and return a gRPC channel object.
Args:
- address (Optionsl[str]): The host for the channel to use.
+ address (Optional[str]): The host for the channel to use.
credentials (Optional[~.Credentials]): The
authorization credentials to attach to requests. These
credentials identify this application to the service. If
none are specified, the client will attempt to ascertain
the credentials from the environment.
+ credentials_file (Optional[str]): A file with credentials that can
+ be loaded with :func:`google.auth.load_credentials_from_file`.
+ This argument is mutually exclusive with credentials.
+ scopes (Optional[Sequence[str]]): A optional list of scopes needed for this
+ service. These are only used when credentials are not specified and
+ are passed to :func:`google.auth.default`.
+ quota_project_id (Optional[str]): An optional project to use for billing
+ and quota.
kwargs (Optional[dict]): Keyword arguments, which are passed to the
channel creation.
Returns:
grpc.Channel: A gRPC channel object.
+
+ Raises:
+ google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials``
+ and ``credentials_file`` are passed.
"""
+ scopes = scopes or cls.AUTH_SCOPES
return grpc_helpers.create_channel(
- host, credentials=credentials, scopes=cls.AUTH_SCOPES, **kwargs
+ host,
+ credentials=credentials,
+ credentials_file=credentials_file,
+ scopes=scopes,
+ quota_project_id=quota_project_id,
+ **kwargs,
)
@property
def grpc_channel(self) -> grpc.Channel:
- """Create the channel designed to connect to this service.
-
- This property caches on the instance; repeated calls return
- the same channel.
+ """Return the channel designed to connect to this service.
"""
- # Sanity check: Only create a new channel if we do not already
- # have one.
- if not hasattr(self, "_grpc_channel"):
- self._grpc_channel = self.create_channel(
- self._host, credentials=self._credentials
- )
-
- # Return the channel from cache.
return self._grpc_channel
@property
def get_billing_account(
- self
+ self,
) -> Callable[
[cloud_billing.GetBillingAccountRequest], cloud_billing.BillingAccount
]:
@@ -188,7 +264,7 @@ def get_billing_account(
@property
def list_billing_accounts(
- self
+ self,
) -> Callable[
[cloud_billing.ListBillingAccountsRequest],
cloud_billing.ListBillingAccountsResponse,
@@ -219,7 +295,7 @@ def list_billing_accounts(
@property
def update_billing_account(
- self
+ self,
) -> Callable[
[cloud_billing.UpdateBillingAccountRequest], cloud_billing.BillingAccount
]:
@@ -252,7 +328,7 @@ def update_billing_account(
@property
def create_billing_account(
- self
+ self,
) -> Callable[
[cloud_billing.CreateBillingAccountRequest], cloud_billing.BillingAccount
]:
@@ -289,7 +365,7 @@ def create_billing_account(
@property
def list_project_billing_info(
- self
+ self,
) -> Callable[
[cloud_billing.ListProjectBillingInfoRequest],
cloud_billing.ListProjectBillingInfoResponse,
@@ -322,7 +398,7 @@ def list_project_billing_info(
@property
def get_project_billing_info(
- self
+ self,
) -> Callable[
[cloud_billing.GetProjectBillingInfoRequest], cloud_billing.ProjectBillingInfo
]:
@@ -352,7 +428,7 @@ def get_project_billing_info(
@property
def update_project_billing_info(
- self
+ self,
) -> Callable[
[cloud_billing.UpdateProjectBillingInfoRequest],
cloud_billing.ProjectBillingInfo,
@@ -416,7 +492,7 @@ def update_project_billing_info(
@property
def get_iam_policy(
- self
+ self,
) -> Callable[[iam_policy.GetIamPolicyRequest], policy.Policy]:
r"""Return a callable for the get iam policy method over gRPC.
@@ -445,7 +521,7 @@ def get_iam_policy(
@property
def set_iam_policy(
- self
+ self,
) -> Callable[[iam_policy.SetIamPolicyRequest], policy.Policy]:
r"""Return a callable for the set iam policy method over gRPC.
@@ -475,7 +551,7 @@ def set_iam_policy(
@property
def test_iam_permissions(
- self
+ self,
) -> Callable[
[iam_policy.TestIamPermissionsRequest], iam_policy.TestIamPermissionsResponse
]:
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/transports/grpc_asyncio.py b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/transports/grpc_asyncio.py
new file mode 100644
index 000000000000..d4e337ccfeb5
--- /dev/null
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_billing/transports/grpc_asyncio.py
@@ -0,0 +1,594 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import warnings
+from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple
+
+from google.api_core import gapic_v1 # type: ignore
+from google.api_core import grpc_helpers_async # type: ignore
+from google import auth # type: ignore
+from google.auth import credentials # type: ignore
+from google.auth.transport.grpc import SslCredentials # type: ignore
+
+import grpc # type: ignore
+from grpc.experimental import aio # type: ignore
+
+from google.cloud.billing_v1.types import cloud_billing
+from google.iam.v1 import iam_policy_pb2 as iam_policy # type: ignore
+from google.iam.v1 import policy_pb2 as policy # type: ignore
+
+from .base import CloudBillingTransport, DEFAULT_CLIENT_INFO
+from .grpc import CloudBillingGrpcTransport
+
+
+class CloudBillingGrpcAsyncIOTransport(CloudBillingTransport):
+ """gRPC AsyncIO backend transport for CloudBilling.
+
+ Retrieves GCP Console billing accounts and associates them
+ with projects.
+
+ This class defines the same methods as the primary client, so the
+ primary client can load the underlying transport implementation
+ and call it.
+
+ It sends protocol buffers over the wire using gRPC (which is built on
+ top of HTTP/2); the ``grpcio`` package must be installed.
+ """
+
+ _grpc_channel: aio.Channel
+ _stubs: Dict[str, Callable] = {}
+
+ @classmethod
+ def create_channel(
+ cls,
+ host: str = "cloudbilling.googleapis.com",
+ credentials: credentials.Credentials = None,
+ credentials_file: Optional[str] = None,
+ scopes: Optional[Sequence[str]] = None,
+ quota_project_id: Optional[str] = None,
+ **kwargs,
+ ) -> aio.Channel:
+ """Create and return a gRPC AsyncIO channel object.
+ Args:
+ address (Optional[str]): The host for the channel to use.
+ credentials (Optional[~.Credentials]): The
+ authorization credentials to attach to requests. These
+ credentials identify this application to the service. If
+ none are specified, the client will attempt to ascertain
+ the credentials from the environment.
+ credentials_file (Optional[str]): A file with credentials that can
+ be loaded with :func:`google.auth.load_credentials_from_file`.
+ This argument is ignored if ``channel`` is provided.
+ scopes (Optional[Sequence[str]]): A optional list of scopes needed for this
+ service. These are only used when credentials are not specified and
+ are passed to :func:`google.auth.default`.
+ quota_project_id (Optional[str]): An optional project to use for billing
+ and quota.
+ kwargs (Optional[dict]): Keyword arguments, which are passed to the
+ channel creation.
+ Returns:
+ aio.Channel: A gRPC AsyncIO channel object.
+ """
+ scopes = scopes or cls.AUTH_SCOPES
+ return grpc_helpers_async.create_channel(
+ host,
+ credentials=credentials,
+ credentials_file=credentials_file,
+ scopes=scopes,
+ quota_project_id=quota_project_id,
+ **kwargs,
+ )
+
+ def __init__(
+ self,
+ *,
+ host: str = "cloudbilling.googleapis.com",
+ credentials: credentials.Credentials = None,
+ credentials_file: Optional[str] = None,
+ scopes: Optional[Sequence[str]] = None,
+ channel: aio.Channel = None,
+ api_mtls_endpoint: str = None,
+ client_cert_source: Callable[[], Tuple[bytes, bytes]] = None,
+ ssl_channel_credentials: grpc.ChannelCredentials = None,
+ quota_project_id=None,
+ client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
+ ) -> None:
+ """Instantiate the transport.
+
+ Args:
+ host (Optional[str]): The hostname to connect to.
+ credentials (Optional[google.auth.credentials.Credentials]): The
+ authorization credentials to attach to requests. These
+ credentials identify the application to the service; if none
+ are specified, the client will attempt to ascertain the
+ credentials from the environment.
+ This argument is ignored if ``channel`` is provided.
+ credentials_file (Optional[str]): A file with credentials that can
+ be loaded with :func:`google.auth.load_credentials_from_file`.
+ This argument is ignored if ``channel`` is provided.
+ scopes (Optional[Sequence[str]]): A optional list of scopes needed for this
+ service. These are only used when credentials are not specified and
+ are passed to :func:`google.auth.default`.
+ channel (Optional[aio.Channel]): A ``Channel`` instance through
+ which to make calls.
+ api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint.
+ If provided, it overrides the ``host`` argument and tries to create
+ a mutual TLS channel with client SSL credentials from
+ ``client_cert_source`` or applicatin default SSL credentials.
+ client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]):
+ Deprecated. A callback to provide client SSL certificate bytes and
+ private key bytes, both in PEM format. It is ignored if
+ ``api_mtls_endpoint`` is None.
+ ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials
+ for grpc channel. It is ignored if ``channel`` is provided.
+ quota_project_id (Optional[str]): An optional project to use for billing
+ and quota.
+ client_info (google.api_core.gapic_v1.client_info.ClientInfo):
+ The client info used to send a user-agent string along with
+ API requests. If ``None``, then default info will be used.
+ Generally, you only need to set this if you're developing
+ your own client library.
+
+ Raises:
+ google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
+ creation failed for any reason.
+ google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials``
+ and ``credentials_file`` are passed.
+ """
+ self._ssl_channel_credentials = ssl_channel_credentials
+
+ if channel:
+ # Sanity check: Ensure that channel and credentials are not both
+ # provided.
+ credentials = False
+
+ # If a channel was explicitly provided, set it.
+ self._grpc_channel = channel
+ self._ssl_channel_credentials = None
+ elif api_mtls_endpoint:
+ warnings.warn(
+ "api_mtls_endpoint and client_cert_source are deprecated",
+ DeprecationWarning,
+ )
+
+ host = (
+ api_mtls_endpoint
+ if ":" in api_mtls_endpoint
+ else api_mtls_endpoint + ":443"
+ )
+
+ if credentials is None:
+ credentials, _ = auth.default(
+ scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id
+ )
+
+ # Create SSL credentials with client_cert_source or application
+ # default SSL credentials.
+ if client_cert_source:
+ cert, key = client_cert_source()
+ ssl_credentials = grpc.ssl_channel_credentials(
+ certificate_chain=cert, private_key=key
+ )
+ else:
+ ssl_credentials = SslCredentials().ssl_credentials
+
+ # create a new channel. The provided one is ignored.
+ self._grpc_channel = type(self).create_channel(
+ host,
+ credentials=credentials,
+ credentials_file=credentials_file,
+ ssl_credentials=ssl_credentials,
+ scopes=scopes or self.AUTH_SCOPES,
+ quota_project_id=quota_project_id,
+ )
+ self._ssl_channel_credentials = ssl_credentials
+ else:
+ host = host if ":" in host else host + ":443"
+
+ if credentials is None:
+ credentials, _ = auth.default(
+ scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id
+ )
+
+ # create a new channel. The provided one is ignored.
+ self._grpc_channel = type(self).create_channel(
+ host,
+ credentials=credentials,
+ credentials_file=credentials_file,
+ ssl_credentials=ssl_channel_credentials,
+ scopes=scopes or self.AUTH_SCOPES,
+ quota_project_id=quota_project_id,
+ )
+
+ # Run the base constructor.
+ super().__init__(
+ host=host,
+ credentials=credentials,
+ credentials_file=credentials_file,
+ scopes=scopes or self.AUTH_SCOPES,
+ quota_project_id=quota_project_id,
+ client_info=client_info,
+ )
+
+ self._stubs = {}
+
+ @property
+ def grpc_channel(self) -> aio.Channel:
+ """Create the channel designed to connect to this service.
+
+ This property caches on the instance; repeated calls return
+ the same channel.
+ """
+ # Return the channel from cache.
+ return self._grpc_channel
+
+ @property
+ def get_billing_account(
+ self,
+ ) -> Callable[
+ [cloud_billing.GetBillingAccountRequest],
+ Awaitable[cloud_billing.BillingAccount],
+ ]:
+ r"""Return a callable for the get billing account method over gRPC.
+
+ Gets information about a billing account. The current
+ authenticated user must be a `viewer of the billing
+ account `__.
+
+ Returns:
+ Callable[[~.GetBillingAccountRequest],
+ Awaitable[~.BillingAccount]]:
+ A function that, when called, will call the underlying RPC
+ on the server.
+ """
+ # Generate a "stub function" on-the-fly which will actually make
+ # the request.
+ # gRPC handles serialization and deserialization, so we just need
+ # to pass in the functions for each.
+ if "get_billing_account" not in self._stubs:
+ self._stubs["get_billing_account"] = self.grpc_channel.unary_unary(
+ "/google.cloud.billing.v1.CloudBilling/GetBillingAccount",
+ request_serializer=cloud_billing.GetBillingAccountRequest.serialize,
+ response_deserializer=cloud_billing.BillingAccount.deserialize,
+ )
+ return self._stubs["get_billing_account"]
+
+ @property
+ def list_billing_accounts(
+ self,
+ ) -> Callable[
+ [cloud_billing.ListBillingAccountsRequest],
+ Awaitable[cloud_billing.ListBillingAccountsResponse],
+ ]:
+ r"""Return a callable for the list billing accounts method over gRPC.
+
+ Lists the billing accounts that the current authenticated user
+ has permission to
+ `view `__.
+
+ Returns:
+ Callable[[~.ListBillingAccountsRequest],
+ Awaitable[~.ListBillingAccountsResponse]]:
+ A function that, when called, will call the underlying RPC
+ on the server.
+ """
+ # Generate a "stub function" on-the-fly which will actually make
+ # the request.
+ # gRPC handles serialization and deserialization, so we just need
+ # to pass in the functions for each.
+ if "list_billing_accounts" not in self._stubs:
+ self._stubs["list_billing_accounts"] = self.grpc_channel.unary_unary(
+ "/google.cloud.billing.v1.CloudBilling/ListBillingAccounts",
+ request_serializer=cloud_billing.ListBillingAccountsRequest.serialize,
+ response_deserializer=cloud_billing.ListBillingAccountsResponse.deserialize,
+ )
+ return self._stubs["list_billing_accounts"]
+
+ @property
+ def update_billing_account(
+ self,
+ ) -> Callable[
+ [cloud_billing.UpdateBillingAccountRequest],
+ Awaitable[cloud_billing.BillingAccount],
+ ]:
+ r"""Return a callable for the update billing account method over gRPC.
+
+ Updates a billing account's fields. Currently the only field
+ that can be edited is ``display_name``. The current
+ authenticated user must have the ``billing.accounts.update`` IAM
+ permission, which is typically given to the
+ `administrator `__
+ of the billing account.
+
+ Returns:
+ Callable[[~.UpdateBillingAccountRequest],
+ Awaitable[~.BillingAccount]]:
+ A function that, when called, will call the underlying RPC
+ on the server.
+ """
+ # Generate a "stub function" on-the-fly which will actually make
+ # the request.
+ # gRPC handles serialization and deserialization, so we just need
+ # to pass in the functions for each.
+ if "update_billing_account" not in self._stubs:
+ self._stubs["update_billing_account"] = self.grpc_channel.unary_unary(
+ "/google.cloud.billing.v1.CloudBilling/UpdateBillingAccount",
+ request_serializer=cloud_billing.UpdateBillingAccountRequest.serialize,
+ response_deserializer=cloud_billing.BillingAccount.deserialize,
+ )
+ return self._stubs["update_billing_account"]
+
+ @property
+ def create_billing_account(
+ self,
+ ) -> Callable[
+ [cloud_billing.CreateBillingAccountRequest],
+ Awaitable[cloud_billing.BillingAccount],
+ ]:
+ r"""Return a callable for the create billing account method over gRPC.
+
+ Creates a billing account. This method can only be used to
+ create `billing
+ subaccounts `__
+ by GCP resellers. When creating a subaccount, the current
+ authenticated user must have the ``billing.accounts.update`` IAM
+ permission on the master account, which is typically given to
+ billing account
+ `administrators `__.
+ This method will return an error if the master account has not
+ been provisioned as a reseller account.
+
+ Returns:
+ Callable[[~.CreateBillingAccountRequest],
+ Awaitable[~.BillingAccount]]:
+ A function that, when called, will call the underlying RPC
+ on the server.
+ """
+ # Generate a "stub function" on-the-fly which will actually make
+ # the request.
+ # gRPC handles serialization and deserialization, so we just need
+ # to pass in the functions for each.
+ if "create_billing_account" not in self._stubs:
+ self._stubs["create_billing_account"] = self.grpc_channel.unary_unary(
+ "/google.cloud.billing.v1.CloudBilling/CreateBillingAccount",
+ request_serializer=cloud_billing.CreateBillingAccountRequest.serialize,
+ response_deserializer=cloud_billing.BillingAccount.deserialize,
+ )
+ return self._stubs["create_billing_account"]
+
+ @property
+ def list_project_billing_info(
+ self,
+ ) -> Callable[
+ [cloud_billing.ListProjectBillingInfoRequest],
+ Awaitable[cloud_billing.ListProjectBillingInfoResponse],
+ ]:
+ r"""Return a callable for the list project billing info method over gRPC.
+
+ Lists the projects associated with a billing account. The
+ current authenticated user must have the
+ ``billing.resourceAssociations.list`` IAM permission, which is
+ often given to billing account
+ `viewers `__.
+
+ Returns:
+ Callable[[~.ListProjectBillingInfoRequest],
+ Awaitable[~.ListProjectBillingInfoResponse]]:
+ A function that, when called, will call the underlying RPC
+ on the server.
+ """
+ # Generate a "stub function" on-the-fly which will actually make
+ # the request.
+ # gRPC handles serialization and deserialization, so we just need
+ # to pass in the functions for each.
+ if "list_project_billing_info" not in self._stubs:
+ self._stubs["list_project_billing_info"] = self.grpc_channel.unary_unary(
+ "/google.cloud.billing.v1.CloudBilling/ListProjectBillingInfo",
+ request_serializer=cloud_billing.ListProjectBillingInfoRequest.serialize,
+ response_deserializer=cloud_billing.ListProjectBillingInfoResponse.deserialize,
+ )
+ return self._stubs["list_project_billing_info"]
+
+ @property
+ def get_project_billing_info(
+ self,
+ ) -> Callable[
+ [cloud_billing.GetProjectBillingInfoRequest],
+ Awaitable[cloud_billing.ProjectBillingInfo],
+ ]:
+ r"""Return a callable for the get project billing info method over gRPC.
+
+ Gets the billing information for a project. The current
+ authenticated user must have `permission to view the
+ project `__.
+
+ Returns:
+ Callable[[~.GetProjectBillingInfoRequest],
+ Awaitable[~.ProjectBillingInfo]]:
+ A function that, when called, will call the underlying RPC
+ on the server.
+ """
+ # Generate a "stub function" on-the-fly which will actually make
+ # the request.
+ # gRPC handles serialization and deserialization, so we just need
+ # to pass in the functions for each.
+ if "get_project_billing_info" not in self._stubs:
+ self._stubs["get_project_billing_info"] = self.grpc_channel.unary_unary(
+ "/google.cloud.billing.v1.CloudBilling/GetProjectBillingInfo",
+ request_serializer=cloud_billing.GetProjectBillingInfoRequest.serialize,
+ response_deserializer=cloud_billing.ProjectBillingInfo.deserialize,
+ )
+ return self._stubs["get_project_billing_info"]
+
+ @property
+ def update_project_billing_info(
+ self,
+ ) -> Callable[
+ [cloud_billing.UpdateProjectBillingInfoRequest],
+ Awaitable[cloud_billing.ProjectBillingInfo],
+ ]:
+ r"""Return a callable for the update project billing info method over gRPC.
+
+ Sets or updates the billing account associated with a project.
+ You specify the new billing account by setting the
+ ``billing_account_name`` in the ``ProjectBillingInfo`` resource
+ to the resource name of a billing account. Associating a project
+ with an open billing account enables billing on the project and
+ allows charges for resource usage. If the project already had a
+ billing account, this method changes the billing account used
+ for resource usage charges.
+
+ *Note:* Incurred charges that have not yet been reported in the
+ transaction history of the GCP Console might be billed to the
+ new billing account, even if the charge occurred before the new
+ billing account was assigned to the project.
+
+ The current authenticated user must have ownership privileges
+ for both the
+ `project `__
+ and the `billing
+ account `__.
+
+ You can disable billing on the project by setting the
+ ``billing_account_name`` field to empty. This action
+ disassociates the current billing account from the project. Any
+ billable activity of your in-use services will stop, and your
+ application could stop functioning as expected. Any unbilled
+ charges to date will be billed to the previously associated
+ account. The current authenticated user must be either an owner
+ of the project or an owner of the billing account for the
+ project.
+
+ Note that associating a project with a *closed* billing account
+ will have much the same effect as disabling billing on the
+ project: any paid resources used by the project will be shut
+ down. Thus, unless you wish to disable billing, you should
+ always call this method with the name of an *open* billing
+ account.
+
+ Returns:
+ Callable[[~.UpdateProjectBillingInfoRequest],
+ Awaitable[~.ProjectBillingInfo]]:
+ A function that, when called, will call the underlying RPC
+ on the server.
+ """
+ # Generate a "stub function" on-the-fly which will actually make
+ # the request.
+ # gRPC handles serialization and deserialization, so we just need
+ # to pass in the functions for each.
+ if "update_project_billing_info" not in self._stubs:
+ self._stubs["update_project_billing_info"] = self.grpc_channel.unary_unary(
+ "/google.cloud.billing.v1.CloudBilling/UpdateProjectBillingInfo",
+ request_serializer=cloud_billing.UpdateProjectBillingInfoRequest.serialize,
+ response_deserializer=cloud_billing.ProjectBillingInfo.deserialize,
+ )
+ return self._stubs["update_project_billing_info"]
+
+ @property
+ def get_iam_policy(
+ self,
+ ) -> Callable[[iam_policy.GetIamPolicyRequest], Awaitable[policy.Policy]]:
+ r"""Return a callable for the get iam policy method over gRPC.
+
+ Gets the access control policy for a billing account. The caller
+ must have the ``billing.accounts.getIamPolicy`` permission on
+ the account, which is often given to billing account
+ `viewers `__.
+
+ Returns:
+ Callable[[~.GetIamPolicyRequest],
+ Awaitable[~.Policy]]:
+ A function that, when called, will call the underlying RPC
+ on the server.
+ """
+ # Generate a "stub function" on-the-fly which will actually make
+ # the request.
+ # gRPC handles serialization and deserialization, so we just need
+ # to pass in the functions for each.
+ if "get_iam_policy" not in self._stubs:
+ self._stubs["get_iam_policy"] = self.grpc_channel.unary_unary(
+ "/google.cloud.billing.v1.CloudBilling/GetIamPolicy",
+ request_serializer=iam_policy.GetIamPolicyRequest.SerializeToString,
+ response_deserializer=policy.Policy.FromString,
+ )
+ return self._stubs["get_iam_policy"]
+
+ @property
+ def set_iam_policy(
+ self,
+ ) -> Callable[[iam_policy.SetIamPolicyRequest], Awaitable[policy.Policy]]:
+ r"""Return a callable for the set iam policy method over gRPC.
+
+ Sets the access control policy for a billing account. Replaces
+ any existing policy. The caller must have the
+ ``billing.accounts.setIamPolicy`` permission on the account,
+ which is often given to billing account
+ `administrators `__.
+
+ Returns:
+ Callable[[~.SetIamPolicyRequest],
+ Awaitable[~.Policy]]:
+ A function that, when called, will call the underlying RPC
+ on the server.
+ """
+ # Generate a "stub function" on-the-fly which will actually make
+ # the request.
+ # gRPC handles serialization and deserialization, so we just need
+ # to pass in the functions for each.
+ if "set_iam_policy" not in self._stubs:
+ self._stubs["set_iam_policy"] = self.grpc_channel.unary_unary(
+ "/google.cloud.billing.v1.CloudBilling/SetIamPolicy",
+ request_serializer=iam_policy.SetIamPolicyRequest.SerializeToString,
+ response_deserializer=policy.Policy.FromString,
+ )
+ return self._stubs["set_iam_policy"]
+
+ @property
+ def test_iam_permissions(
+ self,
+ ) -> Callable[
+ [iam_policy.TestIamPermissionsRequest],
+ Awaitable[iam_policy.TestIamPermissionsResponse],
+ ]:
+ r"""Return a callable for the test iam permissions method over gRPC.
+
+ Tests the access control policy for a billing
+ account. This method takes the resource and a set of
+ permissions as input and returns the subset of the input
+ permissions that the caller is allowed for that
+ resource.
+
+ Returns:
+ Callable[[~.TestIamPermissionsRequest],
+ Awaitable[~.TestIamPermissionsResponse]]:
+ A function that, when called, will call the underlying RPC
+ on the server.
+ """
+ # Generate a "stub function" on-the-fly which will actually make
+ # the request.
+ # gRPC handles serialization and deserialization, so we just need
+ # to pass in the functions for each.
+ if "test_iam_permissions" not in self._stubs:
+ self._stubs["test_iam_permissions"] = self.grpc_channel.unary_unary(
+ "/google.cloud.billing.v1.CloudBilling/TestIamPermissions",
+ request_serializer=iam_policy.TestIamPermissionsRequest.SerializeToString,
+ response_deserializer=iam_policy.TestIamPermissionsResponse.FromString,
+ )
+ return self._stubs["test_iam_permissions"]
+
+
+__all__ = ("CloudBillingGrpcAsyncIOTransport",)
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/__init__.py b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/__init__.py
index 2bce2655b279..cc54a8dfe4d6 100644
--- a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/__init__.py
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/__init__.py
@@ -16,5 +16,9 @@
#
from .client import CloudCatalogClient
+from .async_client import CloudCatalogAsyncClient
-__all__ = ("CloudCatalogClient",)
+__all__ = (
+ "CloudCatalogClient",
+ "CloudCatalogAsyncClient",
+)
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/async_client.py b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/async_client.py
new file mode 100644
index 000000000000..49b0d07eebdc
--- /dev/null
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/async_client.py
@@ -0,0 +1,285 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+from collections import OrderedDict
+import functools
+import re
+from typing import Dict, Sequence, Tuple, Type, Union
+import pkg_resources
+
+import google.api_core.client_options as ClientOptions # type: ignore
+from google.api_core import exceptions # type: ignore
+from google.api_core import gapic_v1 # type: ignore
+from google.api_core import retry as retries # type: ignore
+from google.auth import credentials # type: ignore
+from google.oauth2 import service_account # type: ignore
+
+from google.cloud.billing_v1.services.cloud_catalog import pagers
+from google.cloud.billing_v1.types import cloud_catalog
+
+from .transports.base import CloudCatalogTransport, DEFAULT_CLIENT_INFO
+from .transports.grpc_asyncio import CloudCatalogGrpcAsyncIOTransport
+from .client import CloudCatalogClient
+
+
+class CloudCatalogAsyncClient:
+ """A catalog of Google Cloud Platform services and SKUs.
+ Provides pricing information and metadata on Google Cloud
+ Platform services and SKUs.
+ """
+
+ _client: CloudCatalogClient
+
+ DEFAULT_ENDPOINT = CloudCatalogClient.DEFAULT_ENDPOINT
+ DEFAULT_MTLS_ENDPOINT = CloudCatalogClient.DEFAULT_MTLS_ENDPOINT
+
+ service_path = staticmethod(CloudCatalogClient.service_path)
+ parse_service_path = staticmethod(CloudCatalogClient.parse_service_path)
+ sku_path = staticmethod(CloudCatalogClient.sku_path)
+ parse_sku_path = staticmethod(CloudCatalogClient.parse_sku_path)
+
+ common_billing_account_path = staticmethod(
+ CloudCatalogClient.common_billing_account_path
+ )
+ parse_common_billing_account_path = staticmethod(
+ CloudCatalogClient.parse_common_billing_account_path
+ )
+
+ common_folder_path = staticmethod(CloudCatalogClient.common_folder_path)
+ parse_common_folder_path = staticmethod(CloudCatalogClient.parse_common_folder_path)
+
+ common_organization_path = staticmethod(CloudCatalogClient.common_organization_path)
+ parse_common_organization_path = staticmethod(
+ CloudCatalogClient.parse_common_organization_path
+ )
+
+ common_project_path = staticmethod(CloudCatalogClient.common_project_path)
+ parse_common_project_path = staticmethod(
+ CloudCatalogClient.parse_common_project_path
+ )
+
+ common_location_path = staticmethod(CloudCatalogClient.common_location_path)
+ parse_common_location_path = staticmethod(
+ CloudCatalogClient.parse_common_location_path
+ )
+
+ from_service_account_file = CloudCatalogClient.from_service_account_file
+ from_service_account_json = from_service_account_file
+
+ @property
+ def transport(self) -> CloudCatalogTransport:
+ """Return the transport used by the client instance.
+
+ Returns:
+ CloudCatalogTransport: The transport used by the client instance.
+ """
+ return self._client.transport
+
+ get_transport_class = functools.partial(
+ type(CloudCatalogClient).get_transport_class, type(CloudCatalogClient)
+ )
+
+ def __init__(
+ self,
+ *,
+ credentials: credentials.Credentials = None,
+ transport: Union[str, CloudCatalogTransport] = "grpc_asyncio",
+ client_options: ClientOptions = None,
+ client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
+ ) -> None:
+ """Instantiate the cloud catalog client.
+
+ Args:
+ credentials (Optional[google.auth.credentials.Credentials]): The
+ authorization credentials to attach to requests. These
+ credentials identify the application to the service; if none
+ are specified, the client will attempt to ascertain the
+ credentials from the environment.
+ transport (Union[str, ~.CloudCatalogTransport]): The
+ transport to use. If set to None, a transport is chosen
+ automatically.
+ client_options (ClientOptions): Custom options for the client. It
+ won't take effect if a ``transport`` instance is provided.
+ (1) The ``api_endpoint`` property can be used to override the
+ default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT
+ environment variable can also be used to override the endpoint:
+ "always" (always use the default mTLS endpoint), "never" (always
+ use the default regular endpoint) and "auto" (auto switch to the
+ default mTLS endpoint if client certificate is present, this is
+ the default value). However, the ``api_endpoint`` property takes
+ precedence if provided.
+ (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable
+ is "true", then the ``client_cert_source`` property can be used
+ to provide client certificate for mutual TLS transport. If
+ not provided, the default SSL client certificate will be used if
+ present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not
+ set, no client certificate will be used.
+
+ Raises:
+ google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
+ creation failed for any reason.
+ """
+
+ self._client = CloudCatalogClient(
+ credentials=credentials,
+ transport=transport,
+ client_options=client_options,
+ client_info=client_info,
+ )
+
+ async def list_services(
+ self,
+ request: cloud_catalog.ListServicesRequest = None,
+ *,
+ retry: retries.Retry = gapic_v1.method.DEFAULT,
+ timeout: float = None,
+ metadata: Sequence[Tuple[str, str]] = (),
+ ) -> pagers.ListServicesAsyncPager:
+ r"""Lists all public cloud services.
+
+ Args:
+ request (:class:`~.cloud_catalog.ListServicesRequest`):
+ The request object. Request message for `ListServices`.
+
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
+ should be retried.
+ timeout (float): The timeout for this request.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
+
+ Returns:
+ ~.pagers.ListServicesAsyncPager:
+ Response message for ``ListServices``.
+
+ Iterating over this object will yield results and
+ resolve additional pages automatically.
+
+ """
+ # Create or coerce a protobuf request object.
+
+ request = cloud_catalog.ListServicesRequest(request)
+
+ # Wrap the RPC method; this adds retry and timeout information,
+ # and friendly error handling.
+ rpc = gapic_v1.method_async.wrap_method(
+ self._client._transport.list_services,
+ default_timeout=None,
+ client_info=DEFAULT_CLIENT_INFO,
+ )
+
+ # Send the request.
+ response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
+
+ # This method is paged; wrap the response in a pager, which provides
+ # an `__aiter__` convenience method.
+ response = pagers.ListServicesAsyncPager(
+ method=rpc, request=request, response=response, metadata=metadata,
+ )
+
+ # Done; return the response.
+ return response
+
+ async def list_skus(
+ self,
+ request: cloud_catalog.ListSkusRequest = None,
+ *,
+ parent: str = None,
+ retry: retries.Retry = gapic_v1.method.DEFAULT,
+ timeout: float = None,
+ metadata: Sequence[Tuple[str, str]] = (),
+ ) -> pagers.ListSkusAsyncPager:
+ r"""Lists all publicly available SKUs for a given cloud
+ service.
+
+ Args:
+ request (:class:`~.cloud_catalog.ListSkusRequest`):
+ The request object. Request message for `ListSkus`.
+ parent (:class:`str`):
+ Required. The name of the service.
+ Example: "services/DA34-426B-A397".
+ This corresponds to the ``parent`` field
+ on the ``request`` instance; if ``request`` is provided, this
+ should not be set.
+
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
+ should be retried.
+ timeout (float): The timeout for this request.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
+
+ Returns:
+ ~.pagers.ListSkusAsyncPager:
+ Response message for ``ListSkus``.
+
+ Iterating over this object will yield results and
+ resolve additional pages automatically.
+
+ """
+ # Create or coerce a protobuf request object.
+ # Sanity check: If we got a request object, we should *not* have
+ # gotten any keyword arguments that map to the request.
+ has_flattened_params = any([parent])
+ if request is not None and has_flattened_params:
+ raise ValueError(
+ "If the `request` argument is set, then none of "
+ "the individual field arguments should be set."
+ )
+
+ request = cloud_catalog.ListSkusRequest(request)
+
+ # If we have keyword arguments corresponding to fields on the
+ # request, apply these.
+
+ if parent is not None:
+ request.parent = parent
+
+ # Wrap the RPC method; this adds retry and timeout information,
+ # and friendly error handling.
+ rpc = gapic_v1.method_async.wrap_method(
+ self._client._transport.list_skus,
+ default_timeout=None,
+ client_info=DEFAULT_CLIENT_INFO,
+ )
+
+ # Certain fields should be provided within the metadata header;
+ # add these here.
+ metadata = tuple(metadata) + (
+ gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)),
+ )
+
+ # Send the request.
+ response = await rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
+
+ # This method is paged; wrap the response in a pager, which provides
+ # an `__aiter__` convenience method.
+ response = pagers.ListSkusAsyncPager(
+ method=rpc, request=request, response=response, metadata=metadata,
+ )
+
+ # Done; return the response.
+ return response
+
+
+try:
+ DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
+ gapic_version=pkg_resources.get_distribution("google-cloud-billing",).version,
+ )
+except pkg_resources.DistributionNotFound:
+ DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo()
+
+
+__all__ = ("CloudCatalogAsyncClient",)
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/client.py b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/client.py
index 2af0753e285f..c6f2851755e9 100644
--- a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/client.py
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/client.py
@@ -16,22 +16,28 @@
#
from collections import OrderedDict
+from distutils import util
+import os
import re
-from typing import Callable, Dict, Sequence, Tuple, Type, Union
+from typing import Callable, Dict, Optional, Sequence, Tuple, Type, Union
import pkg_resources
-import google.api_core.client_options as ClientOptions # type: ignore
+from google.api_core import client_options as client_options_lib # type: ignore
from google.api_core import exceptions # type: ignore
from google.api_core import gapic_v1 # type: ignore
from google.api_core import retry as retries # type: ignore
from google.auth import credentials # type: ignore
+from google.auth.transport import mtls # type: ignore
+from google.auth.transport.grpc import SslCredentials # type: ignore
+from google.auth.exceptions import MutualTLSChannelError # type: ignore
from google.oauth2 import service_account # type: ignore
from google.cloud.billing_v1.services.cloud_catalog import pagers
from google.cloud.billing_v1.types import cloud_catalog
-from .transports.base import CloudCatalogTransport
+from .transports.base import CloudCatalogTransport, DEFAULT_CLIENT_INFO
from .transports.grpc import CloudCatalogGrpcTransport
+from .transports.grpc_asyncio import CloudCatalogGrpcAsyncIOTransport
class CloudCatalogClientMeta(type):
@@ -44,8 +50,9 @@ class CloudCatalogClientMeta(type):
_transport_registry = OrderedDict() # type: Dict[str, Type[CloudCatalogTransport]]
_transport_registry["grpc"] = CloudCatalogGrpcTransport
+ _transport_registry["grpc_asyncio"] = CloudCatalogGrpcAsyncIOTransport
- def get_transport_class(cls, label: str = None) -> Type[CloudCatalogTransport]:
+ def get_transport_class(cls, label: str = None,) -> Type[CloudCatalogTransport]:
"""Return an appropriate transport class.
Args:
@@ -124,12 +131,103 @@ def from_service_account_file(cls, filename: str, *args, **kwargs):
from_service_account_json = from_service_account_file
+ @property
+ def transport(self) -> CloudCatalogTransport:
+ """Return the transport used by the client instance.
+
+ Returns:
+ CloudCatalogTransport: The transport used by the client instance.
+ """
+ return self._transport
+
+ @staticmethod
+ def service_path(service: str,) -> str:
+ """Return a fully-qualified service string."""
+ return "services/{service}".format(service=service,)
+
+ @staticmethod
+ def parse_service_path(path: str) -> Dict[str, str]:
+ """Parse a service path into its component segments."""
+ m = re.match(r"^services/(?P.+?)$", path)
+ return m.groupdict() if m else {}
+
+ @staticmethod
+ def sku_path(service: str, sku: str,) -> str:
+ """Return a fully-qualified sku string."""
+ return "services/{service}/skus/{sku}".format(service=service, sku=sku,)
+
+ @staticmethod
+ def parse_sku_path(path: str) -> Dict[str, str]:
+ """Parse a sku path into its component segments."""
+ m = re.match(r"^services/(?P.+?)/skus/(?P.+?)$", path)
+ return m.groupdict() if m else {}
+
+ @staticmethod
+ def common_billing_account_path(billing_account: str,) -> str:
+ """Return a fully-qualified billing_account string."""
+ return "billingAccounts/{billing_account}".format(
+ billing_account=billing_account,
+ )
+
+ @staticmethod
+ def parse_common_billing_account_path(path: str) -> Dict[str, str]:
+ """Parse a billing_account path into its component segments."""
+ m = re.match(r"^billingAccounts/(?P.+?)$", path)
+ return m.groupdict() if m else {}
+
+ @staticmethod
+ def common_folder_path(folder: str,) -> str:
+ """Return a fully-qualified folder string."""
+ return "folders/{folder}".format(folder=folder,)
+
+ @staticmethod
+ def parse_common_folder_path(path: str) -> Dict[str, str]:
+ """Parse a folder path into its component segments."""
+ m = re.match(r"^folders/(?P.+?)$", path)
+ return m.groupdict() if m else {}
+
+ @staticmethod
+ def common_organization_path(organization: str,) -> str:
+ """Return a fully-qualified organization string."""
+ return "organizations/{organization}".format(organization=organization,)
+
+ @staticmethod
+ def parse_common_organization_path(path: str) -> Dict[str, str]:
+ """Parse a organization path into its component segments."""
+ m = re.match(r"^organizations/(?P.+?)$", path)
+ return m.groupdict() if m else {}
+
+ @staticmethod
+ def common_project_path(project: str,) -> str:
+ """Return a fully-qualified project string."""
+ return "projects/{project}".format(project=project,)
+
+ @staticmethod
+ def parse_common_project_path(path: str) -> Dict[str, str]:
+ """Parse a project path into its component segments."""
+ m = re.match(r"^projects/(?P.+?)$", path)
+ return m.groupdict() if m else {}
+
+ @staticmethod
+ def common_location_path(project: str, location: str,) -> str:
+ """Return a fully-qualified location string."""
+ return "projects/{project}/locations/{location}".format(
+ project=project, location=location,
+ )
+
+ @staticmethod
+ def parse_common_location_path(path: str) -> Dict[str, str]:
+ """Parse a location path into its component segments."""
+ m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path)
+ return m.groupdict() if m else {}
+
def __init__(
self,
*,
- credentials: credentials.Credentials = None,
- transport: Union[str, CloudCatalogTransport] = None,
- client_options: ClientOptions = None,
+ credentials: Optional[credentials.Credentials] = None,
+ transport: Union[str, CloudCatalogTransport, None] = None,
+ client_options: Optional[client_options_lib.ClientOptions] = None,
+ client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
) -> None:
"""Instantiate the cloud catalog client.
@@ -142,66 +240,102 @@ def __init__(
transport (Union[str, ~.CloudCatalogTransport]): The
transport to use. If set to None, a transport is chosen
automatically.
- client_options (ClientOptions): Custom options for the client.
+ client_options (client_options_lib.ClientOptions): Custom options for the
+ client. It won't take effect if a ``transport`` instance is provided.
(1) The ``api_endpoint`` property can be used to override the
- default endpoint provided by the client.
- (2) If ``transport`` argument is None, ``client_options`` can be
- used to create a mutual TLS transport. If ``client_cert_source``
- is provided, mutual TLS transport will be created with the given
- ``api_endpoint`` or the default mTLS endpoint, and the client
- SSL credentials obtained from ``client_cert_source``.
+ default endpoint provided by the client. GOOGLE_API_USE_MTLS_ENDPOINT
+ environment variable can also be used to override the endpoint:
+ "always" (always use the default mTLS endpoint), "never" (always
+ use the default regular endpoint) and "auto" (auto switch to the
+ default mTLS endpoint if client certificate is present, this is
+ the default value). However, the ``api_endpoint`` property takes
+ precedence if provided.
+ (2) If GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable
+ is "true", then the ``client_cert_source`` property can be used
+ to provide client certificate for mutual TLS transport. If
+ not provided, the default SSL client certificate will be used if
+ present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not
+ set, no client certificate will be used.
+ client_info (google.api_core.gapic_v1.client_info.ClientInfo):
+ The client info used to send a user-agent string along with
+ API requests. If ``None``, then default info will be used.
+ Generally, you only need to set this if you're developing
+ your own client library.
Raises:
- google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
+ google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport
creation failed for any reason.
"""
if isinstance(client_options, dict):
- client_options = ClientOptions.from_dict(client_options)
+ client_options = client_options_lib.from_dict(client_options)
+ if client_options is None:
+ client_options = client_options_lib.ClientOptions()
+
+ # Create SSL credentials for mutual TLS if needed.
+ use_client_cert = bool(
+ util.strtobool(os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"))
+ )
+
+ ssl_credentials = None
+ is_mtls = False
+ if use_client_cert:
+ if client_options.client_cert_source:
+ import grpc # type: ignore
+
+ cert, key = client_options.client_cert_source()
+ ssl_credentials = grpc.ssl_channel_credentials(
+ certificate_chain=cert, private_key=key
+ )
+ is_mtls = True
+ else:
+ creds = SslCredentials()
+ is_mtls = creds.is_mtls
+ ssl_credentials = creds.ssl_credentials if is_mtls else None
+
+ # Figure out which api endpoint to use.
+ if client_options.api_endpoint is not None:
+ api_endpoint = client_options.api_endpoint
+ else:
+ use_mtls_env = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
+ if use_mtls_env == "never":
+ api_endpoint = self.DEFAULT_ENDPOINT
+ elif use_mtls_env == "always":
+ api_endpoint = self.DEFAULT_MTLS_ENDPOINT
+ elif use_mtls_env == "auto":
+ api_endpoint = (
+ self.DEFAULT_MTLS_ENDPOINT if is_mtls else self.DEFAULT_ENDPOINT
+ )
+ else:
+ raise MutualTLSChannelError(
+ "Unsupported GOOGLE_API_USE_MTLS_ENDPOINT value. Accepted values: never, auto, always"
+ )
# Save or instantiate the transport.
# Ordinarily, we provide the transport, but allowing a custom transport
# instance provides an extensibility point for unusual situations.
if isinstance(transport, CloudCatalogTransport):
# transport is a CloudCatalogTransport instance.
- if credentials:
+ if credentials or client_options.credentials_file:
raise ValueError(
"When providing a transport instance, "
"provide its credentials directly."
)
+ if client_options.scopes:
+ raise ValueError(
+ "When providing a transport instance, "
+ "provide its scopes directly."
+ )
self._transport = transport
- elif client_options is None or (
- client_options.api_endpoint is None
- and client_options.client_cert_source is None
- ):
- # Don't trigger mTLS if we get an empty ClientOptions.
+ else:
Transport = type(self).get_transport_class(transport)
self._transport = Transport(
- credentials=credentials, host=self.DEFAULT_ENDPOINT
- )
- else:
- # We have a non-empty ClientOptions. If client_cert_source is
- # provided, trigger mTLS with user provided endpoint or the default
- # mTLS endpoint.
- if client_options.client_cert_source:
- api_mtls_endpoint = (
- client_options.api_endpoint
- if client_options.api_endpoint
- else self.DEFAULT_MTLS_ENDPOINT
- )
- else:
- api_mtls_endpoint = None
-
- api_endpoint = (
- client_options.api_endpoint
- if client_options.api_endpoint
- else self.DEFAULT_ENDPOINT
- )
-
- self._transport = CloudCatalogGrpcTransport(
credentials=credentials,
+ credentials_file=client_options.credentials_file,
host=api_endpoint,
- api_mtls_endpoint=api_mtls_endpoint,
- client_cert_source=client_options.client_cert_source,
+ scopes=client_options.scopes,
+ ssl_channel_credentials=ssl_credentials,
+ quota_project_id=client_options.quota_project_id,
+ client_info=client_info,
)
def list_services(
@@ -234,23 +368,24 @@ def list_services(
"""
# Create or coerce a protobuf request object.
- request = cloud_catalog.ListServicesRequest(request)
+ # Minor optimization to avoid making a copy if the user passes
+ # in a cloud_catalog.ListServicesRequest.
+ # There's no risk of modifying the input as we've already verified
+ # there are no flattened fields.
+ if not isinstance(request, cloud_catalog.ListServicesRequest):
+ request = cloud_catalog.ListServicesRequest(request)
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
- rpc = gapic_v1.method.wrap_method(
- self._transport.list_services,
- default_timeout=None,
- client_info=_client_info,
- )
+ rpc = self._transport._wrapped_methods[self._transport.list_services]
# Send the request.
- response = rpc(request, retry=retry, timeout=timeout, metadata=metadata)
+ response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
# This method is paged; wrap the response in a pager, which provides
# an `__iter__` convenience method.
response = pagers.ListServicesPager(
- method=rpc, request=request, response=response
+ method=rpc, request=request, response=response, metadata=metadata,
)
# Done; return the response.
@@ -295,25 +430,29 @@ def list_skus(
# Create or coerce a protobuf request object.
# Sanity check: If we got a request object, we should *not* have
# gotten any keyword arguments that map to the request.
- if request is not None and any([parent]):
+ has_flattened_params = any([parent])
+ if request is not None and has_flattened_params:
raise ValueError(
"If the `request` argument is set, then none of "
"the individual field arguments should be set."
)
- request = cloud_catalog.ListSkusRequest(request)
+ # Minor optimization to avoid making a copy if the user passes
+ # in a cloud_catalog.ListSkusRequest.
+ # There's no risk of modifying the input as we've already verified
+ # there are no flattened fields.
+ if not isinstance(request, cloud_catalog.ListSkusRequest):
+ request = cloud_catalog.ListSkusRequest(request)
- # If we have keyword arguments corresponding to fields on the
- # request, apply these.
+ # If we have keyword arguments corresponding to fields on the
+ # request, apply these.
- if parent is not None:
- request.parent = parent
+ if parent is not None:
+ request.parent = parent
# Wrap the RPC method; this adds retry and timeout information,
# and friendly error handling.
- rpc = gapic_v1.method.wrap_method(
- self._transport.list_skus, default_timeout=None, client_info=_client_info
- )
+ rpc = self._transport._wrapped_methods[self._transport.list_skus]
# Certain fields should be provided within the metadata header;
# add these here.
@@ -322,22 +461,24 @@ def list_skus(
)
# Send the request.
- response = rpc(request, retry=retry, timeout=timeout, metadata=metadata)
+ response = rpc(request, retry=retry, timeout=timeout, metadata=metadata,)
# This method is paged; wrap the response in a pager, which provides
# an `__iter__` convenience method.
- response = pagers.ListSkusPager(method=rpc, request=request, response=response)
+ response = pagers.ListSkusPager(
+ method=rpc, request=request, response=response, metadata=metadata,
+ )
# Done; return the response.
return response
try:
- _client_info = gapic_v1.client_info.ClientInfo(
- gapic_version=pkg_resources.get_distribution("google-cloud-billing").version
+ DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
+ gapic_version=pkg_resources.get_distribution("google-cloud-billing",).version,
)
except pkg_resources.DistributionNotFound:
- _client_info = gapic_v1.client_info.ClientInfo()
+ DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo()
__all__ = ("CloudCatalogClient",)
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/pagers.py b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/pagers.py
index 3e74a0a36a1a..e9da0246724e 100644
--- a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/pagers.py
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/pagers.py
@@ -15,7 +15,7 @@
# limitations under the License.
#
-from typing import Any, Callable, Iterable
+from typing import Any, AsyncIterable, Awaitable, Callable, Iterable, Sequence, Tuple
from google.cloud.billing_v1.types import cloud_catalog
@@ -40,11 +40,11 @@ class ListServicesPager:
def __init__(
self,
- method: Callable[
- [cloud_catalog.ListServicesRequest], cloud_catalog.ListServicesResponse
- ],
+ method: Callable[..., cloud_catalog.ListServicesResponse],
request: cloud_catalog.ListServicesRequest,
response: cloud_catalog.ListServicesResponse,
+ *,
+ metadata: Sequence[Tuple[str, str]] = ()
):
"""Instantiate the pager.
@@ -55,10 +55,13 @@ def __init__(
The initial request object.
response (:class:`~.cloud_catalog.ListServicesResponse`):
The initial response object.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
"""
self._method = method
self._request = cloud_catalog.ListServicesRequest(request)
self._response = response
+ self._metadata = metadata
def __getattr__(self, name: str) -> Any:
return getattr(self._response, name)
@@ -68,7 +71,7 @@ def pages(self) -> Iterable[cloud_catalog.ListServicesResponse]:
yield self._response
while self._response.next_page_token:
self._request.page_token = self._response.next_page_token
- self._response = self._method(self._request)
+ self._response = self._method(self._request, metadata=self._metadata)
yield self._response
def __iter__(self) -> Iterable[cloud_catalog.Service]:
@@ -79,6 +82,72 @@ def __repr__(self) -> str:
return "{0}<{1!r}>".format(self.__class__.__name__, self._response)
+class ListServicesAsyncPager:
+ """A pager for iterating through ``list_services`` requests.
+
+ This class thinly wraps an initial
+ :class:`~.cloud_catalog.ListServicesResponse` object, and
+ provides an ``__aiter__`` method to iterate through its
+ ``services`` field.
+
+ If there are more pages, the ``__aiter__`` method will make additional
+ ``ListServices`` requests and continue to iterate
+ through the ``services`` field on the
+ corresponding responses.
+
+ All the usual :class:`~.cloud_catalog.ListServicesResponse`
+ attributes are available on the pager. If multiple requests are made, only
+ the most recent response is retained, and thus used for attribute lookup.
+ """
+
+ def __init__(
+ self,
+ method: Callable[..., Awaitable[cloud_catalog.ListServicesResponse]],
+ request: cloud_catalog.ListServicesRequest,
+ response: cloud_catalog.ListServicesResponse,
+ *,
+ metadata: Sequence[Tuple[str, str]] = ()
+ ):
+ """Instantiate the pager.
+
+ Args:
+ method (Callable): The method that was originally called, and
+ which instantiated this pager.
+ request (:class:`~.cloud_catalog.ListServicesRequest`):
+ The initial request object.
+ response (:class:`~.cloud_catalog.ListServicesResponse`):
+ The initial response object.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
+ """
+ self._method = method
+ self._request = cloud_catalog.ListServicesRequest(request)
+ self._response = response
+ self._metadata = metadata
+
+ def __getattr__(self, name: str) -> Any:
+ return getattr(self._response, name)
+
+ @property
+ async def pages(self) -> AsyncIterable[cloud_catalog.ListServicesResponse]:
+ yield self._response
+ while self._response.next_page_token:
+ self._request.page_token = self._response.next_page_token
+ self._response = await self._method(self._request, metadata=self._metadata)
+ yield self._response
+
+ def __aiter__(self) -> AsyncIterable[cloud_catalog.Service]:
+ async def async_generator():
+ async for page in self.pages:
+ for response in page.services:
+ yield response
+
+ return async_generator()
+
+ def __repr__(self) -> str:
+ return "{0}<{1!r}>".format(self.__class__.__name__, self._response)
+
+
class ListSkusPager:
"""A pager for iterating through ``list_skus`` requests.
@@ -99,11 +168,11 @@ class ListSkusPager:
def __init__(
self,
- method: Callable[
- [cloud_catalog.ListSkusRequest], cloud_catalog.ListSkusResponse
- ],
+ method: Callable[..., cloud_catalog.ListSkusResponse],
request: cloud_catalog.ListSkusRequest,
response: cloud_catalog.ListSkusResponse,
+ *,
+ metadata: Sequence[Tuple[str, str]] = ()
):
"""Instantiate the pager.
@@ -114,10 +183,13 @@ def __init__(
The initial request object.
response (:class:`~.cloud_catalog.ListSkusResponse`):
The initial response object.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
"""
self._method = method
self._request = cloud_catalog.ListSkusRequest(request)
self._response = response
+ self._metadata = metadata
def __getattr__(self, name: str) -> Any:
return getattr(self._response, name)
@@ -127,7 +199,7 @@ def pages(self) -> Iterable[cloud_catalog.ListSkusResponse]:
yield self._response
while self._response.next_page_token:
self._request.page_token = self._response.next_page_token
- self._response = self._method(self._request)
+ self._response = self._method(self._request, metadata=self._metadata)
yield self._response
def __iter__(self) -> Iterable[cloud_catalog.Sku]:
@@ -136,3 +208,69 @@ def __iter__(self) -> Iterable[cloud_catalog.Sku]:
def __repr__(self) -> str:
return "{0}<{1!r}>".format(self.__class__.__name__, self._response)
+
+
+class ListSkusAsyncPager:
+ """A pager for iterating through ``list_skus`` requests.
+
+ This class thinly wraps an initial
+ :class:`~.cloud_catalog.ListSkusResponse` object, and
+ provides an ``__aiter__`` method to iterate through its
+ ``skus`` field.
+
+ If there are more pages, the ``__aiter__`` method will make additional
+ ``ListSkus`` requests and continue to iterate
+ through the ``skus`` field on the
+ corresponding responses.
+
+ All the usual :class:`~.cloud_catalog.ListSkusResponse`
+ attributes are available on the pager. If multiple requests are made, only
+ the most recent response is retained, and thus used for attribute lookup.
+ """
+
+ def __init__(
+ self,
+ method: Callable[..., Awaitable[cloud_catalog.ListSkusResponse]],
+ request: cloud_catalog.ListSkusRequest,
+ response: cloud_catalog.ListSkusResponse,
+ *,
+ metadata: Sequence[Tuple[str, str]] = ()
+ ):
+ """Instantiate the pager.
+
+ Args:
+ method (Callable): The method that was originally called, and
+ which instantiated this pager.
+ request (:class:`~.cloud_catalog.ListSkusRequest`):
+ The initial request object.
+ response (:class:`~.cloud_catalog.ListSkusResponse`):
+ The initial response object.
+ metadata (Sequence[Tuple[str, str]]): Strings which should be
+ sent along with the request as metadata.
+ """
+ self._method = method
+ self._request = cloud_catalog.ListSkusRequest(request)
+ self._response = response
+ self._metadata = metadata
+
+ def __getattr__(self, name: str) -> Any:
+ return getattr(self._response, name)
+
+ @property
+ async def pages(self) -> AsyncIterable[cloud_catalog.ListSkusResponse]:
+ yield self._response
+ while self._response.next_page_token:
+ self._request.page_token = self._response.next_page_token
+ self._response = await self._method(self._request, metadata=self._metadata)
+ yield self._response
+
+ def __aiter__(self) -> AsyncIterable[cloud_catalog.Sku]:
+ async def async_generator():
+ async for page in self.pages:
+ for response in page.skus:
+ yield response
+
+ return async_generator()
+
+ def __repr__(self) -> str:
+ return "{0}<{1!r}>".format(self.__class__.__name__, self._response)
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/transports/__init__.py b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/transports/__init__.py
index a75502743787..a81f59eab3cb 100644
--- a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/transports/__init__.py
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/transports/__init__.py
@@ -20,11 +20,16 @@
from .base import CloudCatalogTransport
from .grpc import CloudCatalogGrpcTransport
+from .grpc_asyncio import CloudCatalogGrpcAsyncIOTransport
# Compile a registry of transports.
_transport_registry = OrderedDict() # type: Dict[str, Type[CloudCatalogTransport]]
_transport_registry["grpc"] = CloudCatalogGrpcTransport
+_transport_registry["grpc_asyncio"] = CloudCatalogGrpcAsyncIOTransport
-
-__all__ = ("CloudCatalogTransport", "CloudCatalogGrpcTransport")
+__all__ = (
+ "CloudCatalogTransport",
+ "CloudCatalogGrpcTransport",
+ "CloudCatalogGrpcAsyncIOTransport",
+)
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/transports/base.py b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/transports/base.py
index 8881cf6d3cdf..64179c6f3d4a 100644
--- a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/transports/base.py
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/transports/base.py
@@ -17,14 +17,26 @@
import abc
import typing
+import pkg_resources
-from google import auth
+from google import auth # type: ignore
+from google.api_core import exceptions # type: ignore
+from google.api_core import gapic_v1 # type: ignore
+from google.api_core import retry as retries # type: ignore
from google.auth import credentials # type: ignore
from google.cloud.billing_v1.types import cloud_catalog
-class CloudCatalogTransport(metaclass=abc.ABCMeta):
+try:
+ DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
+ gapic_version=pkg_resources.get_distribution("google-cloud-billing",).version,
+ )
+except pkg_resources.DistributionNotFound:
+ DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo()
+
+
+class CloudCatalogTransport(abc.ABC):
"""Abstract transport class for CloudCatalog."""
AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",)
@@ -34,6 +46,11 @@ def __init__(
*,
host: str = "cloudbilling.googleapis.com",
credentials: credentials.Credentials = None,
+ credentials_file: typing.Optional[str] = None,
+ scopes: typing.Optional[typing.Sequence[str]] = AUTH_SCOPES,
+ quota_project_id: typing.Optional[str] = None,
+ client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
+ **kwargs,
) -> None:
"""Instantiate the transport.
@@ -44,6 +61,17 @@ def __init__(
credentials identify the application to the service; if none
are specified, the client will attempt to ascertain the
credentials from the environment.
+ credentials_file (Optional[str]): A file with credentials that can
+ be loaded with :func:`google.auth.load_credentials_from_file`.
+ This argument is mutually exclusive with credentials.
+ scope (Optional[Sequence[str]]): A list of scopes.
+ quota_project_id (Optional[str]): An optional project to use for billing
+ and quota.
+ client_info (google.api_core.gapic_v1.client_info.ClientInfo):
+ The client info used to send a user-agent string along with
+ API requests. If ``None``, then default info will be used.
+ Generally, you only need to set this if you're developing
+ your own client library.
"""
# Save the hostname. Default to port 443 (HTTPS) if none is specified.
if ":" not in host:
@@ -52,27 +80,61 @@ def __init__(
# If no credentials are provided, then determine the appropriate
# defaults.
- if credentials is None:
- credentials, _ = auth.default(scopes=self.AUTH_SCOPES)
+ if credentials and credentials_file:
+ raise exceptions.DuplicateCredentialArgs(
+ "'credentials_file' and 'credentials' are mutually exclusive"
+ )
+
+ if credentials_file is not None:
+ credentials, _ = auth.load_credentials_from_file(
+ credentials_file, scopes=scopes, quota_project_id=quota_project_id
+ )
+
+ elif credentials is None:
+ credentials, _ = auth.default(
+ scopes=scopes, quota_project_id=quota_project_id
+ )
# Save the credentials.
self._credentials = credentials
+ # Lifted into its own function so it can be stubbed out during tests.
+ self._prep_wrapped_messages(client_info)
+
+ def _prep_wrapped_messages(self, client_info):
+ # Precompute the wrapped methods.
+ self._wrapped_methods = {
+ self.list_services: gapic_v1.method.wrap_method(
+ self.list_services, default_timeout=None, client_info=client_info,
+ ),
+ self.list_skus: gapic_v1.method.wrap_method(
+ self.list_skus, default_timeout=None, client_info=client_info,
+ ),
+ }
+
@property
def list_services(
- self
+ self,
) -> typing.Callable[
- [cloud_catalog.ListServicesRequest], cloud_catalog.ListServicesResponse
+ [cloud_catalog.ListServicesRequest],
+ typing.Union[
+ cloud_catalog.ListServicesResponse,
+ typing.Awaitable[cloud_catalog.ListServicesResponse],
+ ],
]:
- raise NotImplementedError
+ raise NotImplementedError()
@property
def list_skus(
- self
+ self,
) -> typing.Callable[
- [cloud_catalog.ListSkusRequest], cloud_catalog.ListSkusResponse
+ [cloud_catalog.ListSkusRequest],
+ typing.Union[
+ cloud_catalog.ListSkusResponse,
+ typing.Awaitable[cloud_catalog.ListSkusResponse],
+ ],
]:
- raise NotImplementedError
+ raise NotImplementedError()
__all__ = ("CloudCatalogTransport",)
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/transports/grpc.py b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/transports/grpc.py
index 0a57347fcf72..e41b101fe55f 100644
--- a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/transports/grpc.py
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/transports/grpc.py
@@ -15,18 +15,20 @@
# limitations under the License.
#
-from typing import Callable, Dict, Tuple
+import warnings
+from typing import Callable, Dict, Optional, Sequence, Tuple
from google.api_core import grpc_helpers # type: ignore
+from google.api_core import gapic_v1 # type: ignore
+from google import auth # type: ignore
from google.auth import credentials # type: ignore
from google.auth.transport.grpc import SslCredentials # type: ignore
-
import grpc # type: ignore
from google.cloud.billing_v1.types import cloud_catalog
-from .base import CloudCatalogTransport
+from .base import CloudCatalogTransport, DEFAULT_CLIENT_INFO
class CloudCatalogGrpcTransport(CloudCatalogTransport):
@@ -44,14 +46,21 @@ class CloudCatalogGrpcTransport(CloudCatalogTransport):
top of HTTP/2); the ``grpcio`` package must be installed.
"""
+ _stubs: Dict[str, Callable]
+
def __init__(
self,
*,
host: str = "cloudbilling.googleapis.com",
credentials: credentials.Credentials = None,
+ credentials_file: str = None,
+ scopes: Sequence[str] = None,
channel: grpc.Channel = None,
api_mtls_endpoint: str = None,
- client_cert_source: Callable[[], Tuple[bytes, bytes]] = None
+ client_cert_source: Callable[[], Tuple[bytes, bytes]] = None,
+ ssl_channel_credentials: grpc.ChannelCredentials = None,
+ quota_project_id: Optional[str] = None,
+ client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
) -> None:
"""Instantiate the transport.
@@ -63,21 +72,39 @@ def __init__(
are specified, the client will attempt to ascertain the
credentials from the environment.
This argument is ignored if ``channel`` is provided.
+ credentials_file (Optional[str]): A file with credentials that can
+ be loaded with :func:`google.auth.load_credentials_from_file`.
+ This argument is ignored if ``channel`` is provided.
+ scopes (Optional(Sequence[str])): A list of scopes. This argument is
+ ignored if ``channel`` is provided.
channel (Optional[grpc.Channel]): A ``Channel`` instance through
which to make calls.
- api_mtls_endpoint (Optional[str]): The mutual TLS endpoint. If
- provided, it overrides the ``host`` argument and tries to create
+ api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint.
+ If provided, it overrides the ``host`` argument and tries to create
a mutual TLS channel with client SSL credentials from
``client_cert_source`` or applicatin default SSL credentials.
- client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A
- callback to provide client SSL certificate bytes and private key
- bytes, both in PEM format. It is ignored if ``api_mtls_endpoint``
- is None.
+ client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]):
+ Deprecated. A callback to provide client SSL certificate bytes and
+ private key bytes, both in PEM format. It is ignored if
+ ``api_mtls_endpoint`` is None.
+ ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials
+ for grpc channel. It is ignored if ``channel`` is provided.
+ quota_project_id (Optional[str]): An optional project to use for billing
+ and quota.
+ client_info (google.api_core.gapic_v1.client_info.ClientInfo):
+ The client info used to send a user-agent string along with
+ API requests. If ``None``, then default info will be used.
+ Generally, you only need to set this if you're developing
+ your own client library.
Raises:
- google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
+ google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport
creation failed for any reason.
+ google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials``
+ and ``credentials_file`` are passed.
"""
+ self._ssl_channel_credentials = ssl_channel_credentials
+
if channel:
# Sanity check: Ensure that channel and credentials are not both
# provided.
@@ -85,13 +112,24 @@ def __init__(
# If a channel was explicitly provided, set it.
self._grpc_channel = channel
+ self._ssl_channel_credentials = None
elif api_mtls_endpoint:
+ warnings.warn(
+ "api_mtls_endpoint and client_cert_source are deprecated",
+ DeprecationWarning,
+ )
+
host = (
api_mtls_endpoint
if ":" in api_mtls_endpoint
else api_mtls_endpoint + ":443"
)
+ if credentials is None:
+ credentials, _ = auth.default(
+ scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id
+ )
+
# Create SSL credentials with client_cert_source or application
# default SSL credentials.
if client_cert_source:
@@ -103,61 +141,99 @@ def __init__(
ssl_credentials = SslCredentials().ssl_credentials
# create a new channel. The provided one is ignored.
- self._grpc_channel = grpc_helpers.create_channel(
+ self._grpc_channel = type(self).create_channel(
host,
credentials=credentials,
+ credentials_file=credentials_file,
ssl_credentials=ssl_credentials,
- scopes=self.AUTH_SCOPES,
+ scopes=scopes or self.AUTH_SCOPES,
+ quota_project_id=quota_project_id,
+ )
+ self._ssl_channel_credentials = ssl_credentials
+ else:
+ host = host if ":" in host else host + ":443"
+
+ if credentials is None:
+ credentials, _ = auth.default(
+ scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id
+ )
+
+ # create a new channel. The provided one is ignored.
+ self._grpc_channel = type(self).create_channel(
+ host,
+ credentials=credentials,
+ credentials_file=credentials_file,
+ ssl_credentials=ssl_channel_credentials,
+ scopes=scopes or self.AUTH_SCOPES,
+ quota_project_id=quota_project_id,
)
- # Run the base constructor.
- super().__init__(host=host, credentials=credentials)
self._stubs = {} # type: Dict[str, Callable]
+ # Run the base constructor.
+ super().__init__(
+ host=host,
+ credentials=credentials,
+ credentials_file=credentials_file,
+ scopes=scopes or self.AUTH_SCOPES,
+ quota_project_id=quota_project_id,
+ client_info=client_info,
+ )
+
@classmethod
def create_channel(
cls,
host: str = "cloudbilling.googleapis.com",
credentials: credentials.Credentials = None,
- **kwargs
+ credentials_file: str = None,
+ scopes: Optional[Sequence[str]] = None,
+ quota_project_id: Optional[str] = None,
+ **kwargs,
) -> grpc.Channel:
"""Create and return a gRPC channel object.
Args:
- address (Optionsl[str]): The host for the channel to use.
+ address (Optional[str]): The host for the channel to use.
credentials (Optional[~.Credentials]): The
authorization credentials to attach to requests. These
credentials identify this application to the service. If
none are specified, the client will attempt to ascertain
the credentials from the environment.
+ credentials_file (Optional[str]): A file with credentials that can
+ be loaded with :func:`google.auth.load_credentials_from_file`.
+ This argument is mutually exclusive with credentials.
+ scopes (Optional[Sequence[str]]): A optional list of scopes needed for this
+ service. These are only used when credentials are not specified and
+ are passed to :func:`google.auth.default`.
+ quota_project_id (Optional[str]): An optional project to use for billing
+ and quota.
kwargs (Optional[dict]): Keyword arguments, which are passed to the
channel creation.
Returns:
grpc.Channel: A gRPC channel object.
+
+ Raises:
+ google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials``
+ and ``credentials_file`` are passed.
"""
+ scopes = scopes or cls.AUTH_SCOPES
return grpc_helpers.create_channel(
- host, credentials=credentials, scopes=cls.AUTH_SCOPES, **kwargs
+ host,
+ credentials=credentials,
+ credentials_file=credentials_file,
+ scopes=scopes,
+ quota_project_id=quota_project_id,
+ **kwargs,
)
@property
def grpc_channel(self) -> grpc.Channel:
- """Create the channel designed to connect to this service.
-
- This property caches on the instance; repeated calls return
- the same channel.
+ """Return the channel designed to connect to this service.
"""
- # Sanity check: Only create a new channel if we do not already
- # have one.
- if not hasattr(self, "_grpc_channel"):
- self._grpc_channel = self.create_channel(
- self._host, credentials=self._credentials
- )
-
- # Return the channel from cache.
return self._grpc_channel
@property
def list_services(
- self
+ self,
) -> Callable[
[cloud_catalog.ListServicesRequest], cloud_catalog.ListServicesResponse
]:
@@ -185,7 +261,7 @@ def list_services(
@property
def list_skus(
- self
+ self,
) -> Callable[[cloud_catalog.ListSkusRequest], cloud_catalog.ListSkusResponse]:
r"""Return a callable for the list skus method over gRPC.
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/transports/grpc_asyncio.py b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/transports/grpc_asyncio.py
new file mode 100644
index 000000000000..a2b28efc0db7
--- /dev/null
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/services/cloud_catalog/transports/grpc_asyncio.py
@@ -0,0 +1,297 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import warnings
+from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple
+
+from google.api_core import gapic_v1 # type: ignore
+from google.api_core import grpc_helpers_async # type: ignore
+from google import auth # type: ignore
+from google.auth import credentials # type: ignore
+from google.auth.transport.grpc import SslCredentials # type: ignore
+
+import grpc # type: ignore
+from grpc.experimental import aio # type: ignore
+
+from google.cloud.billing_v1.types import cloud_catalog
+
+from .base import CloudCatalogTransport, DEFAULT_CLIENT_INFO
+from .grpc import CloudCatalogGrpcTransport
+
+
+class CloudCatalogGrpcAsyncIOTransport(CloudCatalogTransport):
+ """gRPC AsyncIO backend transport for CloudCatalog.
+
+ A catalog of Google Cloud Platform services and SKUs.
+ Provides pricing information and metadata on Google Cloud
+ Platform services and SKUs.
+
+ This class defines the same methods as the primary client, so the
+ primary client can load the underlying transport implementation
+ and call it.
+
+ It sends protocol buffers over the wire using gRPC (which is built on
+ top of HTTP/2); the ``grpcio`` package must be installed.
+ """
+
+ _grpc_channel: aio.Channel
+ _stubs: Dict[str, Callable] = {}
+
+ @classmethod
+ def create_channel(
+ cls,
+ host: str = "cloudbilling.googleapis.com",
+ credentials: credentials.Credentials = None,
+ credentials_file: Optional[str] = None,
+ scopes: Optional[Sequence[str]] = None,
+ quota_project_id: Optional[str] = None,
+ **kwargs,
+ ) -> aio.Channel:
+ """Create and return a gRPC AsyncIO channel object.
+ Args:
+ address (Optional[str]): The host for the channel to use.
+ credentials (Optional[~.Credentials]): The
+ authorization credentials to attach to requests. These
+ credentials identify this application to the service. If
+ none are specified, the client will attempt to ascertain
+ the credentials from the environment.
+ credentials_file (Optional[str]): A file with credentials that can
+ be loaded with :func:`google.auth.load_credentials_from_file`.
+ This argument is ignored if ``channel`` is provided.
+ scopes (Optional[Sequence[str]]): A optional list of scopes needed for this
+ service. These are only used when credentials are not specified and
+ are passed to :func:`google.auth.default`.
+ quota_project_id (Optional[str]): An optional project to use for billing
+ and quota.
+ kwargs (Optional[dict]): Keyword arguments, which are passed to the
+ channel creation.
+ Returns:
+ aio.Channel: A gRPC AsyncIO channel object.
+ """
+ scopes = scopes or cls.AUTH_SCOPES
+ return grpc_helpers_async.create_channel(
+ host,
+ credentials=credentials,
+ credentials_file=credentials_file,
+ scopes=scopes,
+ quota_project_id=quota_project_id,
+ **kwargs,
+ )
+
+ def __init__(
+ self,
+ *,
+ host: str = "cloudbilling.googleapis.com",
+ credentials: credentials.Credentials = None,
+ credentials_file: Optional[str] = None,
+ scopes: Optional[Sequence[str]] = None,
+ channel: aio.Channel = None,
+ api_mtls_endpoint: str = None,
+ client_cert_source: Callable[[], Tuple[bytes, bytes]] = None,
+ ssl_channel_credentials: grpc.ChannelCredentials = None,
+ quota_project_id=None,
+ client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
+ ) -> None:
+ """Instantiate the transport.
+
+ Args:
+ host (Optional[str]): The hostname to connect to.
+ credentials (Optional[google.auth.credentials.Credentials]): The
+ authorization credentials to attach to requests. These
+ credentials identify the application to the service; if none
+ are specified, the client will attempt to ascertain the
+ credentials from the environment.
+ This argument is ignored if ``channel`` is provided.
+ credentials_file (Optional[str]): A file with credentials that can
+ be loaded with :func:`google.auth.load_credentials_from_file`.
+ This argument is ignored if ``channel`` is provided.
+ scopes (Optional[Sequence[str]]): A optional list of scopes needed for this
+ service. These are only used when credentials are not specified and
+ are passed to :func:`google.auth.default`.
+ channel (Optional[aio.Channel]): A ``Channel`` instance through
+ which to make calls.
+ api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint.
+ If provided, it overrides the ``host`` argument and tries to create
+ a mutual TLS channel with client SSL credentials from
+ ``client_cert_source`` or applicatin default SSL credentials.
+ client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]):
+ Deprecated. A callback to provide client SSL certificate bytes and
+ private key bytes, both in PEM format. It is ignored if
+ ``api_mtls_endpoint`` is None.
+ ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials
+ for grpc channel. It is ignored if ``channel`` is provided.
+ quota_project_id (Optional[str]): An optional project to use for billing
+ and quota.
+ client_info (google.api_core.gapic_v1.client_info.ClientInfo):
+ The client info used to send a user-agent string along with
+ API requests. If ``None``, then default info will be used.
+ Generally, you only need to set this if you're developing
+ your own client library.
+
+ Raises:
+ google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
+ creation failed for any reason.
+ google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials``
+ and ``credentials_file`` are passed.
+ """
+ self._ssl_channel_credentials = ssl_channel_credentials
+
+ if channel:
+ # Sanity check: Ensure that channel and credentials are not both
+ # provided.
+ credentials = False
+
+ # If a channel was explicitly provided, set it.
+ self._grpc_channel = channel
+ self._ssl_channel_credentials = None
+ elif api_mtls_endpoint:
+ warnings.warn(
+ "api_mtls_endpoint and client_cert_source are deprecated",
+ DeprecationWarning,
+ )
+
+ host = (
+ api_mtls_endpoint
+ if ":" in api_mtls_endpoint
+ else api_mtls_endpoint + ":443"
+ )
+
+ if credentials is None:
+ credentials, _ = auth.default(
+ scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id
+ )
+
+ # Create SSL credentials with client_cert_source or application
+ # default SSL credentials.
+ if client_cert_source:
+ cert, key = client_cert_source()
+ ssl_credentials = grpc.ssl_channel_credentials(
+ certificate_chain=cert, private_key=key
+ )
+ else:
+ ssl_credentials = SslCredentials().ssl_credentials
+
+ # create a new channel. The provided one is ignored.
+ self._grpc_channel = type(self).create_channel(
+ host,
+ credentials=credentials,
+ credentials_file=credentials_file,
+ ssl_credentials=ssl_credentials,
+ scopes=scopes or self.AUTH_SCOPES,
+ quota_project_id=quota_project_id,
+ )
+ self._ssl_channel_credentials = ssl_credentials
+ else:
+ host = host if ":" in host else host + ":443"
+
+ if credentials is None:
+ credentials, _ = auth.default(
+ scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id
+ )
+
+ # create a new channel. The provided one is ignored.
+ self._grpc_channel = type(self).create_channel(
+ host,
+ credentials=credentials,
+ credentials_file=credentials_file,
+ ssl_credentials=ssl_channel_credentials,
+ scopes=scopes or self.AUTH_SCOPES,
+ quota_project_id=quota_project_id,
+ )
+
+ # Run the base constructor.
+ super().__init__(
+ host=host,
+ credentials=credentials,
+ credentials_file=credentials_file,
+ scopes=scopes or self.AUTH_SCOPES,
+ quota_project_id=quota_project_id,
+ client_info=client_info,
+ )
+
+ self._stubs = {}
+
+ @property
+ def grpc_channel(self) -> aio.Channel:
+ """Create the channel designed to connect to this service.
+
+ This property caches on the instance; repeated calls return
+ the same channel.
+ """
+ # Return the channel from cache.
+ return self._grpc_channel
+
+ @property
+ def list_services(
+ self,
+ ) -> Callable[
+ [cloud_catalog.ListServicesRequest],
+ Awaitable[cloud_catalog.ListServicesResponse],
+ ]:
+ r"""Return a callable for the list services method over gRPC.
+
+ Lists all public cloud services.
+
+ Returns:
+ Callable[[~.ListServicesRequest],
+ Awaitable[~.ListServicesResponse]]:
+ A function that, when called, will call the underlying RPC
+ on the server.
+ """
+ # Generate a "stub function" on-the-fly which will actually make
+ # the request.
+ # gRPC handles serialization and deserialization, so we just need
+ # to pass in the functions for each.
+ if "list_services" not in self._stubs:
+ self._stubs["list_services"] = self.grpc_channel.unary_unary(
+ "/google.cloud.billing.v1.CloudCatalog/ListServices",
+ request_serializer=cloud_catalog.ListServicesRequest.serialize,
+ response_deserializer=cloud_catalog.ListServicesResponse.deserialize,
+ )
+ return self._stubs["list_services"]
+
+ @property
+ def list_skus(
+ self,
+ ) -> Callable[
+ [cloud_catalog.ListSkusRequest], Awaitable[cloud_catalog.ListSkusResponse]
+ ]:
+ r"""Return a callable for the list skus method over gRPC.
+
+ Lists all publicly available SKUs for a given cloud
+ service.
+
+ Returns:
+ Callable[[~.ListSkusRequest],
+ Awaitable[~.ListSkusResponse]]:
+ A function that, when called, will call the underlying RPC
+ on the server.
+ """
+ # Generate a "stub function" on-the-fly which will actually make
+ # the request.
+ # gRPC handles serialization and deserialization, so we just need
+ # to pass in the functions for each.
+ if "list_skus" not in self._stubs:
+ self._stubs["list_skus"] = self.grpc_channel.unary_unary(
+ "/google.cloud.billing.v1.CloudCatalog/ListSkus",
+ request_serializer=cloud_catalog.ListSkusRequest.serialize,
+ response_deserializer=cloud_catalog.ListSkusResponse.deserialize,
+ )
+ return self._stubs["list_skus"]
+
+
+__all__ = ("CloudCatalogGrpcAsyncIOTransport",)
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/types/__init__.py b/packages/google-cloud-billing/google/cloud/billing_v1/types/__init__.py
index 2521cc934466..528706531842 100644
--- a/packages/google-cloud-billing/google/cloud/billing_v1/types/__init__.py
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/types/__init__.py
@@ -41,7 +41,6 @@
UpdateProjectBillingInfoRequest,
)
-
__all__ = (
"Service",
"Sku",
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/types/cloud_billing.py b/packages/google-cloud-billing/google/cloud/billing_v1/types/cloud_billing.py
index 8c9bf76387b9..5b1090de11d4 100644
--- a/packages/google-cloud-billing/google/cloud/billing_v1/types/cloud_billing.py
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/types/cloud_billing.py
@@ -51,7 +51,7 @@ class BillingAccount(proto.Message):
example, ``billingAccounts/012345-567890-ABCDEF`` would be
the resource name for billing account
``012345-567890-ABCDEF``.
- open (bool):
+ open_ (bool):
Output only. True if the billing account is
open, and will therefore be charged for any
usage on associated projects. False if the
@@ -71,8 +71,11 @@ class BillingAccount(proto.Message):
"""
name = proto.Field(proto.STRING, number=1)
- open = proto.Field(proto.BOOL, number=2)
+
+ open_ = proto.Field(proto.BOOL, number=2)
+
display_name = proto.Field(proto.STRING, number=3)
+
master_billing_account = proto.Field(proto.STRING, number=4)
@@ -110,8 +113,11 @@ class ProjectBillingInfo(proto.Message):
"""
name = proto.Field(proto.STRING, number=1)
+
project_id = proto.Field(proto.STRING, number=2)
+
billing_account_name = proto.Field(proto.STRING, number=3)
+
billing_enabled = proto.Field(proto.BOOL, number=4)
@@ -151,7 +157,9 @@ class ListBillingAccountsRequest(proto.Message):
"""
page_size = proto.Field(proto.INT32, number=1)
+
page_token = proto.Field(proto.STRING, number=2)
+
filter = proto.Field(proto.STRING, number=3)
@@ -173,8 +181,9 @@ def raw_page(self):
return self
billing_accounts = proto.RepeatedField(
- proto.MESSAGE, number=1, message=BillingAccount
+ proto.MESSAGE, number=1, message="BillingAccount",
)
+
next_page_token = proto.Field(proto.STRING, number=2)
@@ -190,7 +199,7 @@ class CreateBillingAccountRequest(proto.Message):
billing account.
"""
- billing_account = proto.Field(proto.MESSAGE, number=1, message=BillingAccount)
+ billing_account = proto.Field(proto.MESSAGE, number=1, message="BillingAccount",)
class UpdateBillingAccountRequest(proto.Message):
@@ -209,8 +218,10 @@ class UpdateBillingAccountRequest(proto.Message):
"""
name = proto.Field(proto.STRING, number=1)
- account = proto.Field(proto.MESSAGE, number=2, message=BillingAccount)
- update_mask = proto.Field(proto.MESSAGE, number=3, message=field_mask.FieldMask)
+
+ account = proto.Field(proto.MESSAGE, number=2, message="BillingAccount",)
+
+ update_mask = proto.Field(proto.MESSAGE, number=3, message=field_mask.FieldMask,)
class ListProjectBillingInfoRequest(proto.Message):
@@ -232,7 +243,9 @@ class ListProjectBillingInfoRequest(proto.Message):
"""
name = proto.Field(proto.STRING, number=1)
+
page_size = proto.Field(proto.INT32, number=2)
+
page_token = proto.Field(proto.STRING, number=3)
@@ -255,8 +268,9 @@ def raw_page(self):
return self
project_billing_info = proto.RepeatedField(
- proto.MESSAGE, number=1, message=ProjectBillingInfo
+ proto.MESSAGE, number=1, message="ProjectBillingInfo",
)
+
next_page_token = proto.Field(proto.STRING, number=2)
@@ -288,8 +302,9 @@ class UpdateProjectBillingInfoRequest(proto.Message):
"""
name = proto.Field(proto.STRING, number=1)
+
project_billing_info = proto.Field(
- proto.MESSAGE, number=2, message=ProjectBillingInfo
+ proto.MESSAGE, number=2, message="ProjectBillingInfo",
)
diff --git a/packages/google-cloud-billing/google/cloud/billing_v1/types/cloud_catalog.py b/packages/google-cloud-billing/google/cloud/billing_v1/types/cloud_catalog.py
index 206b93a6d409..36278e8dce24 100644
--- a/packages/google-cloud-billing/google/cloud/billing_v1/types/cloud_catalog.py
+++ b/packages/google-cloud-billing/google/cloud/billing_v1/types/cloud_catalog.py
@@ -59,8 +59,11 @@ class Service(proto.Message):
"""
name = proto.Field(proto.STRING, number=1)
+
service_id = proto.Field(proto.STRING, number=2)
+
display_name = proto.Field(proto.STRING, number=3)
+
business_entity_name = proto.Field(proto.STRING, number=4)
@@ -96,11 +99,17 @@ class Sku(proto.Message):
"""
name = proto.Field(proto.STRING, number=1)
+
sku_id = proto.Field(proto.STRING, number=2)
+
description = proto.Field(proto.STRING, number=3)
- category = proto.Field(proto.MESSAGE, number=4, message="Category")
+
+ category = proto.Field(proto.MESSAGE, number=4, message="Category",)
+
service_regions = proto.RepeatedField(proto.STRING, number=5)
- pricing_info = proto.RepeatedField(proto.MESSAGE, number=6, message="PricingInfo")
+
+ pricing_info = proto.RepeatedField(proto.MESSAGE, number=6, message="PricingInfo",)
+
service_provider_name = proto.Field(proto.STRING, number=7)
@@ -126,8 +135,11 @@ class Category(proto.Message):
"""
service_display_name = proto.Field(proto.STRING, number=1)
+
resource_family = proto.Field(proto.STRING, number=2)
+
resource_group = proto.Field(proto.STRING, number=3)
+
usage_type = proto.Field(proto.STRING, number=4)
@@ -163,12 +175,16 @@ class PricingInfo(proto.Message):
1.0. Example: USD \* currency_conversion_rate = JPY
"""
- effective_time = proto.Field(proto.MESSAGE, number=1, message=timestamp.Timestamp)
+ effective_time = proto.Field(proto.MESSAGE, number=1, message=timestamp.Timestamp,)
+
summary = proto.Field(proto.STRING, number=2)
+
pricing_expression = proto.Field(
- proto.MESSAGE, number=3, message="PricingExpression"
+ proto.MESSAGE, number=3, message="PricingExpression",
)
- aggregation_info = proto.Field(proto.MESSAGE, number=4, message="AggregationInfo")
+
+ aggregation_info = proto.Field(proto.MESSAGE, number=4, message="AggregationInfo",)
+
currency_conversion_rate = proto.Field(proto.DOUBLE, number=5)
@@ -236,15 +252,22 @@ class TierRate(proto.Message):
"""
start_usage_amount = proto.Field(proto.DOUBLE, number=1)
- unit_price = proto.Field(proto.MESSAGE, number=2, message=money.Money)
+
+ unit_price = proto.Field(proto.MESSAGE, number=2, message=money.Money,)
usage_unit = proto.Field(proto.STRING, number=1)
+
usage_unit_description = proto.Field(proto.STRING, number=4)
+
base_unit = proto.Field(proto.STRING, number=5)
+
base_unit_description = proto.Field(proto.STRING, number=6)
+
base_unit_conversion_factor = proto.Field(proto.DOUBLE, number=7)
+
display_quantity = proto.Field(proto.DOUBLE, number=2)
- tiered_rates = proto.RepeatedField(proto.MESSAGE, number=3, message=TierRate)
+
+ tiered_rates = proto.RepeatedField(proto.MESSAGE, number=3, message=TierRate,)
class AggregationInfo(proto.Message):
@@ -281,8 +304,10 @@ class AggregationInterval(proto.Enum):
DAILY = 1
MONTHLY = 2
- aggregation_level = proto.Field(proto.ENUM, number=1, enum=AggregationLevel)
- aggregation_interval = proto.Field(proto.ENUM, number=2, enum=AggregationInterval)
+ aggregation_level = proto.Field(proto.ENUM, number=1, enum=AggregationLevel,)
+
+ aggregation_interval = proto.Field(proto.ENUM, number=2, enum=AggregationInterval,)
+
aggregation_count = proto.Field(proto.INT32, number=3)
@@ -300,6 +325,7 @@ class ListServicesRequest(proto.Message):
"""
page_size = proto.Field(proto.INT32, number=1)
+
page_token = proto.Field(proto.STRING, number=2)
@@ -320,7 +346,8 @@ class ListServicesResponse(proto.Message):
def raw_page(self):
return self
- services = proto.RepeatedField(proto.MESSAGE, number=1, message=Service)
+ services = proto.RepeatedField(proto.MESSAGE, number=1, message="Service",)
+
next_page_token = proto.Field(proto.STRING, number=2)
@@ -359,10 +386,15 @@ class ListSkusRequest(proto.Message):
"""
parent = proto.Field(proto.STRING, number=1)
- start_time = proto.Field(proto.MESSAGE, number=2, message=timestamp.Timestamp)
- end_time = proto.Field(proto.MESSAGE, number=3, message=timestamp.Timestamp)
+
+ start_time = proto.Field(proto.MESSAGE, number=2, message=timestamp.Timestamp,)
+
+ end_time = proto.Field(proto.MESSAGE, number=3, message=timestamp.Timestamp,)
+
currency_code = proto.Field(proto.STRING, number=4)
+
page_size = proto.Field(proto.INT32, number=5)
+
page_token = proto.Field(proto.STRING, number=6)
@@ -383,7 +415,8 @@ class ListSkusResponse(proto.Message):
def raw_page(self):
return self
- skus = proto.RepeatedField(proto.MESSAGE, number=1, message=Sku)
+ skus = proto.RepeatedField(proto.MESSAGE, number=1, message="Sku",)
+
next_page_token = proto.Field(proto.STRING, number=2)
diff --git a/packages/google-cloud-billing/noxfile.py b/packages/google-cloud-billing/noxfile.py
index 124d62e10550..3884b3b95aed 100644
--- a/packages/google-cloud-billing/noxfile.py
+++ b/packages/google-cloud-billing/noxfile.py
@@ -23,14 +23,15 @@
import nox
-BLACK_VERSION = "black==19.3b0"
+BLACK_VERSION = "black==19.10b0"
BLACK_PATHS = ["docs", "google", "tests", "noxfile.py", "setup.py"]
-if os.path.exists("samples"):
- BLACK_PATHS.append("samples")
+DEFAULT_PYTHON_VERSION = "3.8"
+SYSTEM_TEST_PYTHON_VERSIONS = ["3.8"]
+UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9"]
-@nox.session(python="3.7")
+@nox.session(python=DEFAULT_PYTHON_VERSION)
def lint(session):
"""Run linters.
@@ -38,7 +39,9 @@ def lint(session):
serious code quality issues.
"""
session.install("flake8", BLACK_VERSION)
- session.run("black", "--check", *BLACK_PATHS)
+ session.run(
+ "black", "--check", *BLACK_PATHS,
+ )
session.run("flake8", "google", "tests")
@@ -53,10 +56,12 @@ def blacken(session):
check the state of the `gcp_ubuntu_config` we use for that Kokoro run.
"""
session.install(BLACK_VERSION)
- session.run("black", *BLACK_PATHS)
+ session.run(
+ "black", *BLACK_PATHS,
+ )
-@nox.session(python="3.7")
+@nox.session(python=DEFAULT_PYTHON_VERSION)
def lint_setup_py(session):
"""Verify that setup.py is valid (including RST check)."""
session.install("docutils", "pygments")
@@ -65,7 +70,11 @@ def lint_setup_py(session):
def default(session):
# Install all test dependencies, then install this package in-place.
- session.install("mock", "pytest", "pytest-cov")
+ session.install("asyncmock", "pytest-asyncio")
+
+ session.install(
+ "mock", "pytest", "pytest-cov",
+ )
session.install("-e", ".")
# Run py.test against the unit tests.
@@ -84,17 +93,21 @@ def default(session):
)
-@nox.session(python=["3.6", "3.7", "3.8"])
+@nox.session(python=UNIT_TEST_PYTHON_VERSIONS)
def unit(session):
"""Run the unit test suite."""
default(session)
-@nox.session(python=["3.7"])
+@nox.session(python=SYSTEM_TEST_PYTHON_VERSIONS)
def system(session):
"""Run the system test suite."""
system_test_path = os.path.join("tests", "system.py")
system_test_folder_path = os.path.join("tests", "system")
+
+ # Check the value of `RUN_SYSTEM_TESTS` env var. It defaults to true.
+ if os.environ.get("RUN_SYSTEM_TESTS", "true") == "false":
+ session.skip("RUN_SYSTEM_TESTS is set to false, skipping")
# Sanity check: Only run tests if the environment variable is set.
if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", ""):
session.skip("Credentials must be set via environment variable")
@@ -110,7 +123,9 @@ def system(session):
# Install all test dependencies, then install this package into the
# virtualenv's dist-packages.
- session.install("mock", "pytest", "google-cloud-testutils")
+ session.install(
+ "mock", "pytest", "google-cloud-testutils",
+ )
session.install("-e", ".")
# Run py.test against the system tests.
@@ -120,7 +135,7 @@ def system(session):
session.run("py.test", "--quiet", system_test_folder_path, *session.posargs)
-@nox.session(python="3.7")
+@nox.session(python=DEFAULT_PYTHON_VERSION)
def cover(session):
"""Run the final coverage report.
@@ -128,12 +143,12 @@ def cover(session):
test runs (not system test runs), and then erases coverage data.
"""
session.install("coverage", "pytest-cov")
- session.run("coverage", "report", "--show-missing", "--fail-under=100")
+ session.run("coverage", "report", "--show-missing", "--fail-under=99")
session.run("coverage", "erase")
-@nox.session(python="3.7")
+@nox.session(python=DEFAULT_PYTHON_VERSION)
def docs(session):
"""Build the docs for this library."""
@@ -153,3 +168,38 @@ def docs(session):
os.path.join("docs", ""),
os.path.join("docs", "_build", "html", ""),
)
+
+
+@nox.session(python=DEFAULT_PYTHON_VERSION)
+def docfx(session):
+ """Build the docfx yaml files for this library."""
+
+ session.install("-e", ".")
+ # sphinx-docfx-yaml supports up to sphinx version 1.5.5.
+ # https://github.com/docascode/sphinx-docfx-yaml/issues/97
+ session.install("sphinx==1.5.5", "alabaster", "recommonmark", "sphinx-docfx-yaml")
+
+ shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True)
+ session.run(
+ "sphinx-build",
+ "-T", # show full traceback on exception
+ "-N", # no colors
+ "-D",
+ (
+ "extensions=sphinx.ext.autodoc,"
+ "sphinx.ext.autosummary,"
+ "docfx_yaml.extension,"
+ "sphinx.ext.intersphinx,"
+ "sphinx.ext.coverage,"
+ "sphinx.ext.napoleon,"
+ "sphinx.ext.todo,"
+ "sphinx.ext.viewcode,"
+ "recommonmark"
+ ),
+ "-b",
+ "html",
+ "-d",
+ os.path.join("docs", "_build", "doctrees", ""),
+ os.path.join("docs", ""),
+ os.path.join("docs", "_build", "html", ""),
+ )
diff --git a/packages/google-cloud-billing/scripts/decrypt-secrets.sh b/packages/google-cloud-billing/scripts/decrypt-secrets.sh
new file mode 100755
index 000000000000..21f6d2a26d90
--- /dev/null
+++ b/packages/google-cloud-billing/scripts/decrypt-secrets.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+# Copyright 2015 Google Inc. All rights reserved.
+#
+# 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.
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+ROOT=$( dirname "$DIR" )
+
+# Work from the project root.
+cd $ROOT
+
+# Prevent it from overriding files.
+# We recommend that sample authors use their own service account files and cloud project.
+# In that case, they are supposed to prepare these files by themselves.
+if [[ -f "testing/test-env.sh" ]] || \
+ [[ -f "testing/service-account.json" ]] || \
+ [[ -f "testing/client-secrets.json" ]]; then
+ echo "One or more target files exist, aborting."
+ exit 1
+fi
+
+# Use SECRET_MANAGER_PROJECT if set, fallback to cloud-devrel-kokoro-resources.
+PROJECT_ID="${SECRET_MANAGER_PROJECT:-cloud-devrel-kokoro-resources}"
+
+gcloud secrets versions access latest --secret="python-docs-samples-test-env" \
+ --project="${PROJECT_ID}" \
+ > testing/test-env.sh
+gcloud secrets versions access latest \
+ --secret="python-docs-samples-service-account" \
+ --project="${PROJECT_ID}" \
+ > testing/service-account.json
+gcloud secrets versions access latest \
+ --secret="python-docs-samples-client-secrets" \
+ --project="${PROJECT_ID}" \
+ > testing/client-secrets.json
diff --git a/packages/google-cloud-billing/scripts/readme-gen/readme_gen.py b/packages/google-cloud-billing/scripts/readme-gen/readme_gen.py
new file mode 100644
index 000000000000..d309d6e97518
--- /dev/null
+++ b/packages/google-cloud-billing/scripts/readme-gen/readme_gen.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+
+# Copyright 2016 Google Inc
+#
+# 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.
+
+"""Generates READMEs using configuration defined in yaml."""
+
+import argparse
+import io
+import os
+import subprocess
+
+import jinja2
+import yaml
+
+
+jinja_env = jinja2.Environment(
+ trim_blocks=True,
+ loader=jinja2.FileSystemLoader(
+ os.path.abspath(os.path.join(os.path.dirname(__file__), 'templates'))))
+
+README_TMPL = jinja_env.get_template('README.tmpl.rst')
+
+
+def get_help(file):
+ return subprocess.check_output(['python', file, '--help']).decode()
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('source')
+ parser.add_argument('--destination', default='README.rst')
+
+ args = parser.parse_args()
+
+ source = os.path.abspath(args.source)
+ root = os.path.dirname(source)
+ destination = os.path.join(root, args.destination)
+
+ jinja_env.globals['get_help'] = get_help
+
+ with io.open(source, 'r') as f:
+ config = yaml.load(f)
+
+ # This allows get_help to execute in the right directory.
+ os.chdir(root)
+
+ output = README_TMPL.render(config)
+
+ with io.open(destination, 'w') as f:
+ f.write(output)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/packages/google-cloud-billing/scripts/readme-gen/templates/README.tmpl.rst b/packages/google-cloud-billing/scripts/readme-gen/templates/README.tmpl.rst
new file mode 100644
index 000000000000..4fd239765b0a
--- /dev/null
+++ b/packages/google-cloud-billing/scripts/readme-gen/templates/README.tmpl.rst
@@ -0,0 +1,87 @@
+{# The following line is a lie. BUT! Once jinja2 is done with it, it will
+ become truth! #}
+.. This file is automatically generated. Do not edit this file directly.
+
+{{product.name}} Python Samples
+===============================================================================
+
+.. image:: https://gstatic.com/cloudssh/images/open-btn.png
+ :target: https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/GoogleCloudPlatform/python-docs-samples&page=editor&open_in_editor={{folder}}/README.rst
+
+
+This directory contains samples for {{product.name}}. {{product.description}}
+
+{{description}}
+
+.. _{{product.name}}: {{product.url}}
+
+{% if required_api_url %}
+To run the sample, you need to enable the API at: {{required_api_url}}
+{% endif %}
+
+{% if required_role %}
+To run the sample, you need to have `{{required_role}}` role.
+{% endif %}
+
+{{other_required_steps}}
+
+{% if setup %}
+Setup
+-------------------------------------------------------------------------------
+
+{% for section in setup %}
+
+{% include section + '.tmpl.rst' %}
+
+{% endfor %}
+{% endif %}
+
+{% if samples %}
+Samples
+-------------------------------------------------------------------------------
+
+{% for sample in samples %}
+{{sample.name}}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+{% if not sample.hide_cloudshell_button %}
+.. image:: https://gstatic.com/cloudssh/images/open-btn.png
+ :target: https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/GoogleCloudPlatform/python-docs-samples&page=editor&open_in_editor={{folder}}/{{sample.file}},{{folder}}/README.rst
+{% endif %}
+
+
+{{sample.description}}
+
+To run this sample:
+
+.. code-block:: bash
+
+ $ python {{sample.file}}
+{% if sample.show_help %}
+
+ {{get_help(sample.file)|indent}}
+{% endif %}
+
+
+{% endfor %}
+{% endif %}
+
+{% if cloud_client_library %}
+
+The client library
+-------------------------------------------------------------------------------
+
+This sample uses the `Google Cloud Client Library for Python`_.
+You can read the documentation for more details on API usage and use GitHub
+to `browse the source`_ and `report issues`_.
+
+.. _Google Cloud Client Library for Python:
+ https://googlecloudplatform.github.io/google-cloud-python/
+.. _browse the source:
+ https://github.com/GoogleCloudPlatform/google-cloud-python
+.. _report issues:
+ https://github.com/GoogleCloudPlatform/google-cloud-python/issues
+
+{% endif %}
+
+.. _Google Cloud SDK: https://cloud.google.com/sdk/
\ No newline at end of file
diff --git a/packages/google-cloud-billing/scripts/readme-gen/templates/auth.tmpl.rst b/packages/google-cloud-billing/scripts/readme-gen/templates/auth.tmpl.rst
new file mode 100644
index 000000000000..1446b94a5e3a
--- /dev/null
+++ b/packages/google-cloud-billing/scripts/readme-gen/templates/auth.tmpl.rst
@@ -0,0 +1,9 @@
+Authentication
+++++++++++++++
+
+This sample requires you to have authentication setup. Refer to the
+`Authentication Getting Started Guide`_ for instructions on setting up
+credentials for applications.
+
+.. _Authentication Getting Started Guide:
+ https://cloud.google.com/docs/authentication/getting-started
diff --git a/packages/google-cloud-billing/scripts/readme-gen/templates/auth_api_key.tmpl.rst b/packages/google-cloud-billing/scripts/readme-gen/templates/auth_api_key.tmpl.rst
new file mode 100644
index 000000000000..11957ce2714a
--- /dev/null
+++ b/packages/google-cloud-billing/scripts/readme-gen/templates/auth_api_key.tmpl.rst
@@ -0,0 +1,14 @@
+Authentication
+++++++++++++++
+
+Authentication for this service is done via an `API Key`_. To obtain an API
+Key:
+
+1. Open the `Cloud Platform Console`_
+2. Make sure that billing is enabled for your project.
+3. From the **Credentials** page, create a new **API Key** or use an existing
+ one for your project.
+
+.. _API Key:
+ https://developers.google.com/api-client-library/python/guide/aaa_apikeys
+.. _Cloud Console: https://console.cloud.google.com/project?_
diff --git a/packages/google-cloud-billing/scripts/readme-gen/templates/install_deps.tmpl.rst b/packages/google-cloud-billing/scripts/readme-gen/templates/install_deps.tmpl.rst
new file mode 100644
index 000000000000..a0406dba8c84
--- /dev/null
+++ b/packages/google-cloud-billing/scripts/readme-gen/templates/install_deps.tmpl.rst
@@ -0,0 +1,29 @@
+Install Dependencies
+++++++++++++++++++++
+
+#. Clone python-docs-samples and change directory to the sample directory you want to use.
+
+ .. code-block:: bash
+
+ $ git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
+
+#. Install `pip`_ and `virtualenv`_ if you do not already have them. You may want to refer to the `Python Development Environment Setup Guide`_ for Google Cloud Platform for instructions.
+
+ .. _Python Development Environment Setup Guide:
+ https://cloud.google.com/python/setup
+
+#. Create a virtualenv. Samples are compatible with Python 2.7 and 3.4+.
+
+ .. code-block:: bash
+
+ $ virtualenv env
+ $ source env/bin/activate
+
+#. Install the dependencies needed to run the samples.
+
+ .. code-block:: bash
+
+ $ pip install -r requirements.txt
+
+.. _pip: https://pip.pypa.io/
+.. _virtualenv: https://virtualenv.pypa.io/
diff --git a/packages/google-cloud-billing/scripts/readme-gen/templates/install_portaudio.tmpl.rst b/packages/google-cloud-billing/scripts/readme-gen/templates/install_portaudio.tmpl.rst
new file mode 100644
index 000000000000..5ea33d18c00c
--- /dev/null
+++ b/packages/google-cloud-billing/scripts/readme-gen/templates/install_portaudio.tmpl.rst
@@ -0,0 +1,35 @@
+Install PortAudio
++++++++++++++++++
+
+Install `PortAudio`_. This is required by the `PyAudio`_ library to stream
+audio from your computer's microphone. PyAudio depends on PortAudio for cross-platform compatibility, and is installed differently depending on the
+platform.
+
+* For Mac OS X, you can use `Homebrew`_::
+
+ brew install portaudio
+
+ **Note**: if you encounter an error when running `pip install` that indicates
+ it can't find `portaudio.h`, try running `pip install` with the following
+ flags::
+
+ pip install --global-option='build_ext' \
+ --global-option='-I/usr/local/include' \
+ --global-option='-L/usr/local/lib' \
+ pyaudio
+
+* For Debian / Ubuntu Linux::
+
+ apt-get install portaudio19-dev python-all-dev
+
+* Windows may work without having to install PortAudio explicitly (it will get
+ installed with PyAudio).
+
+For more details, see the `PyAudio installation`_ page.
+
+
+.. _PyAudio: https://people.csail.mit.edu/hubert/pyaudio/
+.. _PortAudio: http://www.portaudio.com/
+.. _PyAudio installation:
+ https://people.csail.mit.edu/hubert/pyaudio/#downloads
+.. _Homebrew: http://brew.sh
diff --git a/packages/google-cloud-billing/setup.py b/packages/google-cloud-billing/setup.py
index ea168fedfe7d..71db53d4cd73 100644
--- a/packages/google-cloud-billing/setup.py
+++ b/packages/google-cloud-billing/setup.py
@@ -40,9 +40,9 @@
platforms="Posix; MacOS X; Windows",
include_package_data=True,
install_requires=(
- "google-api-core[grpc] >= 1.17.0, < 2.0.0dev",
+ "google-api-core[grpc] >= 1.22.0, < 2.0.0dev",
"grpc-google-iam-v1",
- "proto-plus >= 0.4.0",
+ "proto-plus >= 1.10.0",
),
python_requires=">=3.6",
setup_requires=["libcst >= 0.2.5"],
diff --git a/packages/google-cloud-billing/synth.metadata b/packages/google-cloud-billing/synth.metadata
index 0857e092fe4d..59b0ee0e33b0 100644
--- a/packages/google-cloud-billing/synth.metadata
+++ b/packages/google-cloud-billing/synth.metadata
@@ -3,34 +3,22 @@
{
"git": {
"name": ".",
- "remote": "https://github.com/googleapis/python-billing.git",
- "sha": "fef622a0dddf005d8af329ee001ec41f03850427"
+ "remote": "git@github.com:googleapis/python-billing",
+ "sha": "a9da72a796559ba13b95104cb719ba04300375ac"
}
},
{
"git": {
- "name": "googleapis",
- "remote": "https://github.com/googleapis/googleapis.git",
- "sha": "eafa840ceec23b44a5c21670288107c661252711",
- "internalRef": "313488995"
+ "name": "synthtool",
+ "remote": "https://github.com/googleapis/synthtool.git",
+ "sha": "d5fc0bcf9ea9789c5b0e3154a9e3b29e5cea6116"
}
},
{
"git": {
"name": "synthtool",
"remote": "https://github.com/googleapis/synthtool.git",
- "sha": "71b8a272549c06b5768d00fa48d3ae990e871bec"
- }
- }
- ],
- "destinations": [
- {
- "client": {
- "source": "googleapis",
- "apiName": "billing",
- "apiVersion": "v1",
- "language": "python",
- "generator": "gapic-generator-python"
+ "sha": "d5fc0bcf9ea9789c5b0e3154a9e3b29e5cea6116"
}
}
]
diff --git a/packages/google-cloud-billing/synth.py b/packages/google-cloud-billing/synth.py
index 38b992e0b060..0d66b85c78fa 100644
--- a/packages/google-cloud-billing/synth.py
+++ b/packages/google-cloud-billing/synth.py
@@ -19,38 +19,28 @@
import synthtool.gcp as gcp
from synthtool.languages import python
-gapic = gcp.GAPICMicrogenerator()
+gapic = gcp.GAPICBazel()
common = gcp.CommonTemplates()
# ----------------------------------------------------------------------------
# Generate budgets GAPIC layer
# ----------------------------------------------------------------------------
library = gapic.py_library(
- "billing", "v1"
+ service="billing",
+ version="v1",
+ bazel_target="//google/cloud/billing/v1:billing-v1-py",
)
-excludes = ["setup.py", "docs/index.rst"]
+excludes = ["setup.py", "docs/index.rst", "scripts/fixup_biling_v1_keywords.py"]
s.move(library, excludes=excludes)
-# correct license headers
-python.fix_pb2_headers()
-python.fix_pb2_grpc_headers()
-
# ----------------------------------------------------------------------------
# Add templated files
# ----------------------------------------------------------------------------
-templated_files = common.py_library(cov_level=100)
+templated_files = common.py_library(cov_level=99, microgenerator=True)
s.move(templated_files, excludes=[".coveragerc"]) # the microgenerator has a good coveragerc file
s.replace(".gitignore", "bigquery/docs/generated", "htmlcov") # temporary hack to ignore htmlcov
-# Remove 2.7 and 3.5 tests from noxfile.py
-s.replace("noxfile.py", '''\["2\.7", ''', '[')
-s.replace("noxfile.py", '''"3.5", ''', '')
-
-# Expand flake errors permitted to accomodate the Microgenerator
-# TODO: remove extra error codes once issues below are resolved
-# https://github.com/googleapis/gapic-generator-python/issues/425
-s.replace(".flake8", "(ignore = .*)", "\g<1>, F401, F841")
s.shell.run(["nox", "-s", "blacken"], hide_output=False)
diff --git a/packages/google-cloud-billing/testing/.gitignore b/packages/google-cloud-billing/testing/.gitignore
new file mode 100644
index 000000000000..b05fbd630881
--- /dev/null
+++ b/packages/google-cloud-billing/testing/.gitignore
@@ -0,0 +1,3 @@
+test-env.sh
+service-account.json
+client-secrets.json
\ No newline at end of file
diff --git a/packages/google-cloud-billing/tests/unit/billing_v1/test_cloud_billing.py b/packages/google-cloud-billing/tests/unit/billing_v1/test_cloud_billing.py
deleted file mode 100644
index e87b45499f10..000000000000
--- a/packages/google-cloud-billing/tests/unit/billing_v1/test_cloud_billing.py
+++ /dev/null
@@ -1,1264 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright 2020 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-from unittest import mock
-
-import grpc
-import math
-import pytest
-
-from google import auth
-from google.api_core import client_options
-from google.api_core import grpc_helpers
-from google.auth import credentials
-from google.cloud.billing_v1.services.cloud_billing import CloudBillingClient
-from google.cloud.billing_v1.services.cloud_billing import pagers
-from google.cloud.billing_v1.services.cloud_billing import transports
-from google.cloud.billing_v1.types import cloud_billing
-from google.iam.v1 import iam_policy_pb2 as iam_policy # type: ignore
-from google.iam.v1 import options_pb2 as options # type: ignore
-from google.iam.v1 import policy_pb2 as policy # type: ignore
-from google.oauth2 import service_account
-from google.protobuf import field_mask_pb2 as field_mask # type: ignore
-from google.type import expr_pb2 as expr # type: ignore
-
-
-def client_cert_source_callback():
- return b"cert bytes", b"key bytes"
-
-
-def test__get_default_mtls_endpoint():
- api_endpoint = "example.googleapis.com"
- api_mtls_endpoint = "example.mtls.googleapis.com"
- sandbox_endpoint = "example.sandbox.googleapis.com"
- sandbox_mtls_endpoint = "example.mtls.sandbox.googleapis.com"
- non_googleapi = "api.example.com"
-
- assert CloudBillingClient._get_default_mtls_endpoint(None) is None
- assert (
- CloudBillingClient._get_default_mtls_endpoint(api_endpoint) == api_mtls_endpoint
- )
- assert (
- CloudBillingClient._get_default_mtls_endpoint(api_mtls_endpoint)
- == api_mtls_endpoint
- )
- assert (
- CloudBillingClient._get_default_mtls_endpoint(sandbox_endpoint)
- == sandbox_mtls_endpoint
- )
- assert (
- CloudBillingClient._get_default_mtls_endpoint(sandbox_mtls_endpoint)
- == sandbox_mtls_endpoint
- )
- assert CloudBillingClient._get_default_mtls_endpoint(non_googleapi) == non_googleapi
-
-
-def test_cloud_billing_client_from_service_account_file():
- creds = credentials.AnonymousCredentials()
- with mock.patch.object(
- service_account.Credentials, "from_service_account_file"
- ) as factory:
- factory.return_value = creds
- client = CloudBillingClient.from_service_account_file("dummy/file/path.json")
- assert client._transport._credentials == creds
-
- client = CloudBillingClient.from_service_account_json("dummy/file/path.json")
- assert client._transport._credentials == creds
-
- assert client._transport._host == "cloudbilling.googleapis.com:443"
-
-
-def test_cloud_billing_client_client_options():
- # Check that if channel is provided we won't create a new one.
- with mock.patch(
- "google.cloud.billing_v1.services.cloud_billing.CloudBillingClient.get_transport_class"
- ) as gtc:
- transport = transports.CloudBillingGrpcTransport(
- credentials=credentials.AnonymousCredentials()
- )
- client = CloudBillingClient(transport=transport)
- gtc.assert_not_called()
-
- # Check mTLS is not triggered with empty client options.
- options = client_options.ClientOptions()
- with mock.patch(
- "google.cloud.billing_v1.services.cloud_billing.CloudBillingClient.get_transport_class"
- ) as gtc:
- transport = gtc.return_value = mock.MagicMock()
- client = CloudBillingClient(client_options=options)
- transport.assert_called_once_with(
- credentials=None, host=client.DEFAULT_ENDPOINT
- )
-
- # Check mTLS is not triggered if api_endpoint is provided but
- # client_cert_source is None.
- options = client_options.ClientOptions(api_endpoint="squid.clam.whelk")
- with mock.patch(
- "google.cloud.billing_v1.services.cloud_billing.transports.CloudBillingGrpcTransport.__init__"
- ) as grpc_transport:
- grpc_transport.return_value = None
- client = CloudBillingClient(client_options=options)
- grpc_transport.assert_called_once_with(
- api_mtls_endpoint=None,
- client_cert_source=None,
- credentials=None,
- host="squid.clam.whelk",
- )
-
- # Check mTLS is triggered if client_cert_source is provided.
- options = client_options.ClientOptions(
- client_cert_source=client_cert_source_callback
- )
- with mock.patch(
- "google.cloud.billing_v1.services.cloud_billing.transports.CloudBillingGrpcTransport.__init__"
- ) as grpc_transport:
- grpc_transport.return_value = None
- client = CloudBillingClient(client_options=options)
- grpc_transport.assert_called_once_with(
- api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT,
- client_cert_source=client_cert_source_callback,
- credentials=None,
- host=client.DEFAULT_ENDPOINT,
- )
-
- # Check mTLS is triggered if api_endpoint and client_cert_source are provided.
- options = client_options.ClientOptions(
- api_endpoint="squid.clam.whelk", client_cert_source=client_cert_source_callback
- )
- with mock.patch(
- "google.cloud.billing_v1.services.cloud_billing.transports.CloudBillingGrpcTransport.__init__"
- ) as grpc_transport:
- grpc_transport.return_value = None
- client = CloudBillingClient(client_options=options)
- grpc_transport.assert_called_once_with(
- api_mtls_endpoint="squid.clam.whelk",
- client_cert_source=client_cert_source_callback,
- credentials=None,
- host="squid.clam.whelk",
- )
-
-
-def test_cloud_billing_client_client_options_from_dict():
- with mock.patch(
- "google.cloud.billing_v1.services.cloud_billing.transports.CloudBillingGrpcTransport.__init__"
- ) as grpc_transport:
- grpc_transport.return_value = None
- client = CloudBillingClient(client_options={"api_endpoint": "squid.clam.whelk"})
- grpc_transport.assert_called_once_with(
- api_mtls_endpoint=None,
- client_cert_source=None,
- credentials=None,
- host="squid.clam.whelk",
- )
-
-
-def test_get_billing_account(transport: str = "grpc"):
- client = CloudBillingClient(
- credentials=credentials.AnonymousCredentials(), transport=transport
- )
-
- # Everything is optional in proto3 as far as the runtime is concerned,
- # and we are mocking out the actual API, so just send an empty request.
- request = cloud_billing.GetBillingAccountRequest()
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.get_billing_account), "__call__"
- ) as call:
- # Designate an appropriate return value for the call.
- call.return_value = cloud_billing.BillingAccount(
- name="name_value",
- open=True,
- display_name="display_name_value",
- master_billing_account="master_billing_account_value",
- )
-
- response = client.get_billing_account(request)
-
- # Establish that the underlying gRPC stub method was called.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
-
- assert args[0] == request
-
- # Establish that the response is the type that we expect.
- assert isinstance(response, cloud_billing.BillingAccount)
- assert response.name == "name_value"
-
- assert response.open is True
- assert response.display_name == "display_name_value"
- assert response.master_billing_account == "master_billing_account_value"
-
-
-def test_get_billing_account_field_headers():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Any value that is part of the HTTP/1.1 URI should be sent as
- # a field header. Set these to a non-empty value.
- request = cloud_billing.GetBillingAccountRequest(name="name/value")
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.get_billing_account), "__call__"
- ) as call:
- call.return_value = cloud_billing.BillingAccount()
- client.get_billing_account(request)
-
- # Establish that the underlying gRPC stub method was called.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
- assert args[0] == request
-
- # Establish that the field header was sent.
- _, _, kw = call.mock_calls[0]
- assert ("x-goog-request-params", "name=name/value") in kw["metadata"]
-
-
-def test_get_billing_account_flattened():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.get_billing_account), "__call__"
- ) as call:
- # Designate an appropriate return value for the call.
- call.return_value = cloud_billing.BillingAccount()
-
- # Call the method with a truthy value for each flattened field,
- # using the keyword arguments to the method.
- response = client.get_billing_account(name="name_value")
-
- # Establish that the underlying call was made with the expected
- # request object values.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
- assert args[0].name == "name_value"
-
-
-def test_get_billing_account_flattened_error():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Attempting to call a method with both a request object and flattened
- # fields is an error.
- with pytest.raises(ValueError):
- client.get_billing_account(
- cloud_billing.GetBillingAccountRequest(), name="name_value"
- )
-
-
-def test_list_billing_accounts(transport: str = "grpc"):
- client = CloudBillingClient(
- credentials=credentials.AnonymousCredentials(), transport=transport
- )
-
- # Everything is optional in proto3 as far as the runtime is concerned,
- # and we are mocking out the actual API, so just send an empty request.
- request = cloud_billing.ListBillingAccountsRequest()
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.list_billing_accounts), "__call__"
- ) as call:
- # Designate an appropriate return value for the call.
- call.return_value = cloud_billing.ListBillingAccountsResponse(
- next_page_token="next_page_token_value"
- )
-
- response = client.list_billing_accounts(request)
-
- # Establish that the underlying gRPC stub method was called.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
-
- assert args[0] == request
-
- # Establish that the response is the type that we expect.
- assert isinstance(response, pagers.ListBillingAccountsPager)
- assert response.next_page_token == "next_page_token_value"
-
-
-def test_list_billing_accounts_pager():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials)
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.list_billing_accounts), "__call__"
- ) as call:
- # Set the response to a series of pages.
- call.side_effect = (
- cloud_billing.ListBillingAccountsResponse(
- billing_accounts=[
- cloud_billing.BillingAccount(),
- cloud_billing.BillingAccount(),
- cloud_billing.BillingAccount(),
- ],
- next_page_token="abc",
- ),
- cloud_billing.ListBillingAccountsResponse(
- billing_accounts=[], next_page_token="def"
- ),
- cloud_billing.ListBillingAccountsResponse(
- billing_accounts=[cloud_billing.BillingAccount()], next_page_token="ghi"
- ),
- cloud_billing.ListBillingAccountsResponse(
- billing_accounts=[
- cloud_billing.BillingAccount(),
- cloud_billing.BillingAccount(),
- ]
- ),
- RuntimeError,
- )
- results = [i for i in client.list_billing_accounts(request={})]
- assert len(results) == 6
- assert all(isinstance(i, cloud_billing.BillingAccount) for i in results)
-
-
-def test_list_billing_accounts_pages():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials)
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.list_billing_accounts), "__call__"
- ) as call:
- # Set the response to a series of pages.
- call.side_effect = (
- cloud_billing.ListBillingAccountsResponse(
- billing_accounts=[
- cloud_billing.BillingAccount(),
- cloud_billing.BillingAccount(),
- cloud_billing.BillingAccount(),
- ],
- next_page_token="abc",
- ),
- cloud_billing.ListBillingAccountsResponse(
- billing_accounts=[], next_page_token="def"
- ),
- cloud_billing.ListBillingAccountsResponse(
- billing_accounts=[cloud_billing.BillingAccount()], next_page_token="ghi"
- ),
- cloud_billing.ListBillingAccountsResponse(
- billing_accounts=[
- cloud_billing.BillingAccount(),
- cloud_billing.BillingAccount(),
- ]
- ),
- RuntimeError,
- )
- pages = list(client.list_billing_accounts(request={}).pages)
- for page, token in zip(pages, ["abc", "def", "ghi", ""]):
- assert page.raw_page.next_page_token == token
-
-
-def test_update_billing_account(transport: str = "grpc"):
- client = CloudBillingClient(
- credentials=credentials.AnonymousCredentials(), transport=transport
- )
-
- # Everything is optional in proto3 as far as the runtime is concerned,
- # and we are mocking out the actual API, so just send an empty request.
- request = cloud_billing.UpdateBillingAccountRequest()
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.update_billing_account), "__call__"
- ) as call:
- # Designate an appropriate return value for the call.
- call.return_value = cloud_billing.BillingAccount(
- name="name_value",
- open=True,
- display_name="display_name_value",
- master_billing_account="master_billing_account_value",
- )
-
- response = client.update_billing_account(request)
-
- # Establish that the underlying gRPC stub method was called.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
-
- assert args[0] == request
-
- # Establish that the response is the type that we expect.
- assert isinstance(response, cloud_billing.BillingAccount)
- assert response.name == "name_value"
-
- assert response.open is True
- assert response.display_name == "display_name_value"
- assert response.master_billing_account == "master_billing_account_value"
-
-
-def test_update_billing_account_flattened():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.update_billing_account), "__call__"
- ) as call:
- # Designate an appropriate return value for the call.
- call.return_value = cloud_billing.BillingAccount()
-
- # Call the method with a truthy value for each flattened field,
- # using the keyword arguments to the method.
- response = client.update_billing_account(
- name="name_value", account=cloud_billing.BillingAccount(name="name_value")
- )
-
- # Establish that the underlying call was made with the expected
- # request object values.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
- assert args[0].name == "name_value"
- assert args[0].account == cloud_billing.BillingAccount(name="name_value")
-
-
-def test_update_billing_account_flattened_error():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Attempting to call a method with both a request object and flattened
- # fields is an error.
- with pytest.raises(ValueError):
- client.update_billing_account(
- cloud_billing.UpdateBillingAccountRequest(),
- name="name_value",
- account=cloud_billing.BillingAccount(name="name_value"),
- )
-
-
-def test_create_billing_account(transport: str = "grpc"):
- client = CloudBillingClient(
- credentials=credentials.AnonymousCredentials(), transport=transport
- )
-
- # Everything is optional in proto3 as far as the runtime is concerned,
- # and we are mocking out the actual API, so just send an empty request.
- request = cloud_billing.CreateBillingAccountRequest()
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.create_billing_account), "__call__"
- ) as call:
- # Designate an appropriate return value for the call.
- call.return_value = cloud_billing.BillingAccount(
- name="name_value",
- open=True,
- display_name="display_name_value",
- master_billing_account="master_billing_account_value",
- )
-
- response = client.create_billing_account(request)
-
- # Establish that the underlying gRPC stub method was called.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
-
- assert args[0] == request
-
- # Establish that the response is the type that we expect.
- assert isinstance(response, cloud_billing.BillingAccount)
- assert response.name == "name_value"
-
- assert response.open is True
- assert response.display_name == "display_name_value"
- assert response.master_billing_account == "master_billing_account_value"
-
-
-def test_create_billing_account_flattened():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.create_billing_account), "__call__"
- ) as call:
- # Designate an appropriate return value for the call.
- call.return_value = cloud_billing.BillingAccount()
-
- # Call the method with a truthy value for each flattened field,
- # using the keyword arguments to the method.
- response = client.create_billing_account(
- billing_account=cloud_billing.BillingAccount(name="name_value")
- )
-
- # Establish that the underlying call was made with the expected
- # request object values.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
- assert args[0].billing_account == cloud_billing.BillingAccount(
- name="name_value"
- )
-
-
-def test_create_billing_account_flattened_error():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Attempting to call a method with both a request object and flattened
- # fields is an error.
- with pytest.raises(ValueError):
- client.create_billing_account(
- cloud_billing.CreateBillingAccountRequest(),
- billing_account=cloud_billing.BillingAccount(name="name_value"),
- )
-
-
-def test_list_project_billing_info(transport: str = "grpc"):
- client = CloudBillingClient(
- credentials=credentials.AnonymousCredentials(), transport=transport
- )
-
- # Everything is optional in proto3 as far as the runtime is concerned,
- # and we are mocking out the actual API, so just send an empty request.
- request = cloud_billing.ListProjectBillingInfoRequest()
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.list_project_billing_info), "__call__"
- ) as call:
- # Designate an appropriate return value for the call.
- call.return_value = cloud_billing.ListProjectBillingInfoResponse(
- next_page_token="next_page_token_value"
- )
-
- response = client.list_project_billing_info(request)
-
- # Establish that the underlying gRPC stub method was called.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
-
- assert args[0] == request
-
- # Establish that the response is the type that we expect.
- assert isinstance(response, pagers.ListProjectBillingInfoPager)
- assert response.next_page_token == "next_page_token_value"
-
-
-def test_list_project_billing_info_field_headers():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Any value that is part of the HTTP/1.1 URI should be sent as
- # a field header. Set these to a non-empty value.
- request = cloud_billing.ListProjectBillingInfoRequest(name="name/value")
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.list_project_billing_info), "__call__"
- ) as call:
- call.return_value = cloud_billing.ListProjectBillingInfoResponse()
- client.list_project_billing_info(request)
-
- # Establish that the underlying gRPC stub method was called.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
- assert args[0] == request
-
- # Establish that the field header was sent.
- _, _, kw = call.mock_calls[0]
- assert ("x-goog-request-params", "name=name/value") in kw["metadata"]
-
-
-def test_list_project_billing_info_flattened():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.list_project_billing_info), "__call__"
- ) as call:
- # Designate an appropriate return value for the call.
- call.return_value = cloud_billing.ListProjectBillingInfoResponse()
-
- # Call the method with a truthy value for each flattened field,
- # using the keyword arguments to the method.
- response = client.list_project_billing_info(name="name_value")
-
- # Establish that the underlying call was made with the expected
- # request object values.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
- assert args[0].name == "name_value"
-
-
-def test_list_project_billing_info_flattened_error():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Attempting to call a method with both a request object and flattened
- # fields is an error.
- with pytest.raises(ValueError):
- client.list_project_billing_info(
- cloud_billing.ListProjectBillingInfoRequest(), name="name_value"
- )
-
-
-def test_list_project_billing_info_pager():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials)
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.list_project_billing_info), "__call__"
- ) as call:
- # Set the response to a series of pages.
- call.side_effect = (
- cloud_billing.ListProjectBillingInfoResponse(
- project_billing_info=[
- cloud_billing.ProjectBillingInfo(),
- cloud_billing.ProjectBillingInfo(),
- cloud_billing.ProjectBillingInfo(),
- ],
- next_page_token="abc",
- ),
- cloud_billing.ListProjectBillingInfoResponse(
- project_billing_info=[], next_page_token="def"
- ),
- cloud_billing.ListProjectBillingInfoResponse(
- project_billing_info=[cloud_billing.ProjectBillingInfo()],
- next_page_token="ghi",
- ),
- cloud_billing.ListProjectBillingInfoResponse(
- project_billing_info=[
- cloud_billing.ProjectBillingInfo(),
- cloud_billing.ProjectBillingInfo(),
- ]
- ),
- RuntimeError,
- )
- results = [i for i in client.list_project_billing_info(request={})]
- assert len(results) == 6
- assert all(isinstance(i, cloud_billing.ProjectBillingInfo) for i in results)
-
-
-def test_list_project_billing_info_pages():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials)
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.list_project_billing_info), "__call__"
- ) as call:
- # Set the response to a series of pages.
- call.side_effect = (
- cloud_billing.ListProjectBillingInfoResponse(
- project_billing_info=[
- cloud_billing.ProjectBillingInfo(),
- cloud_billing.ProjectBillingInfo(),
- cloud_billing.ProjectBillingInfo(),
- ],
- next_page_token="abc",
- ),
- cloud_billing.ListProjectBillingInfoResponse(
- project_billing_info=[], next_page_token="def"
- ),
- cloud_billing.ListProjectBillingInfoResponse(
- project_billing_info=[cloud_billing.ProjectBillingInfo()],
- next_page_token="ghi",
- ),
- cloud_billing.ListProjectBillingInfoResponse(
- project_billing_info=[
- cloud_billing.ProjectBillingInfo(),
- cloud_billing.ProjectBillingInfo(),
- ]
- ),
- RuntimeError,
- )
- pages = list(client.list_project_billing_info(request={}).pages)
- for page, token in zip(pages, ["abc", "def", "ghi", ""]):
- assert page.raw_page.next_page_token == token
-
-
-def test_get_project_billing_info(transport: str = "grpc"):
- client = CloudBillingClient(
- credentials=credentials.AnonymousCredentials(), transport=transport
- )
-
- # Everything is optional in proto3 as far as the runtime is concerned,
- # and we are mocking out the actual API, so just send an empty request.
- request = cloud_billing.GetProjectBillingInfoRequest()
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.get_project_billing_info), "__call__"
- ) as call:
- # Designate an appropriate return value for the call.
- call.return_value = cloud_billing.ProjectBillingInfo(
- name="name_value",
- project_id="project_id_value",
- billing_account_name="billing_account_name_value",
- billing_enabled=True,
- )
-
- response = client.get_project_billing_info(request)
-
- # Establish that the underlying gRPC stub method was called.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
-
- assert args[0] == request
-
- # Establish that the response is the type that we expect.
- assert isinstance(response, cloud_billing.ProjectBillingInfo)
- assert response.name == "name_value"
- assert response.project_id == "project_id_value"
- assert response.billing_account_name == "billing_account_name_value"
-
- assert response.billing_enabled is True
-
-
-def test_get_project_billing_info_field_headers():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Any value that is part of the HTTP/1.1 URI should be sent as
- # a field header. Set these to a non-empty value.
- request = cloud_billing.GetProjectBillingInfoRequest(name="name/value")
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.get_project_billing_info), "__call__"
- ) as call:
- call.return_value = cloud_billing.ProjectBillingInfo()
- client.get_project_billing_info(request)
-
- # Establish that the underlying gRPC stub method was called.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
- assert args[0] == request
-
- # Establish that the field header was sent.
- _, _, kw = call.mock_calls[0]
- assert ("x-goog-request-params", "name=name/value") in kw["metadata"]
-
-
-def test_get_project_billing_info_flattened():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.get_project_billing_info), "__call__"
- ) as call:
- # Designate an appropriate return value for the call.
- call.return_value = cloud_billing.ProjectBillingInfo()
-
- # Call the method with a truthy value for each flattened field,
- # using the keyword arguments to the method.
- response = client.get_project_billing_info(name="name_value")
-
- # Establish that the underlying call was made with the expected
- # request object values.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
- assert args[0].name == "name_value"
-
-
-def test_get_project_billing_info_flattened_error():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Attempting to call a method with both a request object and flattened
- # fields is an error.
- with pytest.raises(ValueError):
- client.get_project_billing_info(
- cloud_billing.GetProjectBillingInfoRequest(), name="name_value"
- )
-
-
-def test_update_project_billing_info(transport: str = "grpc"):
- client = CloudBillingClient(
- credentials=credentials.AnonymousCredentials(), transport=transport
- )
-
- # Everything is optional in proto3 as far as the runtime is concerned,
- # and we are mocking out the actual API, so just send an empty request.
- request = cloud_billing.UpdateProjectBillingInfoRequest()
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.update_project_billing_info), "__call__"
- ) as call:
- # Designate an appropriate return value for the call.
- call.return_value = cloud_billing.ProjectBillingInfo(
- name="name_value",
- project_id="project_id_value",
- billing_account_name="billing_account_name_value",
- billing_enabled=True,
- )
-
- response = client.update_project_billing_info(request)
-
- # Establish that the underlying gRPC stub method was called.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
-
- assert args[0] == request
-
- # Establish that the response is the type that we expect.
- assert isinstance(response, cloud_billing.ProjectBillingInfo)
- assert response.name == "name_value"
- assert response.project_id == "project_id_value"
- assert response.billing_account_name == "billing_account_name_value"
-
- assert response.billing_enabled is True
-
-
-def test_update_project_billing_info_flattened():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.update_project_billing_info), "__call__"
- ) as call:
- # Designate an appropriate return value for the call.
- call.return_value = cloud_billing.ProjectBillingInfo()
-
- # Call the method with a truthy value for each flattened field,
- # using the keyword arguments to the method.
- response = client.update_project_billing_info(
- name="name_value",
- project_billing_info=cloud_billing.ProjectBillingInfo(name="name_value"),
- )
-
- # Establish that the underlying call was made with the expected
- # request object values.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
- assert args[0].name == "name_value"
- assert args[0].project_billing_info == cloud_billing.ProjectBillingInfo(
- name="name_value"
- )
-
-
-def test_update_project_billing_info_flattened_error():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Attempting to call a method with both a request object and flattened
- # fields is an error.
- with pytest.raises(ValueError):
- client.update_project_billing_info(
- cloud_billing.UpdateProjectBillingInfoRequest(),
- name="name_value",
- project_billing_info=cloud_billing.ProjectBillingInfo(name="name_value"),
- )
-
-
-def test_get_iam_policy(transport: str = "grpc"):
- client = CloudBillingClient(
- credentials=credentials.AnonymousCredentials(), transport=transport
- )
-
- # Everything is optional in proto3 as far as the runtime is concerned,
- # and we are mocking out the actual API, so just send an empty request.
- request = iam_policy.GetIamPolicyRequest()
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(type(client._transport.get_iam_policy), "__call__") as call:
- # Designate an appropriate return value for the call.
- call.return_value = policy.Policy(version=774, etag=b"etag_blob")
-
- response = client.get_iam_policy(request)
-
- # Establish that the underlying gRPC stub method was called.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
-
- assert args[0] == request
-
- # Establish that the response is the type that we expect.
- assert isinstance(response, policy.Policy)
- assert response.version == 774
- assert response.etag == b"etag_blob"
-
-
-def test_get_iam_policy_field_headers():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Any value that is part of the HTTP/1.1 URI should be sent as
- # a field header. Set these to a non-empty value.
- request = iam_policy.GetIamPolicyRequest(resource="resource/value")
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(type(client._transport.get_iam_policy), "__call__") as call:
- call.return_value = policy.Policy()
- client.get_iam_policy(request)
-
- # Establish that the underlying gRPC stub method was called.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
- assert args[0] == request
-
- # Establish that the field header was sent.
- _, _, kw = call.mock_calls[0]
- assert ("x-goog-request-params", "resource=resource/value") in kw["metadata"]
-
-
-def test_get_iam_policy_from_dict():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(type(client._transport.get_iam_policy), "__call__") as call:
- # Designate an appropriate return value for the call.
- call.return_value = policy.Policy()
-
- response = client.get_iam_policy(
- request={
- "resource": "resource_value",
- "options": options.GetPolicyOptions(requested_policy_version=2598),
- }
- )
- call.assert_called()
-
-
-def test_get_iam_policy_flattened():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(type(client._transport.get_iam_policy), "__call__") as call:
- # Designate an appropriate return value for the call.
- call.return_value = policy.Policy()
-
- # Call the method with a truthy value for each flattened field,
- # using the keyword arguments to the method.
- response = client.get_iam_policy(resource="resource_value")
-
- # Establish that the underlying call was made with the expected
- # request object values.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
- assert args[0].resource == "resource_value"
-
-
-def test_get_iam_policy_flattened_error():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Attempting to call a method with both a request object and flattened
- # fields is an error.
- with pytest.raises(ValueError):
- client.get_iam_policy(
- iam_policy.GetIamPolicyRequest(), resource="resource_value"
- )
-
-
-def test_set_iam_policy(transport: str = "grpc"):
- client = CloudBillingClient(
- credentials=credentials.AnonymousCredentials(), transport=transport
- )
-
- # Everything is optional in proto3 as far as the runtime is concerned,
- # and we are mocking out the actual API, so just send an empty request.
- request = iam_policy.SetIamPolicyRequest()
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(type(client._transport.set_iam_policy), "__call__") as call:
- # Designate an appropriate return value for the call.
- call.return_value = policy.Policy(version=774, etag=b"etag_blob")
-
- response = client.set_iam_policy(request)
-
- # Establish that the underlying gRPC stub method was called.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
-
- assert args[0] == request
-
- # Establish that the response is the type that we expect.
- assert isinstance(response, policy.Policy)
- assert response.version == 774
- assert response.etag == b"etag_blob"
-
-
-def test_set_iam_policy_from_dict():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(type(client._transport.set_iam_policy), "__call__") as call:
- # Designate an appropriate return value for the call.
- call.return_value = policy.Policy()
-
- response = client.set_iam_policy(
- request={"resource": "resource_value", "policy": policy.Policy(version=774)}
- )
- call.assert_called()
-
-
-def test_set_iam_policy_flattened():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(type(client._transport.set_iam_policy), "__call__") as call:
- # Designate an appropriate return value for the call.
- call.return_value = policy.Policy()
-
- # Call the method with a truthy value for each flattened field,
- # using the keyword arguments to the method.
- response = client.set_iam_policy(resource="resource_value")
-
- # Establish that the underlying call was made with the expected
- # request object values.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
- assert args[0].resource == "resource_value"
-
-
-def test_set_iam_policy_flattened_error():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Attempting to call a method with both a request object and flattened
- # fields is an error.
- with pytest.raises(ValueError):
- client.set_iam_policy(
- iam_policy.SetIamPolicyRequest(), resource="resource_value"
- )
-
-
-def test_test_iam_permissions(transport: str = "grpc"):
- client = CloudBillingClient(
- credentials=credentials.AnonymousCredentials(), transport=transport
- )
-
- # Everything is optional in proto3 as far as the runtime is concerned,
- # and we are mocking out the actual API, so just send an empty request.
- request = iam_policy.TestIamPermissionsRequest()
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.test_iam_permissions), "__call__"
- ) as call:
- # Designate an appropriate return value for the call.
- call.return_value = iam_policy.TestIamPermissionsResponse(
- permissions=["permissions_value"]
- )
-
- response = client.test_iam_permissions(request)
-
- # Establish that the underlying gRPC stub method was called.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
-
- assert args[0] == request
-
- # Establish that the response is the type that we expect.
- assert isinstance(response, iam_policy.TestIamPermissionsResponse)
- assert response.permissions == ["permissions_value"]
-
-
-def test_test_iam_permissions_from_dict():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.test_iam_permissions), "__call__"
- ) as call:
- # Designate an appropriate return value for the call.
- call.return_value = iam_policy.TestIamPermissionsResponse()
-
- response = client.test_iam_permissions(
- request={"resource": "resource_value", "permissions": ["permissions_value"]}
- )
- call.assert_called()
-
-
-def test_test_iam_permissions_flattened():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(
- type(client._transport.test_iam_permissions), "__call__"
- ) as call:
- # Designate an appropriate return value for the call.
- call.return_value = iam_policy.TestIamPermissionsResponse()
-
- # Call the method with a truthy value for each flattened field,
- # using the keyword arguments to the method.
- response = client.test_iam_permissions(
- resource="resource_value", permissions=["permissions_value"]
- )
-
- # Establish that the underlying call was made with the expected
- # request object values.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
- assert args[0].resource == "resource_value"
- assert args[0].permissions == ["permissions_value"]
-
-
-def test_test_iam_permissions_flattened_error():
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
-
- # Attempting to call a method with both a request object and flattened
- # fields is an error.
- with pytest.raises(ValueError):
- client.test_iam_permissions(
- iam_policy.TestIamPermissionsRequest(),
- resource="resource_value",
- permissions=["permissions_value"],
- )
-
-
-def test_credentials_transport_error():
- # It is an error to provide credentials and a transport instance.
- transport = transports.CloudBillingGrpcTransport(
- credentials=credentials.AnonymousCredentials()
- )
- with pytest.raises(ValueError):
- client = CloudBillingClient(
- credentials=credentials.AnonymousCredentials(), transport=transport
- )
-
-
-def test_transport_instance():
- # A client may be instantiated with a custom transport instance.
- transport = transports.CloudBillingGrpcTransport(
- credentials=credentials.AnonymousCredentials()
- )
- client = CloudBillingClient(transport=transport)
- assert client._transport is transport
-
-
-def test_transport_grpc_default():
- # A client should use the gRPC transport by default.
- client = CloudBillingClient(credentials=credentials.AnonymousCredentials())
- assert isinstance(client._transport, transports.CloudBillingGrpcTransport)
-
-
-def test_cloud_billing_base_transport():
- # Instantiate the base transport.
- transport = transports.CloudBillingTransport(
- credentials=credentials.AnonymousCredentials()
- )
-
- # Every method on the transport should just blindly
- # raise NotImplementedError.
- methods = (
- "get_billing_account",
- "list_billing_accounts",
- "update_billing_account",
- "create_billing_account",
- "list_project_billing_info",
- "get_project_billing_info",
- "update_project_billing_info",
- "get_iam_policy",
- "set_iam_policy",
- "test_iam_permissions",
- )
- for method in methods:
- with pytest.raises(NotImplementedError):
- getattr(transport, method)(request=object())
-
-
-def test_cloud_billing_auth_adc():
- # If no credentials are provided, we should use ADC credentials.
- with mock.patch.object(auth, "default") as adc:
- adc.return_value = (credentials.AnonymousCredentials(), None)
- CloudBillingClient()
- adc.assert_called_once_with(
- scopes=("https://www.googleapis.com/auth/cloud-platform",)
- )
-
-
-def test_cloud_billing_host_no_port():
- client = CloudBillingClient(
- credentials=credentials.AnonymousCredentials(),
- client_options=client_options.ClientOptions(
- api_endpoint="cloudbilling.googleapis.com"
- ),
- transport="grpc",
- )
- assert client._transport._host == "cloudbilling.googleapis.com:443"
-
-
-def test_cloud_billing_host_with_port():
- client = CloudBillingClient(
- credentials=credentials.AnonymousCredentials(),
- client_options=client_options.ClientOptions(
- api_endpoint="cloudbilling.googleapis.com:8000"
- ),
- transport="grpc",
- )
- assert client._transport._host == "cloudbilling.googleapis.com:8000"
-
-
-def test_cloud_billing_grpc_transport_channel():
- channel = grpc.insecure_channel("http://localhost/")
-
- # Check that if channel is provided, mtls endpoint and client_cert_source
- # won't be used.
- callback = mock.MagicMock()
- transport = transports.CloudBillingGrpcTransport(
- host="squid.clam.whelk",
- channel=channel,
- api_mtls_endpoint="mtls.squid.clam.whelk",
- client_cert_source=callback,
- )
- assert transport.grpc_channel == channel
- assert transport._host == "squid.clam.whelk:443"
- assert not callback.called
-
-
-@mock.patch("grpc.ssl_channel_credentials", autospec=True)
-@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True)
-def test_cloud_billing_grpc_transport_channel_mtls_with_client_cert_source(
- grpc_create_channel, grpc_ssl_channel_cred
-):
- # Check that if channel is None, but api_mtls_endpoint and client_cert_source
- # are provided, then a mTLS channel will be created.
- mock_cred = mock.Mock()
-
- mock_ssl_cred = mock.Mock()
- grpc_ssl_channel_cred.return_value = mock_ssl_cred
-
- mock_grpc_channel = mock.Mock()
- grpc_create_channel.return_value = mock_grpc_channel
-
- transport = transports.CloudBillingGrpcTransport(
- host="squid.clam.whelk",
- credentials=mock_cred,
- api_mtls_endpoint="mtls.squid.clam.whelk",
- client_cert_source=client_cert_source_callback,
- )
- grpc_ssl_channel_cred.assert_called_once_with(
- certificate_chain=b"cert bytes", private_key=b"key bytes"
- )
- grpc_create_channel.assert_called_once_with(
- "mtls.squid.clam.whelk:443",
- credentials=mock_cred,
- ssl_credentials=mock_ssl_cred,
- scopes=("https://www.googleapis.com/auth/cloud-platform",),
- )
- assert transport.grpc_channel == mock_grpc_channel
-
-
-@pytest.mark.parametrize(
- "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"]
-)
-@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True)
-def test_cloud_billing_grpc_transport_channel_mtls_with_adc(
- grpc_create_channel, api_mtls_endpoint
-):
- # Check that if channel and client_cert_source are None, but api_mtls_endpoint
- # is provided, then a mTLS channel will be created with SSL ADC.
- mock_grpc_channel = mock.Mock()
- grpc_create_channel.return_value = mock_grpc_channel
-
- # Mock google.auth.transport.grpc.SslCredentials class.
- mock_ssl_cred = mock.Mock()
- with mock.patch.multiple(
- "google.auth.transport.grpc.SslCredentials",
- __init__=mock.Mock(return_value=None),
- ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred),
- ):
- mock_cred = mock.Mock()
- transport = transports.CloudBillingGrpcTransport(
- host="squid.clam.whelk",
- credentials=mock_cred,
- api_mtls_endpoint=api_mtls_endpoint,
- client_cert_source=None,
- )
- grpc_create_channel.assert_called_once_with(
- "mtls.squid.clam.whelk:443",
- credentials=mock_cred,
- ssl_credentials=mock_ssl_cred,
- scopes=("https://www.googleapis.com/auth/cloud-platform",),
- )
- assert transport.grpc_channel == mock_grpc_channel
diff --git a/packages/google-cloud-billing/tests/unit/billing_v1/test_cloud_catalog.py b/packages/google-cloud-billing/tests/unit/billing_v1/test_cloud_catalog.py
deleted file mode 100644
index 2c4510ae7ed9..000000000000
--- a/packages/google-cloud-billing/tests/unit/billing_v1/test_cloud_catalog.py
+++ /dev/null
@@ -1,535 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright 2020 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-from unittest import mock
-
-import grpc
-import math
-import pytest
-
-from google import auth
-from google.api_core import client_options
-from google.api_core import grpc_helpers
-from google.auth import credentials
-from google.cloud.billing_v1.services.cloud_catalog import CloudCatalogClient
-from google.cloud.billing_v1.services.cloud_catalog import pagers
-from google.cloud.billing_v1.services.cloud_catalog import transports
-from google.cloud.billing_v1.types import cloud_catalog
-from google.oauth2 import service_account
-from google.protobuf import timestamp_pb2 as timestamp # type: ignore
-
-
-def client_cert_source_callback():
- return b"cert bytes", b"key bytes"
-
-
-def test__get_default_mtls_endpoint():
- api_endpoint = "example.googleapis.com"
- api_mtls_endpoint = "example.mtls.googleapis.com"
- sandbox_endpoint = "example.sandbox.googleapis.com"
- sandbox_mtls_endpoint = "example.mtls.sandbox.googleapis.com"
- non_googleapi = "api.example.com"
-
- assert CloudCatalogClient._get_default_mtls_endpoint(None) is None
- assert (
- CloudCatalogClient._get_default_mtls_endpoint(api_endpoint) == api_mtls_endpoint
- )
- assert (
- CloudCatalogClient._get_default_mtls_endpoint(api_mtls_endpoint)
- == api_mtls_endpoint
- )
- assert (
- CloudCatalogClient._get_default_mtls_endpoint(sandbox_endpoint)
- == sandbox_mtls_endpoint
- )
- assert (
- CloudCatalogClient._get_default_mtls_endpoint(sandbox_mtls_endpoint)
- == sandbox_mtls_endpoint
- )
- assert CloudCatalogClient._get_default_mtls_endpoint(non_googleapi) == non_googleapi
-
-
-def test_cloud_catalog_client_from_service_account_file():
- creds = credentials.AnonymousCredentials()
- with mock.patch.object(
- service_account.Credentials, "from_service_account_file"
- ) as factory:
- factory.return_value = creds
- client = CloudCatalogClient.from_service_account_file("dummy/file/path.json")
- assert client._transport._credentials == creds
-
- client = CloudCatalogClient.from_service_account_json("dummy/file/path.json")
- assert client._transport._credentials == creds
-
- assert client._transport._host == "cloudbilling.googleapis.com:443"
-
-
-def test_cloud_catalog_client_client_options():
- # Check that if channel is provided we won't create a new one.
- with mock.patch(
- "google.cloud.billing_v1.services.cloud_catalog.CloudCatalogClient.get_transport_class"
- ) as gtc:
- transport = transports.CloudCatalogGrpcTransport(
- credentials=credentials.AnonymousCredentials()
- )
- client = CloudCatalogClient(transport=transport)
- gtc.assert_not_called()
-
- # Check mTLS is not triggered with empty client options.
- options = client_options.ClientOptions()
- with mock.patch(
- "google.cloud.billing_v1.services.cloud_catalog.CloudCatalogClient.get_transport_class"
- ) as gtc:
- transport = gtc.return_value = mock.MagicMock()
- client = CloudCatalogClient(client_options=options)
- transport.assert_called_once_with(
- credentials=None, host=client.DEFAULT_ENDPOINT
- )
-
- # Check mTLS is not triggered if api_endpoint is provided but
- # client_cert_source is None.
- options = client_options.ClientOptions(api_endpoint="squid.clam.whelk")
- with mock.patch(
- "google.cloud.billing_v1.services.cloud_catalog.transports.CloudCatalogGrpcTransport.__init__"
- ) as grpc_transport:
- grpc_transport.return_value = None
- client = CloudCatalogClient(client_options=options)
- grpc_transport.assert_called_once_with(
- api_mtls_endpoint=None,
- client_cert_source=None,
- credentials=None,
- host="squid.clam.whelk",
- )
-
- # Check mTLS is triggered if client_cert_source is provided.
- options = client_options.ClientOptions(
- client_cert_source=client_cert_source_callback
- )
- with mock.patch(
- "google.cloud.billing_v1.services.cloud_catalog.transports.CloudCatalogGrpcTransport.__init__"
- ) as grpc_transport:
- grpc_transport.return_value = None
- client = CloudCatalogClient(client_options=options)
- grpc_transport.assert_called_once_with(
- api_mtls_endpoint=client.DEFAULT_MTLS_ENDPOINT,
- client_cert_source=client_cert_source_callback,
- credentials=None,
- host=client.DEFAULT_ENDPOINT,
- )
-
- # Check mTLS is triggered if api_endpoint and client_cert_source are provided.
- options = client_options.ClientOptions(
- api_endpoint="squid.clam.whelk", client_cert_source=client_cert_source_callback
- )
- with mock.patch(
- "google.cloud.billing_v1.services.cloud_catalog.transports.CloudCatalogGrpcTransport.__init__"
- ) as grpc_transport:
- grpc_transport.return_value = None
- client = CloudCatalogClient(client_options=options)
- grpc_transport.assert_called_once_with(
- api_mtls_endpoint="squid.clam.whelk",
- client_cert_source=client_cert_source_callback,
- credentials=None,
- host="squid.clam.whelk",
- )
-
-
-def test_cloud_catalog_client_client_options_from_dict():
- with mock.patch(
- "google.cloud.billing_v1.services.cloud_catalog.transports.CloudCatalogGrpcTransport.__init__"
- ) as grpc_transport:
- grpc_transport.return_value = None
- client = CloudCatalogClient(client_options={"api_endpoint": "squid.clam.whelk"})
- grpc_transport.assert_called_once_with(
- api_mtls_endpoint=None,
- client_cert_source=None,
- credentials=None,
- host="squid.clam.whelk",
- )
-
-
-def test_list_services(transport: str = "grpc"):
- client = CloudCatalogClient(
- credentials=credentials.AnonymousCredentials(), transport=transport
- )
-
- # Everything is optional in proto3 as far as the runtime is concerned,
- # and we are mocking out the actual API, so just send an empty request.
- request = cloud_catalog.ListServicesRequest()
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(type(client._transport.list_services), "__call__") as call:
- # Designate an appropriate return value for the call.
- call.return_value = cloud_catalog.ListServicesResponse(
- next_page_token="next_page_token_value"
- )
-
- response = client.list_services(request)
-
- # Establish that the underlying gRPC stub method was called.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
-
- assert args[0] == request
-
- # Establish that the response is the type that we expect.
- assert isinstance(response, pagers.ListServicesPager)
- assert response.next_page_token == "next_page_token_value"
-
-
-def test_list_services_pager():
- client = CloudCatalogClient(credentials=credentials.AnonymousCredentials)
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(type(client._transport.list_services), "__call__") as call:
- # Set the response to a series of pages.
- call.side_effect = (
- cloud_catalog.ListServicesResponse(
- services=[
- cloud_catalog.Service(),
- cloud_catalog.Service(),
- cloud_catalog.Service(),
- ],
- next_page_token="abc",
- ),
- cloud_catalog.ListServicesResponse(services=[], next_page_token="def"),
- cloud_catalog.ListServicesResponse(
- services=[cloud_catalog.Service()], next_page_token="ghi"
- ),
- cloud_catalog.ListServicesResponse(
- services=[cloud_catalog.Service(), cloud_catalog.Service()]
- ),
- RuntimeError,
- )
- results = [i for i in client.list_services(request={})]
- assert len(results) == 6
- assert all(isinstance(i, cloud_catalog.Service) for i in results)
-
-
-def test_list_services_pages():
- client = CloudCatalogClient(credentials=credentials.AnonymousCredentials)
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(type(client._transport.list_services), "__call__") as call:
- # Set the response to a series of pages.
- call.side_effect = (
- cloud_catalog.ListServicesResponse(
- services=[
- cloud_catalog.Service(),
- cloud_catalog.Service(),
- cloud_catalog.Service(),
- ],
- next_page_token="abc",
- ),
- cloud_catalog.ListServicesResponse(services=[], next_page_token="def"),
- cloud_catalog.ListServicesResponse(
- services=[cloud_catalog.Service()], next_page_token="ghi"
- ),
- cloud_catalog.ListServicesResponse(
- services=[cloud_catalog.Service(), cloud_catalog.Service()]
- ),
- RuntimeError,
- )
- pages = list(client.list_services(request={}).pages)
- for page, token in zip(pages, ["abc", "def", "ghi", ""]):
- assert page.raw_page.next_page_token == token
-
-
-def test_list_skus(transport: str = "grpc"):
- client = CloudCatalogClient(
- credentials=credentials.AnonymousCredentials(), transport=transport
- )
-
- # Everything is optional in proto3 as far as the runtime is concerned,
- # and we are mocking out the actual API, so just send an empty request.
- request = cloud_catalog.ListSkusRequest()
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(type(client._transport.list_skus), "__call__") as call:
- # Designate an appropriate return value for the call.
- call.return_value = cloud_catalog.ListSkusResponse(
- next_page_token="next_page_token_value"
- )
-
- response = client.list_skus(request)
-
- # Establish that the underlying gRPC stub method was called.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
-
- assert args[0] == request
-
- # Establish that the response is the type that we expect.
- assert isinstance(response, pagers.ListSkusPager)
- assert response.next_page_token == "next_page_token_value"
-
-
-def test_list_skus_field_headers():
- client = CloudCatalogClient(credentials=credentials.AnonymousCredentials())
-
- # Any value that is part of the HTTP/1.1 URI should be sent as
- # a field header. Set these to a non-empty value.
- request = cloud_catalog.ListSkusRequest(parent="parent/value")
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(type(client._transport.list_skus), "__call__") as call:
- call.return_value = cloud_catalog.ListSkusResponse()
- client.list_skus(request)
-
- # Establish that the underlying gRPC stub method was called.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
- assert args[0] == request
-
- # Establish that the field header was sent.
- _, _, kw = call.mock_calls[0]
- assert ("x-goog-request-params", "parent=parent/value") in kw["metadata"]
-
-
-def test_list_skus_flattened():
- client = CloudCatalogClient(credentials=credentials.AnonymousCredentials())
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(type(client._transport.list_skus), "__call__") as call:
- # Designate an appropriate return value for the call.
- call.return_value = cloud_catalog.ListSkusResponse()
-
- # Call the method with a truthy value for each flattened field,
- # using the keyword arguments to the method.
- response = client.list_skus(parent="parent_value")
-
- # Establish that the underlying call was made with the expected
- # request object values.
- assert len(call.mock_calls) == 1
- _, args, _ = call.mock_calls[0]
- assert args[0].parent == "parent_value"
-
-
-def test_list_skus_flattened_error():
- client = CloudCatalogClient(credentials=credentials.AnonymousCredentials())
-
- # Attempting to call a method with both a request object and flattened
- # fields is an error.
- with pytest.raises(ValueError):
- client.list_skus(cloud_catalog.ListSkusRequest(), parent="parent_value")
-
-
-def test_list_skus_pager():
- client = CloudCatalogClient(credentials=credentials.AnonymousCredentials)
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(type(client._transport.list_skus), "__call__") as call:
- # Set the response to a series of pages.
- call.side_effect = (
- cloud_catalog.ListSkusResponse(
- skus=[cloud_catalog.Sku(), cloud_catalog.Sku(), cloud_catalog.Sku()],
- next_page_token="abc",
- ),
- cloud_catalog.ListSkusResponse(skus=[], next_page_token="def"),
- cloud_catalog.ListSkusResponse(
- skus=[cloud_catalog.Sku()], next_page_token="ghi"
- ),
- cloud_catalog.ListSkusResponse(
- skus=[cloud_catalog.Sku(), cloud_catalog.Sku()]
- ),
- RuntimeError,
- )
- results = [i for i in client.list_skus(request={})]
- assert len(results) == 6
- assert all(isinstance(i, cloud_catalog.Sku) for i in results)
-
-
-def test_list_skus_pages():
- client = CloudCatalogClient(credentials=credentials.AnonymousCredentials)
-
- # Mock the actual call within the gRPC stub, and fake the request.
- with mock.patch.object(type(client._transport.list_skus), "__call__") as call:
- # Set the response to a series of pages.
- call.side_effect = (
- cloud_catalog.ListSkusResponse(
- skus=[cloud_catalog.Sku(), cloud_catalog.Sku(), cloud_catalog.Sku()],
- next_page_token="abc",
- ),
- cloud_catalog.ListSkusResponse(skus=[], next_page_token="def"),
- cloud_catalog.ListSkusResponse(
- skus=[cloud_catalog.Sku()], next_page_token="ghi"
- ),
- cloud_catalog.ListSkusResponse(
- skus=[cloud_catalog.Sku(), cloud_catalog.Sku()]
- ),
- RuntimeError,
- )
- pages = list(client.list_skus(request={}).pages)
- for page, token in zip(pages, ["abc", "def", "ghi", ""]):
- assert page.raw_page.next_page_token == token
-
-
-def test_credentials_transport_error():
- # It is an error to provide credentials and a transport instance.
- transport = transports.CloudCatalogGrpcTransport(
- credentials=credentials.AnonymousCredentials()
- )
- with pytest.raises(ValueError):
- client = CloudCatalogClient(
- credentials=credentials.AnonymousCredentials(), transport=transport
- )
-
-
-def test_transport_instance():
- # A client may be instantiated with a custom transport instance.
- transport = transports.CloudCatalogGrpcTransport(
- credentials=credentials.AnonymousCredentials()
- )
- client = CloudCatalogClient(transport=transport)
- assert client._transport is transport
-
-
-def test_transport_grpc_default():
- # A client should use the gRPC transport by default.
- client = CloudCatalogClient(credentials=credentials.AnonymousCredentials())
- assert isinstance(client._transport, transports.CloudCatalogGrpcTransport)
-
-
-def test_cloud_catalog_base_transport():
- # Instantiate the base transport.
- transport = transports.CloudCatalogTransport(
- credentials=credentials.AnonymousCredentials()
- )
-
- # Every method on the transport should just blindly
- # raise NotImplementedError.
- methods = ("list_services", "list_skus")
- for method in methods:
- with pytest.raises(NotImplementedError):
- getattr(transport, method)(request=object())
-
-
-def test_cloud_catalog_auth_adc():
- # If no credentials are provided, we should use ADC credentials.
- with mock.patch.object(auth, "default") as adc:
- adc.return_value = (credentials.AnonymousCredentials(), None)
- CloudCatalogClient()
- adc.assert_called_once_with(
- scopes=("https://www.googleapis.com/auth/cloud-platform",)
- )
-
-
-def test_cloud_catalog_host_no_port():
- client = CloudCatalogClient(
- credentials=credentials.AnonymousCredentials(),
- client_options=client_options.ClientOptions(
- api_endpoint="cloudbilling.googleapis.com"
- ),
- transport="grpc",
- )
- assert client._transport._host == "cloudbilling.googleapis.com:443"
-
-
-def test_cloud_catalog_host_with_port():
- client = CloudCatalogClient(
- credentials=credentials.AnonymousCredentials(),
- client_options=client_options.ClientOptions(
- api_endpoint="cloudbilling.googleapis.com:8000"
- ),
- transport="grpc",
- )
- assert client._transport._host == "cloudbilling.googleapis.com:8000"
-
-
-def test_cloud_catalog_grpc_transport_channel():
- channel = grpc.insecure_channel("http://localhost/")
-
- # Check that if channel is provided, mtls endpoint and client_cert_source
- # won't be used.
- callback = mock.MagicMock()
- transport = transports.CloudCatalogGrpcTransport(
- host="squid.clam.whelk",
- channel=channel,
- api_mtls_endpoint="mtls.squid.clam.whelk",
- client_cert_source=callback,
- )
- assert transport.grpc_channel == channel
- assert transport._host == "squid.clam.whelk:443"
- assert not callback.called
-
-
-@mock.patch("grpc.ssl_channel_credentials", autospec=True)
-@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True)
-def test_cloud_catalog_grpc_transport_channel_mtls_with_client_cert_source(
- grpc_create_channel, grpc_ssl_channel_cred
-):
- # Check that if channel is None, but api_mtls_endpoint and client_cert_source
- # are provided, then a mTLS channel will be created.
- mock_cred = mock.Mock()
-
- mock_ssl_cred = mock.Mock()
- grpc_ssl_channel_cred.return_value = mock_ssl_cred
-
- mock_grpc_channel = mock.Mock()
- grpc_create_channel.return_value = mock_grpc_channel
-
- transport = transports.CloudCatalogGrpcTransport(
- host="squid.clam.whelk",
- credentials=mock_cred,
- api_mtls_endpoint="mtls.squid.clam.whelk",
- client_cert_source=client_cert_source_callback,
- )
- grpc_ssl_channel_cred.assert_called_once_with(
- certificate_chain=b"cert bytes", private_key=b"key bytes"
- )
- grpc_create_channel.assert_called_once_with(
- "mtls.squid.clam.whelk:443",
- credentials=mock_cred,
- ssl_credentials=mock_ssl_cred,
- scopes=("https://www.googleapis.com/auth/cloud-platform",),
- )
- assert transport.grpc_channel == mock_grpc_channel
-
-
-@pytest.mark.parametrize(
- "api_mtls_endpoint", ["mtls.squid.clam.whelk", "mtls.squid.clam.whelk:443"]
-)
-@mock.patch("google.api_core.grpc_helpers.create_channel", autospec=True)
-def test_cloud_catalog_grpc_transport_channel_mtls_with_adc(
- grpc_create_channel, api_mtls_endpoint
-):
- # Check that if channel and client_cert_source are None, but api_mtls_endpoint
- # is provided, then a mTLS channel will be created with SSL ADC.
- mock_grpc_channel = mock.Mock()
- grpc_create_channel.return_value = mock_grpc_channel
-
- # Mock google.auth.transport.grpc.SslCredentials class.
- mock_ssl_cred = mock.Mock()
- with mock.patch.multiple(
- "google.auth.transport.grpc.SslCredentials",
- __init__=mock.Mock(return_value=None),
- ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred),
- ):
- mock_cred = mock.Mock()
- transport = transports.CloudCatalogGrpcTransport(
- host="squid.clam.whelk",
- credentials=mock_cred,
- api_mtls_endpoint=api_mtls_endpoint,
- client_cert_source=None,
- )
- grpc_create_channel.assert_called_once_with(
- "mtls.squid.clam.whelk:443",
- credentials=mock_cred,
- ssl_credentials=mock_ssl_cred,
- scopes=("https://www.googleapis.com/auth/cloud-platform",),
- )
- assert transport.grpc_channel == mock_grpc_channel
diff --git a/packages/google-cloud-billing/tests/unit/gapic/billing_v1/__init__.py b/packages/google-cloud-billing/tests/unit/gapic/billing_v1/__init__.py
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/packages/google-cloud-billing/tests/unit/gapic/billing_v1/__init__.py
@@ -0,0 +1 @@
+
diff --git a/packages/google-cloud-billing/tests/unit/gapic/billing_v1/test_cloud_billing.py b/packages/google-cloud-billing/tests/unit/gapic/billing_v1/test_cloud_billing.py
new file mode 100644
index 000000000000..9543ca65a545
--- /dev/null
+++ b/packages/google-cloud-billing/tests/unit/gapic/billing_v1/test_cloud_billing.py
@@ -0,0 +1,3232 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import os
+import mock
+
+import grpc
+from grpc.experimental import aio
+import math
+import pytest
+from proto.marshal.rules.dates import DurationRule, TimestampRule
+
+from google import auth
+from google.api_core import client_options
+from google.api_core import exceptions
+from google.api_core import gapic_v1
+from google.api_core import grpc_helpers
+from google.api_core import grpc_helpers_async
+from google.auth import credentials
+from google.auth.exceptions import MutualTLSChannelError
+from google.cloud.billing_v1.services.cloud_billing import CloudBillingAsyncClient
+from google.cloud.billing_v1.services.cloud_billing import CloudBillingClient
+from google.cloud.billing_v1.services.cloud_billing import pagers
+from google.cloud.billing_v1.services.cloud_billing import transports
+from google.cloud.billing_v1.types import cloud_billing
+from google.iam.v1 import iam_policy_pb2 as iam_policy # type: ignore
+from google.iam.v1 import options_pb2 as options # type: ignore
+from google.iam.v1 import policy_pb2 as policy # type: ignore
+from google.oauth2 import service_account
+from google.protobuf import field_mask_pb2 as field_mask # type: ignore
+from google.type import expr_pb2 as expr # type: ignore
+
+
+def client_cert_source_callback():
+ return b"cert bytes", b"key bytes"
+
+
+# If default endpoint is localhost, then default mtls endpoint will be the same.
+# This method modifies the default endpoint so the client can produce a different
+# mtls endpoint for endpoint testing purposes.
+def modify_default_endpoint(client):
+ return (
+ "foo.googleapis.com"
+ if ("localhost" in client.DEFAULT_ENDPOINT)
+ else client.DEFAULT_ENDPOINT
+ )
+
+
+def test__get_default_mtls_endpoint():
+ api_endpoint = "example.googleapis.com"
+ api_mtls_endpoint = "example.mtls.googleapis.com"
+ sandbox_endpoint = "example.sandbox.googleapis.com"
+ sandbox_mtls_endpoint = "example.mtls.sandbox.googleapis.com"
+ non_googleapi = "api.example.com"
+
+ assert CloudBillingClient._get_default_mtls_endpoint(None) is None
+ assert (
+ CloudBillingClient._get_default_mtls_endpoint(api_endpoint) == api_mtls_endpoint
+ )
+ assert (
+ CloudBillingClient._get_default_mtls_endpoint(api_mtls_endpoint)
+ == api_mtls_endpoint
+ )
+ assert (
+ CloudBillingClient._get_default_mtls_endpoint(sandbox_endpoint)
+ == sandbox_mtls_endpoint
+ )
+ assert (
+ CloudBillingClient._get_default_mtls_endpoint(sandbox_mtls_endpoint)
+ == sandbox_mtls_endpoint
+ )
+ assert CloudBillingClient._get_default_mtls_endpoint(non_googleapi) == non_googleapi
+
+
+@pytest.mark.parametrize("client_class", [CloudBillingClient, CloudBillingAsyncClient])
+def test_cloud_billing_client_from_service_account_file(client_class):
+ creds = credentials.AnonymousCredentials()
+ with mock.patch.object(
+ service_account.Credentials, "from_service_account_file"
+ ) as factory:
+ factory.return_value = creds
+ client = client_class.from_service_account_file("dummy/file/path.json")
+ assert client.transport._credentials == creds
+
+ client = client_class.from_service_account_json("dummy/file/path.json")
+ assert client.transport._credentials == creds
+
+ assert client.transport._host == "cloudbilling.googleapis.com:443"
+
+
+def test_cloud_billing_client_get_transport_class():
+ transport = CloudBillingClient.get_transport_class()
+ assert transport == transports.CloudBillingGrpcTransport
+
+ transport = CloudBillingClient.get_transport_class("grpc")
+ assert transport == transports.CloudBillingGrpcTransport
+
+
+@pytest.mark.parametrize(
+ "client_class,transport_class,transport_name",
+ [
+ (CloudBillingClient, transports.CloudBillingGrpcTransport, "grpc"),
+ (
+ CloudBillingAsyncClient,
+ transports.CloudBillingGrpcAsyncIOTransport,
+ "grpc_asyncio",
+ ),
+ ],
+)
+@mock.patch.object(
+ CloudBillingClient, "DEFAULT_ENDPOINT", modify_default_endpoint(CloudBillingClient)
+)
+@mock.patch.object(
+ CloudBillingAsyncClient,
+ "DEFAULT_ENDPOINT",
+ modify_default_endpoint(CloudBillingAsyncClient),
+)
+def test_cloud_billing_client_client_options(
+ client_class, transport_class, transport_name
+):
+ # Check that if channel is provided we won't create a new one.
+ with mock.patch.object(CloudBillingClient, "get_transport_class") as gtc:
+ transport = transport_class(credentials=credentials.AnonymousCredentials())
+ client = client_class(transport=transport)
+ gtc.assert_not_called()
+
+ # Check that if channel is provided via str we will create a new one.
+ with mock.patch.object(CloudBillingClient, "get_transport_class") as gtc:
+ client = client_class(transport=transport_name)
+ gtc.assert_called()
+
+ # Check the case api_endpoint is provided.
+ options = client_options.ClientOptions(api_endpoint="squid.clam.whelk")
+ with mock.patch.object(transport_class, "__init__") as patched:
+ patched.return_value = None
+ client = client_class(client_options=options)
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host="squid.clam.whelk",
+ scopes=None,
+ ssl_channel_credentials=None,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+ # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is
+ # "never".
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}):
+ with mock.patch.object(transport_class, "__init__") as patched:
+ patched.return_value = None
+ client = client_class()
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host=client.DEFAULT_ENDPOINT,
+ scopes=None,
+ ssl_channel_credentials=None,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+ # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is
+ # "always".
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}):
+ with mock.patch.object(transport_class, "__init__") as patched:
+ patched.return_value = None
+ client = client_class()
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host=client.DEFAULT_MTLS_ENDPOINT,
+ scopes=None,
+ ssl_channel_credentials=None,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+ # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has
+ # unsupported value.
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}):
+ with pytest.raises(MutualTLSChannelError):
+ client = client_class()
+
+ # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value.
+ with mock.patch.dict(
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
+ ):
+ with pytest.raises(ValueError):
+ client = client_class()
+
+ # Check the case quota_project_id is provided
+ options = client_options.ClientOptions(quota_project_id="octopus")
+ with mock.patch.object(transport_class, "__init__") as patched:
+ patched.return_value = None
+ client = client_class(client_options=options)
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host=client.DEFAULT_ENDPOINT,
+ scopes=None,
+ ssl_channel_credentials=None,
+ quota_project_id="octopus",
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+
+@pytest.mark.parametrize(
+ "client_class,transport_class,transport_name,use_client_cert_env",
+ [
+ (CloudBillingClient, transports.CloudBillingGrpcTransport, "grpc", "true"),
+ (
+ CloudBillingAsyncClient,
+ transports.CloudBillingGrpcAsyncIOTransport,
+ "grpc_asyncio",
+ "true",
+ ),
+ (CloudBillingClient, transports.CloudBillingGrpcTransport, "grpc", "false"),
+ (
+ CloudBillingAsyncClient,
+ transports.CloudBillingGrpcAsyncIOTransport,
+ "grpc_asyncio",
+ "false",
+ ),
+ ],
+)
+@mock.patch.object(
+ CloudBillingClient, "DEFAULT_ENDPOINT", modify_default_endpoint(CloudBillingClient)
+)
+@mock.patch.object(
+ CloudBillingAsyncClient,
+ "DEFAULT_ENDPOINT",
+ modify_default_endpoint(CloudBillingAsyncClient),
+)
+@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"})
+def test_cloud_billing_client_mtls_env_auto(
+ client_class, transport_class, transport_name, use_client_cert_env
+):
+ # This tests the endpoint autoswitch behavior. Endpoint is autoswitched to the default
+ # mtls endpoint, if GOOGLE_API_USE_CLIENT_CERTIFICATE is "true" and client cert exists.
+
+ # Check the case client_cert_source is provided. Whether client cert is used depends on
+ # GOOGLE_API_USE_CLIENT_CERTIFICATE value.
+ with mock.patch.dict(
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env}
+ ):
+ options = client_options.ClientOptions(
+ client_cert_source=client_cert_source_callback
+ )
+ with mock.patch.object(transport_class, "__init__") as patched:
+ ssl_channel_creds = mock.Mock()
+ with mock.patch(
+ "grpc.ssl_channel_credentials", return_value=ssl_channel_creds
+ ):
+ patched.return_value = None
+ client = client_class(client_options=options)
+
+ if use_client_cert_env == "false":
+ expected_ssl_channel_creds = None
+ expected_host = client.DEFAULT_ENDPOINT
+ else:
+ expected_ssl_channel_creds = ssl_channel_creds
+ expected_host = client.DEFAULT_MTLS_ENDPOINT
+
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host=expected_host,
+ scopes=None,
+ ssl_channel_credentials=expected_ssl_channel_creds,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+ # Check the case ADC client cert is provided. Whether client cert is used depends on
+ # GOOGLE_API_USE_CLIENT_CERTIFICATE value.
+ with mock.patch.dict(
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env}
+ ):
+ with mock.patch.object(transport_class, "__init__") as patched:
+ with mock.patch(
+ "google.auth.transport.grpc.SslCredentials.__init__", return_value=None
+ ):
+ with mock.patch(
+ "google.auth.transport.grpc.SslCredentials.is_mtls",
+ new_callable=mock.PropertyMock,
+ ) as is_mtls_mock:
+ with mock.patch(
+ "google.auth.transport.grpc.SslCredentials.ssl_credentials",
+ new_callable=mock.PropertyMock,
+ ) as ssl_credentials_mock:
+ if use_client_cert_env == "false":
+ is_mtls_mock.return_value = False
+ ssl_credentials_mock.return_value = None
+ expected_host = client.DEFAULT_ENDPOINT
+ expected_ssl_channel_creds = None
+ else:
+ is_mtls_mock.return_value = True
+ ssl_credentials_mock.return_value = mock.Mock()
+ expected_host = client.DEFAULT_MTLS_ENDPOINT
+ expected_ssl_channel_creds = (
+ ssl_credentials_mock.return_value
+ )
+
+ patched.return_value = None
+ client = client_class()
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host=expected_host,
+ scopes=None,
+ ssl_channel_credentials=expected_ssl_channel_creds,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+ # Check the case client_cert_source and ADC client cert are not provided.
+ with mock.patch.dict(
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env}
+ ):
+ with mock.patch.object(transport_class, "__init__") as patched:
+ with mock.patch(
+ "google.auth.transport.grpc.SslCredentials.__init__", return_value=None
+ ):
+ with mock.patch(
+ "google.auth.transport.grpc.SslCredentials.is_mtls",
+ new_callable=mock.PropertyMock,
+ ) as is_mtls_mock:
+ is_mtls_mock.return_value = False
+ patched.return_value = None
+ client = client_class()
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host=client.DEFAULT_ENDPOINT,
+ scopes=None,
+ ssl_channel_credentials=None,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+
+@pytest.mark.parametrize(
+ "client_class,transport_class,transport_name",
+ [
+ (CloudBillingClient, transports.CloudBillingGrpcTransport, "grpc"),
+ (
+ CloudBillingAsyncClient,
+ transports.CloudBillingGrpcAsyncIOTransport,
+ "grpc_asyncio",
+ ),
+ ],
+)
+def test_cloud_billing_client_client_options_scopes(
+ client_class, transport_class, transport_name
+):
+ # Check the case scopes are provided.
+ options = client_options.ClientOptions(scopes=["1", "2"],)
+ with mock.patch.object(transport_class, "__init__") as patched:
+ patched.return_value = None
+ client = client_class(client_options=options)
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host=client.DEFAULT_ENDPOINT,
+ scopes=["1", "2"],
+ ssl_channel_credentials=None,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+
+@pytest.mark.parametrize(
+ "client_class,transport_class,transport_name",
+ [
+ (CloudBillingClient, transports.CloudBillingGrpcTransport, "grpc"),
+ (
+ CloudBillingAsyncClient,
+ transports.CloudBillingGrpcAsyncIOTransport,
+ "grpc_asyncio",
+ ),
+ ],
+)
+def test_cloud_billing_client_client_options_credentials_file(
+ client_class, transport_class, transport_name
+):
+ # Check the case credentials file is provided.
+ options = client_options.ClientOptions(credentials_file="credentials.json")
+ with mock.patch.object(transport_class, "__init__") as patched:
+ patched.return_value = None
+ client = client_class(client_options=options)
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file="credentials.json",
+ host=client.DEFAULT_ENDPOINT,
+ scopes=None,
+ ssl_channel_credentials=None,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+
+def test_cloud_billing_client_client_options_from_dict():
+ with mock.patch(
+ "google.cloud.billing_v1.services.cloud_billing.transports.CloudBillingGrpcTransport.__init__"
+ ) as grpc_transport:
+ grpc_transport.return_value = None
+ client = CloudBillingClient(client_options={"api_endpoint": "squid.clam.whelk"})
+ grpc_transport.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host="squid.clam.whelk",
+ scopes=None,
+ ssl_channel_credentials=None,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+
+def test_get_billing_account(
+ transport: str = "grpc", request_type=cloud_billing.GetBillingAccountRequest
+):
+ client = CloudBillingClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.get_billing_account), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.BillingAccount(
+ name="name_value",
+ open_=True,
+ display_name="display_name_value",
+ master_billing_account="master_billing_account_value",
+ )
+
+ response = client.get_billing_account(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_billing.GetBillingAccountRequest()
+
+ # Establish that the response is the type that we expect.
+
+ assert isinstance(response, cloud_billing.BillingAccount)
+
+ assert response.name == "name_value"
+
+ assert response.open_ is True
+
+ assert response.display_name == "display_name_value"
+
+ assert response.master_billing_account == "master_billing_account_value"
+
+
+def test_get_billing_account_from_dict():
+ test_get_billing_account(request_type=dict)
+
+
+@pytest.mark.asyncio
+async def test_get_billing_account_async(
+ transport: str = "grpc_asyncio", request_type=cloud_billing.GetBillingAccountRequest
+):
+ client = CloudBillingAsyncClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.get_billing_account), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.BillingAccount(
+ name="name_value",
+ open_=True,
+ display_name="display_name_value",
+ master_billing_account="master_billing_account_value",
+ )
+ )
+
+ response = await client.get_billing_account(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_billing.GetBillingAccountRequest()
+
+ # Establish that the response is the type that we expect.
+ assert isinstance(response, cloud_billing.BillingAccount)
+
+ assert response.name == "name_value"
+
+ assert response.open_ is True
+
+ assert response.display_name == "display_name_value"
+
+ assert response.master_billing_account == "master_billing_account_value"
+
+
+@pytest.mark.asyncio
+async def test_get_billing_account_async_from_dict():
+ await test_get_billing_account_async(request_type=dict)
+
+
+def test_get_billing_account_field_headers():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = cloud_billing.GetBillingAccountRequest()
+ request.name = "name/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.get_billing_account), "__call__"
+ ) as call:
+ call.return_value = cloud_billing.BillingAccount()
+
+ client.get_billing_account(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "name=name/value",) in kw["metadata"]
+
+
+@pytest.mark.asyncio
+async def test_get_billing_account_field_headers_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = cloud_billing.GetBillingAccountRequest()
+ request.name = "name/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.get_billing_account), "__call__"
+ ) as call:
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.BillingAccount()
+ )
+
+ await client.get_billing_account(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "name=name/value",) in kw["metadata"]
+
+
+def test_get_billing_account_flattened():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.get_billing_account), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.BillingAccount()
+
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ client.get_billing_account(name="name_value",)
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].name == "name_value"
+
+
+def test_get_billing_account_flattened_error():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ client.get_billing_account(
+ cloud_billing.GetBillingAccountRequest(), name="name_value",
+ )
+
+
+@pytest.mark.asyncio
+async def test_get_billing_account_flattened_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.get_billing_account), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.BillingAccount()
+
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.BillingAccount()
+ )
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ response = await client.get_billing_account(name="name_value",)
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].name == "name_value"
+
+
+@pytest.mark.asyncio
+async def test_get_billing_account_flattened_error_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ await client.get_billing_account(
+ cloud_billing.GetBillingAccountRequest(), name="name_value",
+ )
+
+
+def test_list_billing_accounts(
+ transport: str = "grpc", request_type=cloud_billing.ListBillingAccountsRequest
+):
+ client = CloudBillingClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_billing_accounts), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.ListBillingAccountsResponse(
+ next_page_token="next_page_token_value",
+ )
+
+ response = client.list_billing_accounts(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_billing.ListBillingAccountsRequest()
+
+ # Establish that the response is the type that we expect.
+
+ assert isinstance(response, pagers.ListBillingAccountsPager)
+
+ assert response.next_page_token == "next_page_token_value"
+
+
+def test_list_billing_accounts_from_dict():
+ test_list_billing_accounts(request_type=dict)
+
+
+@pytest.mark.asyncio
+async def test_list_billing_accounts_async(
+ transport: str = "grpc_asyncio",
+ request_type=cloud_billing.ListBillingAccountsRequest,
+):
+ client = CloudBillingAsyncClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_billing_accounts), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.ListBillingAccountsResponse(
+ next_page_token="next_page_token_value",
+ )
+ )
+
+ response = await client.list_billing_accounts(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_billing.ListBillingAccountsRequest()
+
+ # Establish that the response is the type that we expect.
+ assert isinstance(response, pagers.ListBillingAccountsAsyncPager)
+
+ assert response.next_page_token == "next_page_token_value"
+
+
+@pytest.mark.asyncio
+async def test_list_billing_accounts_async_from_dict():
+ await test_list_billing_accounts_async(request_type=dict)
+
+
+def test_list_billing_accounts_pager():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials,)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_billing_accounts), "__call__"
+ ) as call:
+ # Set the response to a series of pages.
+ call.side_effect = (
+ cloud_billing.ListBillingAccountsResponse(
+ billing_accounts=[
+ cloud_billing.BillingAccount(),
+ cloud_billing.BillingAccount(),
+ cloud_billing.BillingAccount(),
+ ],
+ next_page_token="abc",
+ ),
+ cloud_billing.ListBillingAccountsResponse(
+ billing_accounts=[], next_page_token="def",
+ ),
+ cloud_billing.ListBillingAccountsResponse(
+ billing_accounts=[cloud_billing.BillingAccount(),],
+ next_page_token="ghi",
+ ),
+ cloud_billing.ListBillingAccountsResponse(
+ billing_accounts=[
+ cloud_billing.BillingAccount(),
+ cloud_billing.BillingAccount(),
+ ],
+ ),
+ RuntimeError,
+ )
+
+ metadata = ()
+ pager = client.list_billing_accounts(request={})
+
+ assert pager._metadata == metadata
+
+ results = [i for i in pager]
+ assert len(results) == 6
+ assert all(isinstance(i, cloud_billing.BillingAccount) for i in results)
+
+
+def test_list_billing_accounts_pages():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials,)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_billing_accounts), "__call__"
+ ) as call:
+ # Set the response to a series of pages.
+ call.side_effect = (
+ cloud_billing.ListBillingAccountsResponse(
+ billing_accounts=[
+ cloud_billing.BillingAccount(),
+ cloud_billing.BillingAccount(),
+ cloud_billing.BillingAccount(),
+ ],
+ next_page_token="abc",
+ ),
+ cloud_billing.ListBillingAccountsResponse(
+ billing_accounts=[], next_page_token="def",
+ ),
+ cloud_billing.ListBillingAccountsResponse(
+ billing_accounts=[cloud_billing.BillingAccount(),],
+ next_page_token="ghi",
+ ),
+ cloud_billing.ListBillingAccountsResponse(
+ billing_accounts=[
+ cloud_billing.BillingAccount(),
+ cloud_billing.BillingAccount(),
+ ],
+ ),
+ RuntimeError,
+ )
+ pages = list(client.list_billing_accounts(request={}).pages)
+ for page_, token in zip(pages, ["abc", "def", "ghi", ""]):
+ assert page_.raw_page.next_page_token == token
+
+
+@pytest.mark.asyncio
+async def test_list_billing_accounts_async_pager():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials,)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_billing_accounts),
+ "__call__",
+ new_callable=mock.AsyncMock,
+ ) as call:
+ # Set the response to a series of pages.
+ call.side_effect = (
+ cloud_billing.ListBillingAccountsResponse(
+ billing_accounts=[
+ cloud_billing.BillingAccount(),
+ cloud_billing.BillingAccount(),
+ cloud_billing.BillingAccount(),
+ ],
+ next_page_token="abc",
+ ),
+ cloud_billing.ListBillingAccountsResponse(
+ billing_accounts=[], next_page_token="def",
+ ),
+ cloud_billing.ListBillingAccountsResponse(
+ billing_accounts=[cloud_billing.BillingAccount(),],
+ next_page_token="ghi",
+ ),
+ cloud_billing.ListBillingAccountsResponse(
+ billing_accounts=[
+ cloud_billing.BillingAccount(),
+ cloud_billing.BillingAccount(),
+ ],
+ ),
+ RuntimeError,
+ )
+ async_pager = await client.list_billing_accounts(request={},)
+ assert async_pager.next_page_token == "abc"
+ responses = []
+ async for response in async_pager:
+ responses.append(response)
+
+ assert len(responses) == 6
+ assert all(isinstance(i, cloud_billing.BillingAccount) for i in responses)
+
+
+@pytest.mark.asyncio
+async def test_list_billing_accounts_async_pages():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials,)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_billing_accounts),
+ "__call__",
+ new_callable=mock.AsyncMock,
+ ) as call:
+ # Set the response to a series of pages.
+ call.side_effect = (
+ cloud_billing.ListBillingAccountsResponse(
+ billing_accounts=[
+ cloud_billing.BillingAccount(),
+ cloud_billing.BillingAccount(),
+ cloud_billing.BillingAccount(),
+ ],
+ next_page_token="abc",
+ ),
+ cloud_billing.ListBillingAccountsResponse(
+ billing_accounts=[], next_page_token="def",
+ ),
+ cloud_billing.ListBillingAccountsResponse(
+ billing_accounts=[cloud_billing.BillingAccount(),],
+ next_page_token="ghi",
+ ),
+ cloud_billing.ListBillingAccountsResponse(
+ billing_accounts=[
+ cloud_billing.BillingAccount(),
+ cloud_billing.BillingAccount(),
+ ],
+ ),
+ RuntimeError,
+ )
+ pages = []
+ async for page_ in (await client.list_billing_accounts(request={})).pages:
+ pages.append(page_)
+ for page_, token in zip(pages, ["abc", "def", "ghi", ""]):
+ assert page_.raw_page.next_page_token == token
+
+
+def test_update_billing_account(
+ transport: str = "grpc", request_type=cloud_billing.UpdateBillingAccountRequest
+):
+ client = CloudBillingClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.update_billing_account), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.BillingAccount(
+ name="name_value",
+ open_=True,
+ display_name="display_name_value",
+ master_billing_account="master_billing_account_value",
+ )
+
+ response = client.update_billing_account(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_billing.UpdateBillingAccountRequest()
+
+ # Establish that the response is the type that we expect.
+
+ assert isinstance(response, cloud_billing.BillingAccount)
+
+ assert response.name == "name_value"
+
+ assert response.open_ is True
+
+ assert response.display_name == "display_name_value"
+
+ assert response.master_billing_account == "master_billing_account_value"
+
+
+def test_update_billing_account_from_dict():
+ test_update_billing_account(request_type=dict)
+
+
+@pytest.mark.asyncio
+async def test_update_billing_account_async(
+ transport: str = "grpc_asyncio",
+ request_type=cloud_billing.UpdateBillingAccountRequest,
+):
+ client = CloudBillingAsyncClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.update_billing_account), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.BillingAccount(
+ name="name_value",
+ open_=True,
+ display_name="display_name_value",
+ master_billing_account="master_billing_account_value",
+ )
+ )
+
+ response = await client.update_billing_account(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_billing.UpdateBillingAccountRequest()
+
+ # Establish that the response is the type that we expect.
+ assert isinstance(response, cloud_billing.BillingAccount)
+
+ assert response.name == "name_value"
+
+ assert response.open_ is True
+
+ assert response.display_name == "display_name_value"
+
+ assert response.master_billing_account == "master_billing_account_value"
+
+
+@pytest.mark.asyncio
+async def test_update_billing_account_async_from_dict():
+ await test_update_billing_account_async(request_type=dict)
+
+
+def test_update_billing_account_field_headers():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = cloud_billing.UpdateBillingAccountRequest()
+ request.name = "name/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.update_billing_account), "__call__"
+ ) as call:
+ call.return_value = cloud_billing.BillingAccount()
+
+ client.update_billing_account(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "name=name/value",) in kw["metadata"]
+
+
+@pytest.mark.asyncio
+async def test_update_billing_account_field_headers_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = cloud_billing.UpdateBillingAccountRequest()
+ request.name = "name/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.update_billing_account), "__call__"
+ ) as call:
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.BillingAccount()
+ )
+
+ await client.update_billing_account(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "name=name/value",) in kw["metadata"]
+
+
+def test_update_billing_account_flattened():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.update_billing_account), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.BillingAccount()
+
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ client.update_billing_account(
+ name="name_value", account=cloud_billing.BillingAccount(name="name_value"),
+ )
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].name == "name_value"
+
+ assert args[0].account == cloud_billing.BillingAccount(name="name_value")
+
+
+def test_update_billing_account_flattened_error():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ client.update_billing_account(
+ cloud_billing.UpdateBillingAccountRequest(),
+ name="name_value",
+ account=cloud_billing.BillingAccount(name="name_value"),
+ )
+
+
+@pytest.mark.asyncio
+async def test_update_billing_account_flattened_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.update_billing_account), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.BillingAccount()
+
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.BillingAccount()
+ )
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ response = await client.update_billing_account(
+ name="name_value", account=cloud_billing.BillingAccount(name="name_value"),
+ )
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].name == "name_value"
+
+ assert args[0].account == cloud_billing.BillingAccount(name="name_value")
+
+
+@pytest.mark.asyncio
+async def test_update_billing_account_flattened_error_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ await client.update_billing_account(
+ cloud_billing.UpdateBillingAccountRequest(),
+ name="name_value",
+ account=cloud_billing.BillingAccount(name="name_value"),
+ )
+
+
+def test_create_billing_account(
+ transport: str = "grpc", request_type=cloud_billing.CreateBillingAccountRequest
+):
+ client = CloudBillingClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.create_billing_account), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.BillingAccount(
+ name="name_value",
+ open_=True,
+ display_name="display_name_value",
+ master_billing_account="master_billing_account_value",
+ )
+
+ response = client.create_billing_account(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_billing.CreateBillingAccountRequest()
+
+ # Establish that the response is the type that we expect.
+
+ assert isinstance(response, cloud_billing.BillingAccount)
+
+ assert response.name == "name_value"
+
+ assert response.open_ is True
+
+ assert response.display_name == "display_name_value"
+
+ assert response.master_billing_account == "master_billing_account_value"
+
+
+def test_create_billing_account_from_dict():
+ test_create_billing_account(request_type=dict)
+
+
+@pytest.mark.asyncio
+async def test_create_billing_account_async(
+ transport: str = "grpc_asyncio",
+ request_type=cloud_billing.CreateBillingAccountRequest,
+):
+ client = CloudBillingAsyncClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.create_billing_account), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.BillingAccount(
+ name="name_value",
+ open_=True,
+ display_name="display_name_value",
+ master_billing_account="master_billing_account_value",
+ )
+ )
+
+ response = await client.create_billing_account(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_billing.CreateBillingAccountRequest()
+
+ # Establish that the response is the type that we expect.
+ assert isinstance(response, cloud_billing.BillingAccount)
+
+ assert response.name == "name_value"
+
+ assert response.open_ is True
+
+ assert response.display_name == "display_name_value"
+
+ assert response.master_billing_account == "master_billing_account_value"
+
+
+@pytest.mark.asyncio
+async def test_create_billing_account_async_from_dict():
+ await test_create_billing_account_async(request_type=dict)
+
+
+def test_create_billing_account_flattened():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.create_billing_account), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.BillingAccount()
+
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ client.create_billing_account(
+ billing_account=cloud_billing.BillingAccount(name="name_value"),
+ )
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].billing_account == cloud_billing.BillingAccount(
+ name="name_value"
+ )
+
+
+def test_create_billing_account_flattened_error():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ client.create_billing_account(
+ cloud_billing.CreateBillingAccountRequest(),
+ billing_account=cloud_billing.BillingAccount(name="name_value"),
+ )
+
+
+@pytest.mark.asyncio
+async def test_create_billing_account_flattened_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.create_billing_account), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.BillingAccount()
+
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.BillingAccount()
+ )
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ response = await client.create_billing_account(
+ billing_account=cloud_billing.BillingAccount(name="name_value"),
+ )
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].billing_account == cloud_billing.BillingAccount(
+ name="name_value"
+ )
+
+
+@pytest.mark.asyncio
+async def test_create_billing_account_flattened_error_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ await client.create_billing_account(
+ cloud_billing.CreateBillingAccountRequest(),
+ billing_account=cloud_billing.BillingAccount(name="name_value"),
+ )
+
+
+def test_list_project_billing_info(
+ transport: str = "grpc", request_type=cloud_billing.ListProjectBillingInfoRequest
+):
+ client = CloudBillingClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_project_billing_info), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.ListProjectBillingInfoResponse(
+ next_page_token="next_page_token_value",
+ )
+
+ response = client.list_project_billing_info(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_billing.ListProjectBillingInfoRequest()
+
+ # Establish that the response is the type that we expect.
+
+ assert isinstance(response, pagers.ListProjectBillingInfoPager)
+
+ assert response.next_page_token == "next_page_token_value"
+
+
+def test_list_project_billing_info_from_dict():
+ test_list_project_billing_info(request_type=dict)
+
+
+@pytest.mark.asyncio
+async def test_list_project_billing_info_async(
+ transport: str = "grpc_asyncio",
+ request_type=cloud_billing.ListProjectBillingInfoRequest,
+):
+ client = CloudBillingAsyncClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_project_billing_info), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.ListProjectBillingInfoResponse(
+ next_page_token="next_page_token_value",
+ )
+ )
+
+ response = await client.list_project_billing_info(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_billing.ListProjectBillingInfoRequest()
+
+ # Establish that the response is the type that we expect.
+ assert isinstance(response, pagers.ListProjectBillingInfoAsyncPager)
+
+ assert response.next_page_token == "next_page_token_value"
+
+
+@pytest.mark.asyncio
+async def test_list_project_billing_info_async_from_dict():
+ await test_list_project_billing_info_async(request_type=dict)
+
+
+def test_list_project_billing_info_field_headers():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = cloud_billing.ListProjectBillingInfoRequest()
+ request.name = "name/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_project_billing_info), "__call__"
+ ) as call:
+ call.return_value = cloud_billing.ListProjectBillingInfoResponse()
+
+ client.list_project_billing_info(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "name=name/value",) in kw["metadata"]
+
+
+@pytest.mark.asyncio
+async def test_list_project_billing_info_field_headers_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = cloud_billing.ListProjectBillingInfoRequest()
+ request.name = "name/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_project_billing_info), "__call__"
+ ) as call:
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.ListProjectBillingInfoResponse()
+ )
+
+ await client.list_project_billing_info(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "name=name/value",) in kw["metadata"]
+
+
+def test_list_project_billing_info_flattened():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_project_billing_info), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.ListProjectBillingInfoResponse()
+
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ client.list_project_billing_info(name="name_value",)
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].name == "name_value"
+
+
+def test_list_project_billing_info_flattened_error():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ client.list_project_billing_info(
+ cloud_billing.ListProjectBillingInfoRequest(), name="name_value",
+ )
+
+
+@pytest.mark.asyncio
+async def test_list_project_billing_info_flattened_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_project_billing_info), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.ListProjectBillingInfoResponse()
+
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.ListProjectBillingInfoResponse()
+ )
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ response = await client.list_project_billing_info(name="name_value",)
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].name == "name_value"
+
+
+@pytest.mark.asyncio
+async def test_list_project_billing_info_flattened_error_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ await client.list_project_billing_info(
+ cloud_billing.ListProjectBillingInfoRequest(), name="name_value",
+ )
+
+
+def test_list_project_billing_info_pager():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials,)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_project_billing_info), "__call__"
+ ) as call:
+ # Set the response to a series of pages.
+ call.side_effect = (
+ cloud_billing.ListProjectBillingInfoResponse(
+ project_billing_info=[
+ cloud_billing.ProjectBillingInfo(),
+ cloud_billing.ProjectBillingInfo(),
+ cloud_billing.ProjectBillingInfo(),
+ ],
+ next_page_token="abc",
+ ),
+ cloud_billing.ListProjectBillingInfoResponse(
+ project_billing_info=[], next_page_token="def",
+ ),
+ cloud_billing.ListProjectBillingInfoResponse(
+ project_billing_info=[cloud_billing.ProjectBillingInfo(),],
+ next_page_token="ghi",
+ ),
+ cloud_billing.ListProjectBillingInfoResponse(
+ project_billing_info=[
+ cloud_billing.ProjectBillingInfo(),
+ cloud_billing.ProjectBillingInfo(),
+ ],
+ ),
+ RuntimeError,
+ )
+
+ metadata = ()
+ metadata = tuple(metadata) + (
+ gapic_v1.routing_header.to_grpc_metadata((("name", ""),)),
+ )
+ pager = client.list_project_billing_info(request={})
+
+ assert pager._metadata == metadata
+
+ results = [i for i in pager]
+ assert len(results) == 6
+ assert all(isinstance(i, cloud_billing.ProjectBillingInfo) for i in results)
+
+
+def test_list_project_billing_info_pages():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials,)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_project_billing_info), "__call__"
+ ) as call:
+ # Set the response to a series of pages.
+ call.side_effect = (
+ cloud_billing.ListProjectBillingInfoResponse(
+ project_billing_info=[
+ cloud_billing.ProjectBillingInfo(),
+ cloud_billing.ProjectBillingInfo(),
+ cloud_billing.ProjectBillingInfo(),
+ ],
+ next_page_token="abc",
+ ),
+ cloud_billing.ListProjectBillingInfoResponse(
+ project_billing_info=[], next_page_token="def",
+ ),
+ cloud_billing.ListProjectBillingInfoResponse(
+ project_billing_info=[cloud_billing.ProjectBillingInfo(),],
+ next_page_token="ghi",
+ ),
+ cloud_billing.ListProjectBillingInfoResponse(
+ project_billing_info=[
+ cloud_billing.ProjectBillingInfo(),
+ cloud_billing.ProjectBillingInfo(),
+ ],
+ ),
+ RuntimeError,
+ )
+ pages = list(client.list_project_billing_info(request={}).pages)
+ for page_, token in zip(pages, ["abc", "def", "ghi", ""]):
+ assert page_.raw_page.next_page_token == token
+
+
+@pytest.mark.asyncio
+async def test_list_project_billing_info_async_pager():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials,)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_project_billing_info),
+ "__call__",
+ new_callable=mock.AsyncMock,
+ ) as call:
+ # Set the response to a series of pages.
+ call.side_effect = (
+ cloud_billing.ListProjectBillingInfoResponse(
+ project_billing_info=[
+ cloud_billing.ProjectBillingInfo(),
+ cloud_billing.ProjectBillingInfo(),
+ cloud_billing.ProjectBillingInfo(),
+ ],
+ next_page_token="abc",
+ ),
+ cloud_billing.ListProjectBillingInfoResponse(
+ project_billing_info=[], next_page_token="def",
+ ),
+ cloud_billing.ListProjectBillingInfoResponse(
+ project_billing_info=[cloud_billing.ProjectBillingInfo(),],
+ next_page_token="ghi",
+ ),
+ cloud_billing.ListProjectBillingInfoResponse(
+ project_billing_info=[
+ cloud_billing.ProjectBillingInfo(),
+ cloud_billing.ProjectBillingInfo(),
+ ],
+ ),
+ RuntimeError,
+ )
+ async_pager = await client.list_project_billing_info(request={},)
+ assert async_pager.next_page_token == "abc"
+ responses = []
+ async for response in async_pager:
+ responses.append(response)
+
+ assert len(responses) == 6
+ assert all(isinstance(i, cloud_billing.ProjectBillingInfo) for i in responses)
+
+
+@pytest.mark.asyncio
+async def test_list_project_billing_info_async_pages():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials,)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_project_billing_info),
+ "__call__",
+ new_callable=mock.AsyncMock,
+ ) as call:
+ # Set the response to a series of pages.
+ call.side_effect = (
+ cloud_billing.ListProjectBillingInfoResponse(
+ project_billing_info=[
+ cloud_billing.ProjectBillingInfo(),
+ cloud_billing.ProjectBillingInfo(),
+ cloud_billing.ProjectBillingInfo(),
+ ],
+ next_page_token="abc",
+ ),
+ cloud_billing.ListProjectBillingInfoResponse(
+ project_billing_info=[], next_page_token="def",
+ ),
+ cloud_billing.ListProjectBillingInfoResponse(
+ project_billing_info=[cloud_billing.ProjectBillingInfo(),],
+ next_page_token="ghi",
+ ),
+ cloud_billing.ListProjectBillingInfoResponse(
+ project_billing_info=[
+ cloud_billing.ProjectBillingInfo(),
+ cloud_billing.ProjectBillingInfo(),
+ ],
+ ),
+ RuntimeError,
+ )
+ pages = []
+ async for page_ in (await client.list_project_billing_info(request={})).pages:
+ pages.append(page_)
+ for page_, token in zip(pages, ["abc", "def", "ghi", ""]):
+ assert page_.raw_page.next_page_token == token
+
+
+def test_get_project_billing_info(
+ transport: str = "grpc", request_type=cloud_billing.GetProjectBillingInfoRequest
+):
+ client = CloudBillingClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.get_project_billing_info), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.ProjectBillingInfo(
+ name="name_value",
+ project_id="project_id_value",
+ billing_account_name="billing_account_name_value",
+ billing_enabled=True,
+ )
+
+ response = client.get_project_billing_info(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_billing.GetProjectBillingInfoRequest()
+
+ # Establish that the response is the type that we expect.
+
+ assert isinstance(response, cloud_billing.ProjectBillingInfo)
+
+ assert response.name == "name_value"
+
+ assert response.project_id == "project_id_value"
+
+ assert response.billing_account_name == "billing_account_name_value"
+
+ assert response.billing_enabled is True
+
+
+def test_get_project_billing_info_from_dict():
+ test_get_project_billing_info(request_type=dict)
+
+
+@pytest.mark.asyncio
+async def test_get_project_billing_info_async(
+ transport: str = "grpc_asyncio",
+ request_type=cloud_billing.GetProjectBillingInfoRequest,
+):
+ client = CloudBillingAsyncClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.get_project_billing_info), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.ProjectBillingInfo(
+ name="name_value",
+ project_id="project_id_value",
+ billing_account_name="billing_account_name_value",
+ billing_enabled=True,
+ )
+ )
+
+ response = await client.get_project_billing_info(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_billing.GetProjectBillingInfoRequest()
+
+ # Establish that the response is the type that we expect.
+ assert isinstance(response, cloud_billing.ProjectBillingInfo)
+
+ assert response.name == "name_value"
+
+ assert response.project_id == "project_id_value"
+
+ assert response.billing_account_name == "billing_account_name_value"
+
+ assert response.billing_enabled is True
+
+
+@pytest.mark.asyncio
+async def test_get_project_billing_info_async_from_dict():
+ await test_get_project_billing_info_async(request_type=dict)
+
+
+def test_get_project_billing_info_field_headers():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = cloud_billing.GetProjectBillingInfoRequest()
+ request.name = "name/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.get_project_billing_info), "__call__"
+ ) as call:
+ call.return_value = cloud_billing.ProjectBillingInfo()
+
+ client.get_project_billing_info(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "name=name/value",) in kw["metadata"]
+
+
+@pytest.mark.asyncio
+async def test_get_project_billing_info_field_headers_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = cloud_billing.GetProjectBillingInfoRequest()
+ request.name = "name/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.get_project_billing_info), "__call__"
+ ) as call:
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.ProjectBillingInfo()
+ )
+
+ await client.get_project_billing_info(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "name=name/value",) in kw["metadata"]
+
+
+def test_get_project_billing_info_flattened():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.get_project_billing_info), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.ProjectBillingInfo()
+
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ client.get_project_billing_info(name="name_value",)
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].name == "name_value"
+
+
+def test_get_project_billing_info_flattened_error():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ client.get_project_billing_info(
+ cloud_billing.GetProjectBillingInfoRequest(), name="name_value",
+ )
+
+
+@pytest.mark.asyncio
+async def test_get_project_billing_info_flattened_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.get_project_billing_info), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.ProjectBillingInfo()
+
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.ProjectBillingInfo()
+ )
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ response = await client.get_project_billing_info(name="name_value",)
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].name == "name_value"
+
+
+@pytest.mark.asyncio
+async def test_get_project_billing_info_flattened_error_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ await client.get_project_billing_info(
+ cloud_billing.GetProjectBillingInfoRequest(), name="name_value",
+ )
+
+
+def test_update_project_billing_info(
+ transport: str = "grpc", request_type=cloud_billing.UpdateProjectBillingInfoRequest
+):
+ client = CloudBillingClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.update_project_billing_info), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.ProjectBillingInfo(
+ name="name_value",
+ project_id="project_id_value",
+ billing_account_name="billing_account_name_value",
+ billing_enabled=True,
+ )
+
+ response = client.update_project_billing_info(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_billing.UpdateProjectBillingInfoRequest()
+
+ # Establish that the response is the type that we expect.
+
+ assert isinstance(response, cloud_billing.ProjectBillingInfo)
+
+ assert response.name == "name_value"
+
+ assert response.project_id == "project_id_value"
+
+ assert response.billing_account_name == "billing_account_name_value"
+
+ assert response.billing_enabled is True
+
+
+def test_update_project_billing_info_from_dict():
+ test_update_project_billing_info(request_type=dict)
+
+
+@pytest.mark.asyncio
+async def test_update_project_billing_info_async(
+ transport: str = "grpc_asyncio",
+ request_type=cloud_billing.UpdateProjectBillingInfoRequest,
+):
+ client = CloudBillingAsyncClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.update_project_billing_info), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.ProjectBillingInfo(
+ name="name_value",
+ project_id="project_id_value",
+ billing_account_name="billing_account_name_value",
+ billing_enabled=True,
+ )
+ )
+
+ response = await client.update_project_billing_info(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_billing.UpdateProjectBillingInfoRequest()
+
+ # Establish that the response is the type that we expect.
+ assert isinstance(response, cloud_billing.ProjectBillingInfo)
+
+ assert response.name == "name_value"
+
+ assert response.project_id == "project_id_value"
+
+ assert response.billing_account_name == "billing_account_name_value"
+
+ assert response.billing_enabled is True
+
+
+@pytest.mark.asyncio
+async def test_update_project_billing_info_async_from_dict():
+ await test_update_project_billing_info_async(request_type=dict)
+
+
+def test_update_project_billing_info_field_headers():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = cloud_billing.UpdateProjectBillingInfoRequest()
+ request.name = "name/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.update_project_billing_info), "__call__"
+ ) as call:
+ call.return_value = cloud_billing.ProjectBillingInfo()
+
+ client.update_project_billing_info(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "name=name/value",) in kw["metadata"]
+
+
+@pytest.mark.asyncio
+async def test_update_project_billing_info_field_headers_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = cloud_billing.UpdateProjectBillingInfoRequest()
+ request.name = "name/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.update_project_billing_info), "__call__"
+ ) as call:
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.ProjectBillingInfo()
+ )
+
+ await client.update_project_billing_info(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "name=name/value",) in kw["metadata"]
+
+
+def test_update_project_billing_info_flattened():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.update_project_billing_info), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.ProjectBillingInfo()
+
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ client.update_project_billing_info(
+ name="name_value",
+ project_billing_info=cloud_billing.ProjectBillingInfo(name="name_value"),
+ )
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].name == "name_value"
+
+ assert args[0].project_billing_info == cloud_billing.ProjectBillingInfo(
+ name="name_value"
+ )
+
+
+def test_update_project_billing_info_flattened_error():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ client.update_project_billing_info(
+ cloud_billing.UpdateProjectBillingInfoRequest(),
+ name="name_value",
+ project_billing_info=cloud_billing.ProjectBillingInfo(name="name_value"),
+ )
+
+
+@pytest.mark.asyncio
+async def test_update_project_billing_info_flattened_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.update_project_billing_info), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_billing.ProjectBillingInfo()
+
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_billing.ProjectBillingInfo()
+ )
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ response = await client.update_project_billing_info(
+ name="name_value",
+ project_billing_info=cloud_billing.ProjectBillingInfo(name="name_value"),
+ )
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].name == "name_value"
+
+ assert args[0].project_billing_info == cloud_billing.ProjectBillingInfo(
+ name="name_value"
+ )
+
+
+@pytest.mark.asyncio
+async def test_update_project_billing_info_flattened_error_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ await client.update_project_billing_info(
+ cloud_billing.UpdateProjectBillingInfoRequest(),
+ name="name_value",
+ project_billing_info=cloud_billing.ProjectBillingInfo(name="name_value"),
+ )
+
+
+def test_get_iam_policy(
+ transport: str = "grpc", request_type=iam_policy.GetIamPolicyRequest
+):
+ client = CloudBillingClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = policy.Policy(version=774, etag=b"etag_blob",)
+
+ response = client.get_iam_policy(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == iam_policy.GetIamPolicyRequest()
+
+ # Establish that the response is the type that we expect.
+
+ assert isinstance(response, policy.Policy)
+
+ assert response.version == 774
+
+ assert response.etag == b"etag_blob"
+
+
+def test_get_iam_policy_from_dict():
+ test_get_iam_policy(request_type=dict)
+
+
+@pytest.mark.asyncio
+async def test_get_iam_policy_async(
+ transport: str = "grpc_asyncio", request_type=iam_policy.GetIamPolicyRequest
+):
+ client = CloudBillingAsyncClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ policy.Policy(version=774, etag=b"etag_blob",)
+ )
+
+ response = await client.get_iam_policy(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == iam_policy.GetIamPolicyRequest()
+
+ # Establish that the response is the type that we expect.
+ assert isinstance(response, policy.Policy)
+
+ assert response.version == 774
+
+ assert response.etag == b"etag_blob"
+
+
+@pytest.mark.asyncio
+async def test_get_iam_policy_async_from_dict():
+ await test_get_iam_policy_async(request_type=dict)
+
+
+def test_get_iam_policy_field_headers():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = iam_policy.GetIamPolicyRequest()
+ request.resource = "resource/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call:
+ call.return_value = policy.Policy()
+
+ client.get_iam_policy(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "resource=resource/value",) in kw["metadata"]
+
+
+@pytest.mark.asyncio
+async def test_get_iam_policy_field_headers_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = iam_policy.GetIamPolicyRequest()
+ request.resource = "resource/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call:
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(policy.Policy())
+
+ await client.get_iam_policy(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "resource=resource/value",) in kw["metadata"]
+
+
+def test_get_iam_policy_from_dict_foreign():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = policy.Policy()
+
+ response = client.get_iam_policy(
+ request={
+ "resource": "resource_value",
+ "options": options.GetPolicyOptions(requested_policy_version=2598),
+ }
+ )
+ call.assert_called()
+
+
+def test_get_iam_policy_flattened():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = policy.Policy()
+
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ client.get_iam_policy(resource="resource_value",)
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].resource == "resource_value"
+
+
+def test_get_iam_policy_flattened_error():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ client.get_iam_policy(
+ iam_policy.GetIamPolicyRequest(), resource="resource_value",
+ )
+
+
+@pytest.mark.asyncio
+async def test_get_iam_policy_flattened_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = policy.Policy()
+
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(policy.Policy())
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ response = await client.get_iam_policy(resource="resource_value",)
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].resource == "resource_value"
+
+
+@pytest.mark.asyncio
+async def test_get_iam_policy_flattened_error_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ await client.get_iam_policy(
+ iam_policy.GetIamPolicyRequest(), resource="resource_value",
+ )
+
+
+def test_set_iam_policy(
+ transport: str = "grpc", request_type=iam_policy.SetIamPolicyRequest
+):
+ client = CloudBillingClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = policy.Policy(version=774, etag=b"etag_blob",)
+
+ response = client.set_iam_policy(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == iam_policy.SetIamPolicyRequest()
+
+ # Establish that the response is the type that we expect.
+
+ assert isinstance(response, policy.Policy)
+
+ assert response.version == 774
+
+ assert response.etag == b"etag_blob"
+
+
+def test_set_iam_policy_from_dict():
+ test_set_iam_policy(request_type=dict)
+
+
+@pytest.mark.asyncio
+async def test_set_iam_policy_async(
+ transport: str = "grpc_asyncio", request_type=iam_policy.SetIamPolicyRequest
+):
+ client = CloudBillingAsyncClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ policy.Policy(version=774, etag=b"etag_blob",)
+ )
+
+ response = await client.set_iam_policy(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == iam_policy.SetIamPolicyRequest()
+
+ # Establish that the response is the type that we expect.
+ assert isinstance(response, policy.Policy)
+
+ assert response.version == 774
+
+ assert response.etag == b"etag_blob"
+
+
+@pytest.mark.asyncio
+async def test_set_iam_policy_async_from_dict():
+ await test_set_iam_policy_async(request_type=dict)
+
+
+def test_set_iam_policy_field_headers():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = iam_policy.SetIamPolicyRequest()
+ request.resource = "resource/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call:
+ call.return_value = policy.Policy()
+
+ client.set_iam_policy(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "resource=resource/value",) in kw["metadata"]
+
+
+@pytest.mark.asyncio
+async def test_set_iam_policy_field_headers_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = iam_policy.SetIamPolicyRequest()
+ request.resource = "resource/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call:
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(policy.Policy())
+
+ await client.set_iam_policy(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "resource=resource/value",) in kw["metadata"]
+
+
+def test_set_iam_policy_from_dict_foreign():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = policy.Policy()
+
+ response = client.set_iam_policy(
+ request={
+ "resource": "resource_value",
+ "policy": policy.Policy(version=774),
+ }
+ )
+ call.assert_called()
+
+
+def test_set_iam_policy_flattened():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = policy.Policy()
+
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ client.set_iam_policy(resource="resource_value",)
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].resource == "resource_value"
+
+
+def test_set_iam_policy_flattened_error():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ client.set_iam_policy(
+ iam_policy.SetIamPolicyRequest(), resource="resource_value",
+ )
+
+
+@pytest.mark.asyncio
+async def test_set_iam_policy_flattened_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = policy.Policy()
+
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(policy.Policy())
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ response = await client.set_iam_policy(resource="resource_value",)
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].resource == "resource_value"
+
+
+@pytest.mark.asyncio
+async def test_set_iam_policy_flattened_error_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ await client.set_iam_policy(
+ iam_policy.SetIamPolicyRequest(), resource="resource_value",
+ )
+
+
+def test_test_iam_permissions(
+ transport: str = "grpc", request_type=iam_policy.TestIamPermissionsRequest
+):
+ client = CloudBillingClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.test_iam_permissions), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = iam_policy.TestIamPermissionsResponse(
+ permissions=["permissions_value"],
+ )
+
+ response = client.test_iam_permissions(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == iam_policy.TestIamPermissionsRequest()
+
+ # Establish that the response is the type that we expect.
+
+ assert isinstance(response, iam_policy.TestIamPermissionsResponse)
+
+ assert response.permissions == ["permissions_value"]
+
+
+def test_test_iam_permissions_from_dict():
+ test_test_iam_permissions(request_type=dict)
+
+
+@pytest.mark.asyncio
+async def test_test_iam_permissions_async(
+ transport: str = "grpc_asyncio", request_type=iam_policy.TestIamPermissionsRequest
+):
+ client = CloudBillingAsyncClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.test_iam_permissions), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ iam_policy.TestIamPermissionsResponse(permissions=["permissions_value"],)
+ )
+
+ response = await client.test_iam_permissions(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == iam_policy.TestIamPermissionsRequest()
+
+ # Establish that the response is the type that we expect.
+ assert isinstance(response, iam_policy.TestIamPermissionsResponse)
+
+ assert response.permissions == ["permissions_value"]
+
+
+@pytest.mark.asyncio
+async def test_test_iam_permissions_async_from_dict():
+ await test_test_iam_permissions_async(request_type=dict)
+
+
+def test_test_iam_permissions_field_headers():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = iam_policy.TestIamPermissionsRequest()
+ request.resource = "resource/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.test_iam_permissions), "__call__"
+ ) as call:
+ call.return_value = iam_policy.TestIamPermissionsResponse()
+
+ client.test_iam_permissions(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "resource=resource/value",) in kw["metadata"]
+
+
+@pytest.mark.asyncio
+async def test_test_iam_permissions_field_headers_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = iam_policy.TestIamPermissionsRequest()
+ request.resource = "resource/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.test_iam_permissions), "__call__"
+ ) as call:
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ iam_policy.TestIamPermissionsResponse()
+ )
+
+ await client.test_iam_permissions(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "resource=resource/value",) in kw["metadata"]
+
+
+def test_test_iam_permissions_from_dict_foreign():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.test_iam_permissions), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = iam_policy.TestIamPermissionsResponse()
+
+ response = client.test_iam_permissions(
+ request={
+ "resource": "resource_value",
+ "permissions": ["permissions_value"],
+ }
+ )
+ call.assert_called()
+
+
+def test_test_iam_permissions_flattened():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.test_iam_permissions), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = iam_policy.TestIamPermissionsResponse()
+
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ client.test_iam_permissions(
+ resource="resource_value", permissions=["permissions_value"],
+ )
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].resource == "resource_value"
+
+ assert args[0].permissions == ["permissions_value"]
+
+
+def test_test_iam_permissions_flattened_error():
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ client.test_iam_permissions(
+ iam_policy.TestIamPermissionsRequest(),
+ resource="resource_value",
+ permissions=["permissions_value"],
+ )
+
+
+@pytest.mark.asyncio
+async def test_test_iam_permissions_flattened_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.test_iam_permissions), "__call__"
+ ) as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = iam_policy.TestIamPermissionsResponse()
+
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ iam_policy.TestIamPermissionsResponse()
+ )
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ response = await client.test_iam_permissions(
+ resource="resource_value", permissions=["permissions_value"],
+ )
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].resource == "resource_value"
+
+ assert args[0].permissions == ["permissions_value"]
+
+
+@pytest.mark.asyncio
+async def test_test_iam_permissions_flattened_error_async():
+ client = CloudBillingAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ await client.test_iam_permissions(
+ iam_policy.TestIamPermissionsRequest(),
+ resource="resource_value",
+ permissions=["permissions_value"],
+ )
+
+
+def test_credentials_transport_error():
+ # It is an error to provide credentials and a transport instance.
+ transport = transports.CloudBillingGrpcTransport(
+ credentials=credentials.AnonymousCredentials(),
+ )
+ with pytest.raises(ValueError):
+ client = CloudBillingClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # It is an error to provide a credentials file and a transport instance.
+ transport = transports.CloudBillingGrpcTransport(
+ credentials=credentials.AnonymousCredentials(),
+ )
+ with pytest.raises(ValueError):
+ client = CloudBillingClient(
+ client_options={"credentials_file": "credentials.json"},
+ transport=transport,
+ )
+
+ # It is an error to provide scopes and a transport instance.
+ transport = transports.CloudBillingGrpcTransport(
+ credentials=credentials.AnonymousCredentials(),
+ )
+ with pytest.raises(ValueError):
+ client = CloudBillingClient(
+ client_options={"scopes": ["1", "2"]}, transport=transport,
+ )
+
+
+def test_transport_instance():
+ # A client may be instantiated with a custom transport instance.
+ transport = transports.CloudBillingGrpcTransport(
+ credentials=credentials.AnonymousCredentials(),
+ )
+ client = CloudBillingClient(transport=transport)
+ assert client.transport is transport
+
+
+def test_transport_get_channel():
+ # A client may be instantiated with a custom transport instance.
+ transport = transports.CloudBillingGrpcTransport(
+ credentials=credentials.AnonymousCredentials(),
+ )
+ channel = transport.grpc_channel
+ assert channel
+
+ transport = transports.CloudBillingGrpcAsyncIOTransport(
+ credentials=credentials.AnonymousCredentials(),
+ )
+ channel = transport.grpc_channel
+ assert channel
+
+
+@pytest.mark.parametrize(
+ "transport_class",
+ [transports.CloudBillingGrpcTransport, transports.CloudBillingGrpcAsyncIOTransport],
+)
+def test_transport_adc(transport_class):
+ # Test default credentials are used if not provided.
+ with mock.patch.object(auth, "default") as adc:
+ adc.return_value = (credentials.AnonymousCredentials(), None)
+ transport_class()
+ adc.assert_called_once()
+
+
+def test_transport_grpc_default():
+ # A client should use the gRPC transport by default.
+ client = CloudBillingClient(credentials=credentials.AnonymousCredentials(),)
+ assert isinstance(client.transport, transports.CloudBillingGrpcTransport,)
+
+
+def test_cloud_billing_base_transport_error():
+ # Passing both a credentials object and credentials_file should raise an error
+ with pytest.raises(exceptions.DuplicateCredentialArgs):
+ transport = transports.CloudBillingTransport(
+ credentials=credentials.AnonymousCredentials(),
+ credentials_file="credentials.json",
+ )
+
+
+def test_cloud_billing_base_transport():
+ # Instantiate the base transport.
+ with mock.patch(
+ "google.cloud.billing_v1.services.cloud_billing.transports.CloudBillingTransport.__init__"
+ ) as Transport:
+ Transport.return_value = None
+ transport = transports.CloudBillingTransport(
+ credentials=credentials.AnonymousCredentials(),
+ )
+
+ # Every method on the transport should just blindly
+ # raise NotImplementedError.
+ methods = (
+ "get_billing_account",
+ "list_billing_accounts",
+ "update_billing_account",
+ "create_billing_account",
+ "list_project_billing_info",
+ "get_project_billing_info",
+ "update_project_billing_info",
+ "get_iam_policy",
+ "set_iam_policy",
+ "test_iam_permissions",
+ )
+ for method in methods:
+ with pytest.raises(NotImplementedError):
+ getattr(transport, method)(request=object())
+
+
+def test_cloud_billing_base_transport_with_credentials_file():
+ # Instantiate the base transport with a credentials file
+ with mock.patch.object(
+ auth, "load_credentials_from_file"
+ ) as load_creds, mock.patch(
+ "google.cloud.billing_v1.services.cloud_billing.transports.CloudBillingTransport._prep_wrapped_messages"
+ ) as Transport:
+ Transport.return_value = None
+ load_creds.return_value = (credentials.AnonymousCredentials(), None)
+ transport = transports.CloudBillingTransport(
+ credentials_file="credentials.json", quota_project_id="octopus",
+ )
+ load_creds.assert_called_once_with(
+ "credentials.json",
+ scopes=("https://www.googleapis.com/auth/cloud-platform",),
+ quota_project_id="octopus",
+ )
+
+
+def test_cloud_billing_base_transport_with_adc():
+ # Test the default credentials are used if credentials and credentials_file are None.
+ with mock.patch.object(auth, "default") as adc, mock.patch(
+ "google.cloud.billing_v1.services.cloud_billing.transports.CloudBillingTransport._prep_wrapped_messages"
+ ) as Transport:
+ Transport.return_value = None
+ adc.return_value = (credentials.AnonymousCredentials(), None)
+ transport = transports.CloudBillingTransport()
+ adc.assert_called_once()
+
+
+def test_cloud_billing_auth_adc():
+ # If no credentials are provided, we should use ADC credentials.
+ with mock.patch.object(auth, "default") as adc:
+ adc.return_value = (credentials.AnonymousCredentials(), None)
+ CloudBillingClient()
+ adc.assert_called_once_with(
+ scopes=("https://www.googleapis.com/auth/cloud-platform",),
+ quota_project_id=None,
+ )
+
+
+def test_cloud_billing_transport_auth_adc():
+ # If credentials and host are not provided, the transport class should use
+ # ADC credentials.
+ with mock.patch.object(auth, "default") as adc:
+ adc.return_value = (credentials.AnonymousCredentials(), None)
+ transports.CloudBillingGrpcTransport(
+ host="squid.clam.whelk", quota_project_id="octopus"
+ )
+ adc.assert_called_once_with(
+ scopes=("https://www.googleapis.com/auth/cloud-platform",),
+ quota_project_id="octopus",
+ )
+
+
+def test_cloud_billing_host_no_port():
+ client = CloudBillingClient(
+ credentials=credentials.AnonymousCredentials(),
+ client_options=client_options.ClientOptions(
+ api_endpoint="cloudbilling.googleapis.com"
+ ),
+ )
+ assert client.transport._host == "cloudbilling.googleapis.com:443"
+
+
+def test_cloud_billing_host_with_port():
+ client = CloudBillingClient(
+ credentials=credentials.AnonymousCredentials(),
+ client_options=client_options.ClientOptions(
+ api_endpoint="cloudbilling.googleapis.com:8000"
+ ),
+ )
+ assert client.transport._host == "cloudbilling.googleapis.com:8000"
+
+
+def test_cloud_billing_grpc_transport_channel():
+ channel = grpc.insecure_channel("http://localhost/")
+
+ # Check that channel is used if provided.
+ transport = transports.CloudBillingGrpcTransport(
+ host="squid.clam.whelk", channel=channel,
+ )
+ assert transport.grpc_channel == channel
+ assert transport._host == "squid.clam.whelk:443"
+ assert transport._ssl_channel_credentials == None
+
+
+def test_cloud_billing_grpc_asyncio_transport_channel():
+ channel = aio.insecure_channel("http://localhost/")
+
+ # Check that channel is used if provided.
+ transport = transports.CloudBillingGrpcAsyncIOTransport(
+ host="squid.clam.whelk", channel=channel,
+ )
+ assert transport.grpc_channel == channel
+ assert transport._host == "squid.clam.whelk:443"
+ assert transport._ssl_channel_credentials == None
+
+
+@pytest.mark.parametrize(
+ "transport_class",
+ [transports.CloudBillingGrpcTransport, transports.CloudBillingGrpcAsyncIOTransport],
+)
+def test_cloud_billing_transport_channel_mtls_with_client_cert_source(transport_class):
+ with mock.patch(
+ "grpc.ssl_channel_credentials", autospec=True
+ ) as grpc_ssl_channel_cred:
+ with mock.patch.object(
+ transport_class, "create_channel", autospec=True
+ ) as grpc_create_channel:
+ mock_ssl_cred = mock.Mock()
+ grpc_ssl_channel_cred.return_value = mock_ssl_cred
+
+ mock_grpc_channel = mock.Mock()
+ grpc_create_channel.return_value = mock_grpc_channel
+
+ cred = credentials.AnonymousCredentials()
+ with pytest.warns(DeprecationWarning):
+ with mock.patch.object(auth, "default") as adc:
+ adc.return_value = (cred, None)
+ transport = transport_class(
+ host="squid.clam.whelk",
+ api_mtls_endpoint="mtls.squid.clam.whelk",
+ client_cert_source=client_cert_source_callback,
+ )
+ adc.assert_called_once()
+
+ grpc_ssl_channel_cred.assert_called_once_with(
+ certificate_chain=b"cert bytes", private_key=b"key bytes"
+ )
+ grpc_create_channel.assert_called_once_with(
+ "mtls.squid.clam.whelk:443",
+ credentials=cred,
+ credentials_file=None,
+ scopes=("https://www.googleapis.com/auth/cloud-platform",),
+ ssl_credentials=mock_ssl_cred,
+ quota_project_id=None,
+ )
+ assert transport.grpc_channel == mock_grpc_channel
+ assert transport._ssl_channel_credentials == mock_ssl_cred
+
+
+@pytest.mark.parametrize(
+ "transport_class",
+ [transports.CloudBillingGrpcTransport, transports.CloudBillingGrpcAsyncIOTransport],
+)
+def test_cloud_billing_transport_channel_mtls_with_adc(transport_class):
+ mock_ssl_cred = mock.Mock()
+ with mock.patch.multiple(
+ "google.auth.transport.grpc.SslCredentials",
+ __init__=mock.Mock(return_value=None),
+ ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred),
+ ):
+ with mock.patch.object(
+ transport_class, "create_channel", autospec=True
+ ) as grpc_create_channel:
+ mock_grpc_channel = mock.Mock()
+ grpc_create_channel.return_value = mock_grpc_channel
+ mock_cred = mock.Mock()
+
+ with pytest.warns(DeprecationWarning):
+ transport = transport_class(
+ host="squid.clam.whelk",
+ credentials=mock_cred,
+ api_mtls_endpoint="mtls.squid.clam.whelk",
+ client_cert_source=None,
+ )
+
+ grpc_create_channel.assert_called_once_with(
+ "mtls.squid.clam.whelk:443",
+ credentials=mock_cred,
+ credentials_file=None,
+ scopes=("https://www.googleapis.com/auth/cloud-platform",),
+ ssl_credentials=mock_ssl_cred,
+ quota_project_id=None,
+ )
+ assert transport.grpc_channel == mock_grpc_channel
+
+
+def test_common_billing_account_path():
+ billing_account = "squid"
+
+ expected = "billingAccounts/{billing_account}".format(
+ billing_account=billing_account,
+ )
+ actual = CloudBillingClient.common_billing_account_path(billing_account)
+ assert expected == actual
+
+
+def test_parse_common_billing_account_path():
+ expected = {
+ "billing_account": "clam",
+ }
+ path = CloudBillingClient.common_billing_account_path(**expected)
+
+ # Check that the path construction is reversible.
+ actual = CloudBillingClient.parse_common_billing_account_path(path)
+ assert expected == actual
+
+
+def test_common_folder_path():
+ folder = "whelk"
+
+ expected = "folders/{folder}".format(folder=folder,)
+ actual = CloudBillingClient.common_folder_path(folder)
+ assert expected == actual
+
+
+def test_parse_common_folder_path():
+ expected = {
+ "folder": "octopus",
+ }
+ path = CloudBillingClient.common_folder_path(**expected)
+
+ # Check that the path construction is reversible.
+ actual = CloudBillingClient.parse_common_folder_path(path)
+ assert expected == actual
+
+
+def test_common_organization_path():
+ organization = "oyster"
+
+ expected = "organizations/{organization}".format(organization=organization,)
+ actual = CloudBillingClient.common_organization_path(organization)
+ assert expected == actual
+
+
+def test_parse_common_organization_path():
+ expected = {
+ "organization": "nudibranch",
+ }
+ path = CloudBillingClient.common_organization_path(**expected)
+
+ # Check that the path construction is reversible.
+ actual = CloudBillingClient.parse_common_organization_path(path)
+ assert expected == actual
+
+
+def test_common_project_path():
+ project = "cuttlefish"
+
+ expected = "projects/{project}".format(project=project,)
+ actual = CloudBillingClient.common_project_path(project)
+ assert expected == actual
+
+
+def test_parse_common_project_path():
+ expected = {
+ "project": "mussel",
+ }
+ path = CloudBillingClient.common_project_path(**expected)
+
+ # Check that the path construction is reversible.
+ actual = CloudBillingClient.parse_common_project_path(path)
+ assert expected == actual
+
+
+def test_common_location_path():
+ project = "winkle"
+ location = "nautilus"
+
+ expected = "projects/{project}/locations/{location}".format(
+ project=project, location=location,
+ )
+ actual = CloudBillingClient.common_location_path(project, location)
+ assert expected == actual
+
+
+def test_parse_common_location_path():
+ expected = {
+ "project": "scallop",
+ "location": "abalone",
+ }
+ path = CloudBillingClient.common_location_path(**expected)
+
+ # Check that the path construction is reversible.
+ actual = CloudBillingClient.parse_common_location_path(path)
+ assert expected == actual
+
+
+def test_client_withDEFAULT_CLIENT_INFO():
+ client_info = gapic_v1.client_info.ClientInfo()
+
+ with mock.patch.object(
+ transports.CloudBillingTransport, "_prep_wrapped_messages"
+ ) as prep:
+ client = CloudBillingClient(
+ credentials=credentials.AnonymousCredentials(), client_info=client_info,
+ )
+ prep.assert_called_once_with(client_info)
+
+ with mock.patch.object(
+ transports.CloudBillingTransport, "_prep_wrapped_messages"
+ ) as prep:
+ transport_class = CloudBillingClient.get_transport_class()
+ transport = transport_class(
+ credentials=credentials.AnonymousCredentials(), client_info=client_info,
+ )
+ prep.assert_called_once_with(client_info)
diff --git a/packages/google-cloud-billing/tests/unit/gapic/billing_v1/test_cloud_catalog.py b/packages/google-cloud-billing/tests/unit/gapic/billing_v1/test_cloud_catalog.py
new file mode 100644
index 000000000000..cc9acb1052f3
--- /dev/null
+++ b/packages/google-cloud-billing/tests/unit/gapic/billing_v1/test_cloud_catalog.py
@@ -0,0 +1,1393 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import os
+import mock
+
+import grpc
+from grpc.experimental import aio
+import math
+import pytest
+from proto.marshal.rules.dates import DurationRule, TimestampRule
+
+from google import auth
+from google.api_core import client_options
+from google.api_core import exceptions
+from google.api_core import gapic_v1
+from google.api_core import grpc_helpers
+from google.api_core import grpc_helpers_async
+from google.auth import credentials
+from google.auth.exceptions import MutualTLSChannelError
+from google.cloud.billing_v1.services.cloud_catalog import CloudCatalogAsyncClient
+from google.cloud.billing_v1.services.cloud_catalog import CloudCatalogClient
+from google.cloud.billing_v1.services.cloud_catalog import pagers
+from google.cloud.billing_v1.services.cloud_catalog import transports
+from google.cloud.billing_v1.types import cloud_catalog
+from google.oauth2 import service_account
+from google.protobuf import timestamp_pb2 as timestamp # type: ignore
+
+
+def client_cert_source_callback():
+ return b"cert bytes", b"key bytes"
+
+
+# If default endpoint is localhost, then default mtls endpoint will be the same.
+# This method modifies the default endpoint so the client can produce a different
+# mtls endpoint for endpoint testing purposes.
+def modify_default_endpoint(client):
+ return (
+ "foo.googleapis.com"
+ if ("localhost" in client.DEFAULT_ENDPOINT)
+ else client.DEFAULT_ENDPOINT
+ )
+
+
+def test__get_default_mtls_endpoint():
+ api_endpoint = "example.googleapis.com"
+ api_mtls_endpoint = "example.mtls.googleapis.com"
+ sandbox_endpoint = "example.sandbox.googleapis.com"
+ sandbox_mtls_endpoint = "example.mtls.sandbox.googleapis.com"
+ non_googleapi = "api.example.com"
+
+ assert CloudCatalogClient._get_default_mtls_endpoint(None) is None
+ assert (
+ CloudCatalogClient._get_default_mtls_endpoint(api_endpoint) == api_mtls_endpoint
+ )
+ assert (
+ CloudCatalogClient._get_default_mtls_endpoint(api_mtls_endpoint)
+ == api_mtls_endpoint
+ )
+ assert (
+ CloudCatalogClient._get_default_mtls_endpoint(sandbox_endpoint)
+ == sandbox_mtls_endpoint
+ )
+ assert (
+ CloudCatalogClient._get_default_mtls_endpoint(sandbox_mtls_endpoint)
+ == sandbox_mtls_endpoint
+ )
+ assert CloudCatalogClient._get_default_mtls_endpoint(non_googleapi) == non_googleapi
+
+
+@pytest.mark.parametrize("client_class", [CloudCatalogClient, CloudCatalogAsyncClient])
+def test_cloud_catalog_client_from_service_account_file(client_class):
+ creds = credentials.AnonymousCredentials()
+ with mock.patch.object(
+ service_account.Credentials, "from_service_account_file"
+ ) as factory:
+ factory.return_value = creds
+ client = client_class.from_service_account_file("dummy/file/path.json")
+ assert client.transport._credentials == creds
+
+ client = client_class.from_service_account_json("dummy/file/path.json")
+ assert client.transport._credentials == creds
+
+ assert client.transport._host == "cloudbilling.googleapis.com:443"
+
+
+def test_cloud_catalog_client_get_transport_class():
+ transport = CloudCatalogClient.get_transport_class()
+ assert transport == transports.CloudCatalogGrpcTransport
+
+ transport = CloudCatalogClient.get_transport_class("grpc")
+ assert transport == transports.CloudCatalogGrpcTransport
+
+
+@pytest.mark.parametrize(
+ "client_class,transport_class,transport_name",
+ [
+ (CloudCatalogClient, transports.CloudCatalogGrpcTransport, "grpc"),
+ (
+ CloudCatalogAsyncClient,
+ transports.CloudCatalogGrpcAsyncIOTransport,
+ "grpc_asyncio",
+ ),
+ ],
+)
+@mock.patch.object(
+ CloudCatalogClient, "DEFAULT_ENDPOINT", modify_default_endpoint(CloudCatalogClient)
+)
+@mock.patch.object(
+ CloudCatalogAsyncClient,
+ "DEFAULT_ENDPOINT",
+ modify_default_endpoint(CloudCatalogAsyncClient),
+)
+def test_cloud_catalog_client_client_options(
+ client_class, transport_class, transport_name
+):
+ # Check that if channel is provided we won't create a new one.
+ with mock.patch.object(CloudCatalogClient, "get_transport_class") as gtc:
+ transport = transport_class(credentials=credentials.AnonymousCredentials())
+ client = client_class(transport=transport)
+ gtc.assert_not_called()
+
+ # Check that if channel is provided via str we will create a new one.
+ with mock.patch.object(CloudCatalogClient, "get_transport_class") as gtc:
+ client = client_class(transport=transport_name)
+ gtc.assert_called()
+
+ # Check the case api_endpoint is provided.
+ options = client_options.ClientOptions(api_endpoint="squid.clam.whelk")
+ with mock.patch.object(transport_class, "__init__") as patched:
+ patched.return_value = None
+ client = client_class(client_options=options)
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host="squid.clam.whelk",
+ scopes=None,
+ ssl_channel_credentials=None,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+ # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is
+ # "never".
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}):
+ with mock.patch.object(transport_class, "__init__") as patched:
+ patched.return_value = None
+ client = client_class()
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host=client.DEFAULT_ENDPOINT,
+ scopes=None,
+ ssl_channel_credentials=None,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+ # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is
+ # "always".
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}):
+ with mock.patch.object(transport_class, "__init__") as patched:
+ patched.return_value = None
+ client = client_class()
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host=client.DEFAULT_MTLS_ENDPOINT,
+ scopes=None,
+ ssl_channel_credentials=None,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+ # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has
+ # unsupported value.
+ with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}):
+ with pytest.raises(MutualTLSChannelError):
+ client = client_class()
+
+ # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value.
+ with mock.patch.dict(
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"}
+ ):
+ with pytest.raises(ValueError):
+ client = client_class()
+
+ # Check the case quota_project_id is provided
+ options = client_options.ClientOptions(quota_project_id="octopus")
+ with mock.patch.object(transport_class, "__init__") as patched:
+ patched.return_value = None
+ client = client_class(client_options=options)
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host=client.DEFAULT_ENDPOINT,
+ scopes=None,
+ ssl_channel_credentials=None,
+ quota_project_id="octopus",
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+
+@pytest.mark.parametrize(
+ "client_class,transport_class,transport_name,use_client_cert_env",
+ [
+ (CloudCatalogClient, transports.CloudCatalogGrpcTransport, "grpc", "true"),
+ (
+ CloudCatalogAsyncClient,
+ transports.CloudCatalogGrpcAsyncIOTransport,
+ "grpc_asyncio",
+ "true",
+ ),
+ (CloudCatalogClient, transports.CloudCatalogGrpcTransport, "grpc", "false"),
+ (
+ CloudCatalogAsyncClient,
+ transports.CloudCatalogGrpcAsyncIOTransport,
+ "grpc_asyncio",
+ "false",
+ ),
+ ],
+)
+@mock.patch.object(
+ CloudCatalogClient, "DEFAULT_ENDPOINT", modify_default_endpoint(CloudCatalogClient)
+)
+@mock.patch.object(
+ CloudCatalogAsyncClient,
+ "DEFAULT_ENDPOINT",
+ modify_default_endpoint(CloudCatalogAsyncClient),
+)
+@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"})
+def test_cloud_catalog_client_mtls_env_auto(
+ client_class, transport_class, transport_name, use_client_cert_env
+):
+ # This tests the endpoint autoswitch behavior. Endpoint is autoswitched to the default
+ # mtls endpoint, if GOOGLE_API_USE_CLIENT_CERTIFICATE is "true" and client cert exists.
+
+ # Check the case client_cert_source is provided. Whether client cert is used depends on
+ # GOOGLE_API_USE_CLIENT_CERTIFICATE value.
+ with mock.patch.dict(
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env}
+ ):
+ options = client_options.ClientOptions(
+ client_cert_source=client_cert_source_callback
+ )
+ with mock.patch.object(transport_class, "__init__") as patched:
+ ssl_channel_creds = mock.Mock()
+ with mock.patch(
+ "grpc.ssl_channel_credentials", return_value=ssl_channel_creds
+ ):
+ patched.return_value = None
+ client = client_class(client_options=options)
+
+ if use_client_cert_env == "false":
+ expected_ssl_channel_creds = None
+ expected_host = client.DEFAULT_ENDPOINT
+ else:
+ expected_ssl_channel_creds = ssl_channel_creds
+ expected_host = client.DEFAULT_MTLS_ENDPOINT
+
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host=expected_host,
+ scopes=None,
+ ssl_channel_credentials=expected_ssl_channel_creds,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+ # Check the case ADC client cert is provided. Whether client cert is used depends on
+ # GOOGLE_API_USE_CLIENT_CERTIFICATE value.
+ with mock.patch.dict(
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env}
+ ):
+ with mock.patch.object(transport_class, "__init__") as patched:
+ with mock.patch(
+ "google.auth.transport.grpc.SslCredentials.__init__", return_value=None
+ ):
+ with mock.patch(
+ "google.auth.transport.grpc.SslCredentials.is_mtls",
+ new_callable=mock.PropertyMock,
+ ) as is_mtls_mock:
+ with mock.patch(
+ "google.auth.transport.grpc.SslCredentials.ssl_credentials",
+ new_callable=mock.PropertyMock,
+ ) as ssl_credentials_mock:
+ if use_client_cert_env == "false":
+ is_mtls_mock.return_value = False
+ ssl_credentials_mock.return_value = None
+ expected_host = client.DEFAULT_ENDPOINT
+ expected_ssl_channel_creds = None
+ else:
+ is_mtls_mock.return_value = True
+ ssl_credentials_mock.return_value = mock.Mock()
+ expected_host = client.DEFAULT_MTLS_ENDPOINT
+ expected_ssl_channel_creds = (
+ ssl_credentials_mock.return_value
+ )
+
+ patched.return_value = None
+ client = client_class()
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host=expected_host,
+ scopes=None,
+ ssl_channel_credentials=expected_ssl_channel_creds,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+ # Check the case client_cert_source and ADC client cert are not provided.
+ with mock.patch.dict(
+ os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env}
+ ):
+ with mock.patch.object(transport_class, "__init__") as patched:
+ with mock.patch(
+ "google.auth.transport.grpc.SslCredentials.__init__", return_value=None
+ ):
+ with mock.patch(
+ "google.auth.transport.grpc.SslCredentials.is_mtls",
+ new_callable=mock.PropertyMock,
+ ) as is_mtls_mock:
+ is_mtls_mock.return_value = False
+ patched.return_value = None
+ client = client_class()
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host=client.DEFAULT_ENDPOINT,
+ scopes=None,
+ ssl_channel_credentials=None,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+
+@pytest.mark.parametrize(
+ "client_class,transport_class,transport_name",
+ [
+ (CloudCatalogClient, transports.CloudCatalogGrpcTransport, "grpc"),
+ (
+ CloudCatalogAsyncClient,
+ transports.CloudCatalogGrpcAsyncIOTransport,
+ "grpc_asyncio",
+ ),
+ ],
+)
+def test_cloud_catalog_client_client_options_scopes(
+ client_class, transport_class, transport_name
+):
+ # Check the case scopes are provided.
+ options = client_options.ClientOptions(scopes=["1", "2"],)
+ with mock.patch.object(transport_class, "__init__") as patched:
+ patched.return_value = None
+ client = client_class(client_options=options)
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host=client.DEFAULT_ENDPOINT,
+ scopes=["1", "2"],
+ ssl_channel_credentials=None,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+
+@pytest.mark.parametrize(
+ "client_class,transport_class,transport_name",
+ [
+ (CloudCatalogClient, transports.CloudCatalogGrpcTransport, "grpc"),
+ (
+ CloudCatalogAsyncClient,
+ transports.CloudCatalogGrpcAsyncIOTransport,
+ "grpc_asyncio",
+ ),
+ ],
+)
+def test_cloud_catalog_client_client_options_credentials_file(
+ client_class, transport_class, transport_name
+):
+ # Check the case credentials file is provided.
+ options = client_options.ClientOptions(credentials_file="credentials.json")
+ with mock.patch.object(transport_class, "__init__") as patched:
+ patched.return_value = None
+ client = client_class(client_options=options)
+ patched.assert_called_once_with(
+ credentials=None,
+ credentials_file="credentials.json",
+ host=client.DEFAULT_ENDPOINT,
+ scopes=None,
+ ssl_channel_credentials=None,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+
+def test_cloud_catalog_client_client_options_from_dict():
+ with mock.patch(
+ "google.cloud.billing_v1.services.cloud_catalog.transports.CloudCatalogGrpcTransport.__init__"
+ ) as grpc_transport:
+ grpc_transport.return_value = None
+ client = CloudCatalogClient(client_options={"api_endpoint": "squid.clam.whelk"})
+ grpc_transport.assert_called_once_with(
+ credentials=None,
+ credentials_file=None,
+ host="squid.clam.whelk",
+ scopes=None,
+ ssl_channel_credentials=None,
+ quota_project_id=None,
+ client_info=transports.base.DEFAULT_CLIENT_INFO,
+ )
+
+
+def test_list_services(
+ transport: str = "grpc", request_type=cloud_catalog.ListServicesRequest
+):
+ client = CloudCatalogClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.list_services), "__call__") as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_catalog.ListServicesResponse(
+ next_page_token="next_page_token_value",
+ )
+
+ response = client.list_services(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_catalog.ListServicesRequest()
+
+ # Establish that the response is the type that we expect.
+
+ assert isinstance(response, pagers.ListServicesPager)
+
+ assert response.next_page_token == "next_page_token_value"
+
+
+def test_list_services_from_dict():
+ test_list_services(request_type=dict)
+
+
+@pytest.mark.asyncio
+async def test_list_services_async(
+ transport: str = "grpc_asyncio", request_type=cloud_catalog.ListServicesRequest
+):
+ client = CloudCatalogAsyncClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.list_services), "__call__") as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_catalog.ListServicesResponse(next_page_token="next_page_token_value",)
+ )
+
+ response = await client.list_services(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_catalog.ListServicesRequest()
+
+ # Establish that the response is the type that we expect.
+ assert isinstance(response, pagers.ListServicesAsyncPager)
+
+ assert response.next_page_token == "next_page_token_value"
+
+
+@pytest.mark.asyncio
+async def test_list_services_async_from_dict():
+ await test_list_services_async(request_type=dict)
+
+
+def test_list_services_pager():
+ client = CloudCatalogClient(credentials=credentials.AnonymousCredentials,)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.list_services), "__call__") as call:
+ # Set the response to a series of pages.
+ call.side_effect = (
+ cloud_catalog.ListServicesResponse(
+ services=[
+ cloud_catalog.Service(),
+ cloud_catalog.Service(),
+ cloud_catalog.Service(),
+ ],
+ next_page_token="abc",
+ ),
+ cloud_catalog.ListServicesResponse(services=[], next_page_token="def",),
+ cloud_catalog.ListServicesResponse(
+ services=[cloud_catalog.Service(),], next_page_token="ghi",
+ ),
+ cloud_catalog.ListServicesResponse(
+ services=[cloud_catalog.Service(), cloud_catalog.Service(),],
+ ),
+ RuntimeError,
+ )
+
+ metadata = ()
+ pager = client.list_services(request={})
+
+ assert pager._metadata == metadata
+
+ results = [i for i in pager]
+ assert len(results) == 6
+ assert all(isinstance(i, cloud_catalog.Service) for i in results)
+
+
+def test_list_services_pages():
+ client = CloudCatalogClient(credentials=credentials.AnonymousCredentials,)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.list_services), "__call__") as call:
+ # Set the response to a series of pages.
+ call.side_effect = (
+ cloud_catalog.ListServicesResponse(
+ services=[
+ cloud_catalog.Service(),
+ cloud_catalog.Service(),
+ cloud_catalog.Service(),
+ ],
+ next_page_token="abc",
+ ),
+ cloud_catalog.ListServicesResponse(services=[], next_page_token="def",),
+ cloud_catalog.ListServicesResponse(
+ services=[cloud_catalog.Service(),], next_page_token="ghi",
+ ),
+ cloud_catalog.ListServicesResponse(
+ services=[cloud_catalog.Service(), cloud_catalog.Service(),],
+ ),
+ RuntimeError,
+ )
+ pages = list(client.list_services(request={}).pages)
+ for page_, token in zip(pages, ["abc", "def", "ghi", ""]):
+ assert page_.raw_page.next_page_token == token
+
+
+@pytest.mark.asyncio
+async def test_list_services_async_pager():
+ client = CloudCatalogAsyncClient(credentials=credentials.AnonymousCredentials,)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_services), "__call__", new_callable=mock.AsyncMock
+ ) as call:
+ # Set the response to a series of pages.
+ call.side_effect = (
+ cloud_catalog.ListServicesResponse(
+ services=[
+ cloud_catalog.Service(),
+ cloud_catalog.Service(),
+ cloud_catalog.Service(),
+ ],
+ next_page_token="abc",
+ ),
+ cloud_catalog.ListServicesResponse(services=[], next_page_token="def",),
+ cloud_catalog.ListServicesResponse(
+ services=[cloud_catalog.Service(),], next_page_token="ghi",
+ ),
+ cloud_catalog.ListServicesResponse(
+ services=[cloud_catalog.Service(), cloud_catalog.Service(),],
+ ),
+ RuntimeError,
+ )
+ async_pager = await client.list_services(request={},)
+ assert async_pager.next_page_token == "abc"
+ responses = []
+ async for response in async_pager:
+ responses.append(response)
+
+ assert len(responses) == 6
+ assert all(isinstance(i, cloud_catalog.Service) for i in responses)
+
+
+@pytest.mark.asyncio
+async def test_list_services_async_pages():
+ client = CloudCatalogAsyncClient(credentials=credentials.AnonymousCredentials,)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_services), "__call__", new_callable=mock.AsyncMock
+ ) as call:
+ # Set the response to a series of pages.
+ call.side_effect = (
+ cloud_catalog.ListServicesResponse(
+ services=[
+ cloud_catalog.Service(),
+ cloud_catalog.Service(),
+ cloud_catalog.Service(),
+ ],
+ next_page_token="abc",
+ ),
+ cloud_catalog.ListServicesResponse(services=[], next_page_token="def",),
+ cloud_catalog.ListServicesResponse(
+ services=[cloud_catalog.Service(),], next_page_token="ghi",
+ ),
+ cloud_catalog.ListServicesResponse(
+ services=[cloud_catalog.Service(), cloud_catalog.Service(),],
+ ),
+ RuntimeError,
+ )
+ pages = []
+ async for page_ in (await client.list_services(request={})).pages:
+ pages.append(page_)
+ for page_, token in zip(pages, ["abc", "def", "ghi", ""]):
+ assert page_.raw_page.next_page_token == token
+
+
+def test_list_skus(transport: str = "grpc", request_type=cloud_catalog.ListSkusRequest):
+ client = CloudCatalogClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.list_skus), "__call__") as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_catalog.ListSkusResponse(
+ next_page_token="next_page_token_value",
+ )
+
+ response = client.list_skus(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_catalog.ListSkusRequest()
+
+ # Establish that the response is the type that we expect.
+
+ assert isinstance(response, pagers.ListSkusPager)
+
+ assert response.next_page_token == "next_page_token_value"
+
+
+def test_list_skus_from_dict():
+ test_list_skus(request_type=dict)
+
+
+@pytest.mark.asyncio
+async def test_list_skus_async(
+ transport: str = "grpc_asyncio", request_type=cloud_catalog.ListSkusRequest
+):
+ client = CloudCatalogAsyncClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # Everything is optional in proto3 as far as the runtime is concerned,
+ # and we are mocking out the actual API, so just send an empty request.
+ request = request_type()
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.list_skus), "__call__") as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_catalog.ListSkusResponse(next_page_token="next_page_token_value",)
+ )
+
+ response = await client.list_skus(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0] == cloud_catalog.ListSkusRequest()
+
+ # Establish that the response is the type that we expect.
+ assert isinstance(response, pagers.ListSkusAsyncPager)
+
+ assert response.next_page_token == "next_page_token_value"
+
+
+@pytest.mark.asyncio
+async def test_list_skus_async_from_dict():
+ await test_list_skus_async(request_type=dict)
+
+
+def test_list_skus_field_headers():
+ client = CloudCatalogClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = cloud_catalog.ListSkusRequest()
+ request.parent = "parent/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.list_skus), "__call__") as call:
+ call.return_value = cloud_catalog.ListSkusResponse()
+
+ client.list_skus(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "parent=parent/value",) in kw["metadata"]
+
+
+@pytest.mark.asyncio
+async def test_list_skus_field_headers_async():
+ client = CloudCatalogAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Any value that is part of the HTTP/1.1 URI should be sent as
+ # a field header. Set these to a non-empty value.
+ request = cloud_catalog.ListSkusRequest()
+ request.parent = "parent/value"
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.list_skus), "__call__") as call:
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_catalog.ListSkusResponse()
+ )
+
+ await client.list_skus(request)
+
+ # Establish that the underlying gRPC stub method was called.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+ assert args[0] == request
+
+ # Establish that the field header was sent.
+ _, _, kw = call.mock_calls[0]
+ assert ("x-goog-request-params", "parent=parent/value",) in kw["metadata"]
+
+
+def test_list_skus_flattened():
+ client = CloudCatalogClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.list_skus), "__call__") as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_catalog.ListSkusResponse()
+
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ client.list_skus(parent="parent_value",)
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls) == 1
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].parent == "parent_value"
+
+
+def test_list_skus_flattened_error():
+ client = CloudCatalogClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ client.list_skus(
+ cloud_catalog.ListSkusRequest(), parent="parent_value",
+ )
+
+
+@pytest.mark.asyncio
+async def test_list_skus_flattened_async():
+ client = CloudCatalogAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.list_skus), "__call__") as call:
+ # Designate an appropriate return value for the call.
+ call.return_value = cloud_catalog.ListSkusResponse()
+
+ call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(
+ cloud_catalog.ListSkusResponse()
+ )
+ # Call the method with a truthy value for each flattened field,
+ # using the keyword arguments to the method.
+ response = await client.list_skus(parent="parent_value",)
+
+ # Establish that the underlying call was made with the expected
+ # request object values.
+ assert len(call.mock_calls)
+ _, args, _ = call.mock_calls[0]
+
+ assert args[0].parent == "parent_value"
+
+
+@pytest.mark.asyncio
+async def test_list_skus_flattened_error_async():
+ client = CloudCatalogAsyncClient(credentials=credentials.AnonymousCredentials(),)
+
+ # Attempting to call a method with both a request object and flattened
+ # fields is an error.
+ with pytest.raises(ValueError):
+ await client.list_skus(
+ cloud_catalog.ListSkusRequest(), parent="parent_value",
+ )
+
+
+def test_list_skus_pager():
+ client = CloudCatalogClient(credentials=credentials.AnonymousCredentials,)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.list_skus), "__call__") as call:
+ # Set the response to a series of pages.
+ call.side_effect = (
+ cloud_catalog.ListSkusResponse(
+ skus=[cloud_catalog.Sku(), cloud_catalog.Sku(), cloud_catalog.Sku(),],
+ next_page_token="abc",
+ ),
+ cloud_catalog.ListSkusResponse(skus=[], next_page_token="def",),
+ cloud_catalog.ListSkusResponse(
+ skus=[cloud_catalog.Sku(),], next_page_token="ghi",
+ ),
+ cloud_catalog.ListSkusResponse(
+ skus=[cloud_catalog.Sku(), cloud_catalog.Sku(),],
+ ),
+ RuntimeError,
+ )
+
+ metadata = ()
+ metadata = tuple(metadata) + (
+ gapic_v1.routing_header.to_grpc_metadata((("parent", ""),)),
+ )
+ pager = client.list_skus(request={})
+
+ assert pager._metadata == metadata
+
+ results = [i for i in pager]
+ assert len(results) == 6
+ assert all(isinstance(i, cloud_catalog.Sku) for i in results)
+
+
+def test_list_skus_pages():
+ client = CloudCatalogClient(credentials=credentials.AnonymousCredentials,)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(type(client.transport.list_skus), "__call__") as call:
+ # Set the response to a series of pages.
+ call.side_effect = (
+ cloud_catalog.ListSkusResponse(
+ skus=[cloud_catalog.Sku(), cloud_catalog.Sku(), cloud_catalog.Sku(),],
+ next_page_token="abc",
+ ),
+ cloud_catalog.ListSkusResponse(skus=[], next_page_token="def",),
+ cloud_catalog.ListSkusResponse(
+ skus=[cloud_catalog.Sku(),], next_page_token="ghi",
+ ),
+ cloud_catalog.ListSkusResponse(
+ skus=[cloud_catalog.Sku(), cloud_catalog.Sku(),],
+ ),
+ RuntimeError,
+ )
+ pages = list(client.list_skus(request={}).pages)
+ for page_, token in zip(pages, ["abc", "def", "ghi", ""]):
+ assert page_.raw_page.next_page_token == token
+
+
+@pytest.mark.asyncio
+async def test_list_skus_async_pager():
+ client = CloudCatalogAsyncClient(credentials=credentials.AnonymousCredentials,)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_skus), "__call__", new_callable=mock.AsyncMock
+ ) as call:
+ # Set the response to a series of pages.
+ call.side_effect = (
+ cloud_catalog.ListSkusResponse(
+ skus=[cloud_catalog.Sku(), cloud_catalog.Sku(), cloud_catalog.Sku(),],
+ next_page_token="abc",
+ ),
+ cloud_catalog.ListSkusResponse(skus=[], next_page_token="def",),
+ cloud_catalog.ListSkusResponse(
+ skus=[cloud_catalog.Sku(),], next_page_token="ghi",
+ ),
+ cloud_catalog.ListSkusResponse(
+ skus=[cloud_catalog.Sku(), cloud_catalog.Sku(),],
+ ),
+ RuntimeError,
+ )
+ async_pager = await client.list_skus(request={},)
+ assert async_pager.next_page_token == "abc"
+ responses = []
+ async for response in async_pager:
+ responses.append(response)
+
+ assert len(responses) == 6
+ assert all(isinstance(i, cloud_catalog.Sku) for i in responses)
+
+
+@pytest.mark.asyncio
+async def test_list_skus_async_pages():
+ client = CloudCatalogAsyncClient(credentials=credentials.AnonymousCredentials,)
+
+ # Mock the actual call within the gRPC stub, and fake the request.
+ with mock.patch.object(
+ type(client.transport.list_skus), "__call__", new_callable=mock.AsyncMock
+ ) as call:
+ # Set the response to a series of pages.
+ call.side_effect = (
+ cloud_catalog.ListSkusResponse(
+ skus=[cloud_catalog.Sku(), cloud_catalog.Sku(), cloud_catalog.Sku(),],
+ next_page_token="abc",
+ ),
+ cloud_catalog.ListSkusResponse(skus=[], next_page_token="def",),
+ cloud_catalog.ListSkusResponse(
+ skus=[cloud_catalog.Sku(),], next_page_token="ghi",
+ ),
+ cloud_catalog.ListSkusResponse(
+ skus=[cloud_catalog.Sku(), cloud_catalog.Sku(),],
+ ),
+ RuntimeError,
+ )
+ pages = []
+ async for page_ in (await client.list_skus(request={})).pages:
+ pages.append(page_)
+ for page_, token in zip(pages, ["abc", "def", "ghi", ""]):
+ assert page_.raw_page.next_page_token == token
+
+
+def test_credentials_transport_error():
+ # It is an error to provide credentials and a transport instance.
+ transport = transports.CloudCatalogGrpcTransport(
+ credentials=credentials.AnonymousCredentials(),
+ )
+ with pytest.raises(ValueError):
+ client = CloudCatalogClient(
+ credentials=credentials.AnonymousCredentials(), transport=transport,
+ )
+
+ # It is an error to provide a credentials file and a transport instance.
+ transport = transports.CloudCatalogGrpcTransport(
+ credentials=credentials.AnonymousCredentials(),
+ )
+ with pytest.raises(ValueError):
+ client = CloudCatalogClient(
+ client_options={"credentials_file": "credentials.json"},
+ transport=transport,
+ )
+
+ # It is an error to provide scopes and a transport instance.
+ transport = transports.CloudCatalogGrpcTransport(
+ credentials=credentials.AnonymousCredentials(),
+ )
+ with pytest.raises(ValueError):
+ client = CloudCatalogClient(
+ client_options={"scopes": ["1", "2"]}, transport=transport,
+ )
+
+
+def test_transport_instance():
+ # A client may be instantiated with a custom transport instance.
+ transport = transports.CloudCatalogGrpcTransport(
+ credentials=credentials.AnonymousCredentials(),
+ )
+ client = CloudCatalogClient(transport=transport)
+ assert client.transport is transport
+
+
+def test_transport_get_channel():
+ # A client may be instantiated with a custom transport instance.
+ transport = transports.CloudCatalogGrpcTransport(
+ credentials=credentials.AnonymousCredentials(),
+ )
+ channel = transport.grpc_channel
+ assert channel
+
+ transport = transports.CloudCatalogGrpcAsyncIOTransport(
+ credentials=credentials.AnonymousCredentials(),
+ )
+ channel = transport.grpc_channel
+ assert channel
+
+
+@pytest.mark.parametrize(
+ "transport_class",
+ [transports.CloudCatalogGrpcTransport, transports.CloudCatalogGrpcAsyncIOTransport],
+)
+def test_transport_adc(transport_class):
+ # Test default credentials are used if not provided.
+ with mock.patch.object(auth, "default") as adc:
+ adc.return_value = (credentials.AnonymousCredentials(), None)
+ transport_class()
+ adc.assert_called_once()
+
+
+def test_transport_grpc_default():
+ # A client should use the gRPC transport by default.
+ client = CloudCatalogClient(credentials=credentials.AnonymousCredentials(),)
+ assert isinstance(client.transport, transports.CloudCatalogGrpcTransport,)
+
+
+def test_cloud_catalog_base_transport_error():
+ # Passing both a credentials object and credentials_file should raise an error
+ with pytest.raises(exceptions.DuplicateCredentialArgs):
+ transport = transports.CloudCatalogTransport(
+ credentials=credentials.AnonymousCredentials(),
+ credentials_file="credentials.json",
+ )
+
+
+def test_cloud_catalog_base_transport():
+ # Instantiate the base transport.
+ with mock.patch(
+ "google.cloud.billing_v1.services.cloud_catalog.transports.CloudCatalogTransport.__init__"
+ ) as Transport:
+ Transport.return_value = None
+ transport = transports.CloudCatalogTransport(
+ credentials=credentials.AnonymousCredentials(),
+ )
+
+ # Every method on the transport should just blindly
+ # raise NotImplementedError.
+ methods = (
+ "list_services",
+ "list_skus",
+ )
+ for method in methods:
+ with pytest.raises(NotImplementedError):
+ getattr(transport, method)(request=object())
+
+
+def test_cloud_catalog_base_transport_with_credentials_file():
+ # Instantiate the base transport with a credentials file
+ with mock.patch.object(
+ auth, "load_credentials_from_file"
+ ) as load_creds, mock.patch(
+ "google.cloud.billing_v1.services.cloud_catalog.transports.CloudCatalogTransport._prep_wrapped_messages"
+ ) as Transport:
+ Transport.return_value = None
+ load_creds.return_value = (credentials.AnonymousCredentials(), None)
+ transport = transports.CloudCatalogTransport(
+ credentials_file="credentials.json", quota_project_id="octopus",
+ )
+ load_creds.assert_called_once_with(
+ "credentials.json",
+ scopes=("https://www.googleapis.com/auth/cloud-platform",),
+ quota_project_id="octopus",
+ )
+
+
+def test_cloud_catalog_base_transport_with_adc():
+ # Test the default credentials are used if credentials and credentials_file are None.
+ with mock.patch.object(auth, "default") as adc, mock.patch(
+ "google.cloud.billing_v1.services.cloud_catalog.transports.CloudCatalogTransport._prep_wrapped_messages"
+ ) as Transport:
+ Transport.return_value = None
+ adc.return_value = (credentials.AnonymousCredentials(), None)
+ transport = transports.CloudCatalogTransport()
+ adc.assert_called_once()
+
+
+def test_cloud_catalog_auth_adc():
+ # If no credentials are provided, we should use ADC credentials.
+ with mock.patch.object(auth, "default") as adc:
+ adc.return_value = (credentials.AnonymousCredentials(), None)
+ CloudCatalogClient()
+ adc.assert_called_once_with(
+ scopes=("https://www.googleapis.com/auth/cloud-platform",),
+ quota_project_id=None,
+ )
+
+
+def test_cloud_catalog_transport_auth_adc():
+ # If credentials and host are not provided, the transport class should use
+ # ADC credentials.
+ with mock.patch.object(auth, "default") as adc:
+ adc.return_value = (credentials.AnonymousCredentials(), None)
+ transports.CloudCatalogGrpcTransport(
+ host="squid.clam.whelk", quota_project_id="octopus"
+ )
+ adc.assert_called_once_with(
+ scopes=("https://www.googleapis.com/auth/cloud-platform",),
+ quota_project_id="octopus",
+ )
+
+
+def test_cloud_catalog_host_no_port():
+ client = CloudCatalogClient(
+ credentials=credentials.AnonymousCredentials(),
+ client_options=client_options.ClientOptions(
+ api_endpoint="cloudbilling.googleapis.com"
+ ),
+ )
+ assert client.transport._host == "cloudbilling.googleapis.com:443"
+
+
+def test_cloud_catalog_host_with_port():
+ client = CloudCatalogClient(
+ credentials=credentials.AnonymousCredentials(),
+ client_options=client_options.ClientOptions(
+ api_endpoint="cloudbilling.googleapis.com:8000"
+ ),
+ )
+ assert client.transport._host == "cloudbilling.googleapis.com:8000"
+
+
+def test_cloud_catalog_grpc_transport_channel():
+ channel = grpc.insecure_channel("http://localhost/")
+
+ # Check that channel is used if provided.
+ transport = transports.CloudCatalogGrpcTransport(
+ host="squid.clam.whelk", channel=channel,
+ )
+ assert transport.grpc_channel == channel
+ assert transport._host == "squid.clam.whelk:443"
+ assert transport._ssl_channel_credentials == None
+
+
+def test_cloud_catalog_grpc_asyncio_transport_channel():
+ channel = aio.insecure_channel("http://localhost/")
+
+ # Check that channel is used if provided.
+ transport = transports.CloudCatalogGrpcAsyncIOTransport(
+ host="squid.clam.whelk", channel=channel,
+ )
+ assert transport.grpc_channel == channel
+ assert transport._host == "squid.clam.whelk:443"
+ assert transport._ssl_channel_credentials == None
+
+
+@pytest.mark.parametrize(
+ "transport_class",
+ [transports.CloudCatalogGrpcTransport, transports.CloudCatalogGrpcAsyncIOTransport],
+)
+def test_cloud_catalog_transport_channel_mtls_with_client_cert_source(transport_class):
+ with mock.patch(
+ "grpc.ssl_channel_credentials", autospec=True
+ ) as grpc_ssl_channel_cred:
+ with mock.patch.object(
+ transport_class, "create_channel", autospec=True
+ ) as grpc_create_channel:
+ mock_ssl_cred = mock.Mock()
+ grpc_ssl_channel_cred.return_value = mock_ssl_cred
+
+ mock_grpc_channel = mock.Mock()
+ grpc_create_channel.return_value = mock_grpc_channel
+
+ cred = credentials.AnonymousCredentials()
+ with pytest.warns(DeprecationWarning):
+ with mock.patch.object(auth, "default") as adc:
+ adc.return_value = (cred, None)
+ transport = transport_class(
+ host="squid.clam.whelk",
+ api_mtls_endpoint="mtls.squid.clam.whelk",
+ client_cert_source=client_cert_source_callback,
+ )
+ adc.assert_called_once()
+
+ grpc_ssl_channel_cred.assert_called_once_with(
+ certificate_chain=b"cert bytes", private_key=b"key bytes"
+ )
+ grpc_create_channel.assert_called_once_with(
+ "mtls.squid.clam.whelk:443",
+ credentials=cred,
+ credentials_file=None,
+ scopes=("https://www.googleapis.com/auth/cloud-platform",),
+ ssl_credentials=mock_ssl_cred,
+ quota_project_id=None,
+ )
+ assert transport.grpc_channel == mock_grpc_channel
+ assert transport._ssl_channel_credentials == mock_ssl_cred
+
+
+@pytest.mark.parametrize(
+ "transport_class",
+ [transports.CloudCatalogGrpcTransport, transports.CloudCatalogGrpcAsyncIOTransport],
+)
+def test_cloud_catalog_transport_channel_mtls_with_adc(transport_class):
+ mock_ssl_cred = mock.Mock()
+ with mock.patch.multiple(
+ "google.auth.transport.grpc.SslCredentials",
+ __init__=mock.Mock(return_value=None),
+ ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred),
+ ):
+ with mock.patch.object(
+ transport_class, "create_channel", autospec=True
+ ) as grpc_create_channel:
+ mock_grpc_channel = mock.Mock()
+ grpc_create_channel.return_value = mock_grpc_channel
+ mock_cred = mock.Mock()
+
+ with pytest.warns(DeprecationWarning):
+ transport = transport_class(
+ host="squid.clam.whelk",
+ credentials=mock_cred,
+ api_mtls_endpoint="mtls.squid.clam.whelk",
+ client_cert_source=None,
+ )
+
+ grpc_create_channel.assert_called_once_with(
+ "mtls.squid.clam.whelk:443",
+ credentials=mock_cred,
+ credentials_file=None,
+ scopes=("https://www.googleapis.com/auth/cloud-platform",),
+ ssl_credentials=mock_ssl_cred,
+ quota_project_id=None,
+ )
+ assert transport.grpc_channel == mock_grpc_channel
+
+
+def test_service_path():
+ service = "squid"
+
+ expected = "services/{service}".format(service=service,)
+ actual = CloudCatalogClient.service_path(service)
+ assert expected == actual
+
+
+def test_parse_service_path():
+ expected = {
+ "service": "clam",
+ }
+ path = CloudCatalogClient.service_path(**expected)
+
+ # Check that the path construction is reversible.
+ actual = CloudCatalogClient.parse_service_path(path)
+ assert expected == actual
+
+
+def test_sku_path():
+ service = "whelk"
+ sku = "octopus"
+
+ expected = "services/{service}/skus/{sku}".format(service=service, sku=sku,)
+ actual = CloudCatalogClient.sku_path(service, sku)
+ assert expected == actual
+
+
+def test_parse_sku_path():
+ expected = {
+ "service": "oyster",
+ "sku": "nudibranch",
+ }
+ path = CloudCatalogClient.sku_path(**expected)
+
+ # Check that the path construction is reversible.
+ actual = CloudCatalogClient.parse_sku_path(path)
+ assert expected == actual
+
+
+def test_common_billing_account_path():
+ billing_account = "cuttlefish"
+
+ expected = "billingAccounts/{billing_account}".format(
+ billing_account=billing_account,
+ )
+ actual = CloudCatalogClient.common_billing_account_path(billing_account)
+ assert expected == actual
+
+
+def test_parse_common_billing_account_path():
+ expected = {
+ "billing_account": "mussel",
+ }
+ path = CloudCatalogClient.common_billing_account_path(**expected)
+
+ # Check that the path construction is reversible.
+ actual = CloudCatalogClient.parse_common_billing_account_path(path)
+ assert expected == actual
+
+
+def test_common_folder_path():
+ folder = "winkle"
+
+ expected = "folders/{folder}".format(folder=folder,)
+ actual = CloudCatalogClient.common_folder_path(folder)
+ assert expected == actual
+
+
+def test_parse_common_folder_path():
+ expected = {
+ "folder": "nautilus",
+ }
+ path = CloudCatalogClient.common_folder_path(**expected)
+
+ # Check that the path construction is reversible.
+ actual = CloudCatalogClient.parse_common_folder_path(path)
+ assert expected == actual
+
+
+def test_common_organization_path():
+ organization = "scallop"
+
+ expected = "organizations/{organization}".format(organization=organization,)
+ actual = CloudCatalogClient.common_organization_path(organization)
+ assert expected == actual
+
+
+def test_parse_common_organization_path():
+ expected = {
+ "organization": "abalone",
+ }
+ path = CloudCatalogClient.common_organization_path(**expected)
+
+ # Check that the path construction is reversible.
+ actual = CloudCatalogClient.parse_common_organization_path(path)
+ assert expected == actual
+
+
+def test_common_project_path():
+ project = "squid"
+
+ expected = "projects/{project}".format(project=project,)
+ actual = CloudCatalogClient.common_project_path(project)
+ assert expected == actual
+
+
+def test_parse_common_project_path():
+ expected = {
+ "project": "clam",
+ }
+ path = CloudCatalogClient.common_project_path(**expected)
+
+ # Check that the path construction is reversible.
+ actual = CloudCatalogClient.parse_common_project_path(path)
+ assert expected == actual
+
+
+def test_common_location_path():
+ project = "whelk"
+ location = "octopus"
+
+ expected = "projects/{project}/locations/{location}".format(
+ project=project, location=location,
+ )
+ actual = CloudCatalogClient.common_location_path(project, location)
+ assert expected == actual
+
+
+def test_parse_common_location_path():
+ expected = {
+ "project": "oyster",
+ "location": "nudibranch",
+ }
+ path = CloudCatalogClient.common_location_path(**expected)
+
+ # Check that the path construction is reversible.
+ actual = CloudCatalogClient.parse_common_location_path(path)
+ assert expected == actual
+
+
+def test_client_withDEFAULT_CLIENT_INFO():
+ client_info = gapic_v1.client_info.ClientInfo()
+
+ with mock.patch.object(
+ transports.CloudCatalogTransport, "_prep_wrapped_messages"
+ ) as prep:
+ client = CloudCatalogClient(
+ credentials=credentials.AnonymousCredentials(), client_info=client_info,
+ )
+ prep.assert_called_once_with(client_info)
+
+ with mock.patch.object(
+ transports.CloudCatalogTransport, "_prep_wrapped_messages"
+ ) as prep:
+ transport_class = CloudCatalogClient.get_transport_class()
+ transport = transport_class(
+ credentials=credentials.AnonymousCredentials(), client_info=client_info,
+ )
+ prep.assert_called_once_with(client_info)