diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml new file mode 100644 index 0000000..76de9e5 --- /dev/null +++ b/.github/.OwlBot.lock.yaml @@ -0,0 +1,4 @@ +docker: + digest: sha256:56133a8648855cccff1389e56a8e7e22168f9ebde70c27b77c0c3ec6d15d90bb + image: gcr.io/repo-automation-bots/owlbot-python:latest + diff --git a/.github/.OwlBot.yaml b/.github/.OwlBot.yaml new file mode 100644 index 0000000..af8f560 --- /dev/null +++ b/.github/.OwlBot.yaml @@ -0,0 +1,26 @@ +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +docker: + image: gcr.io/repo-automation-bots/owlbot-python:latest + +deep-remove-regex: + - /owl-bot-staging + +deep-copy-regex: + - source: /google/cloud/channel/(v.*)/.*-py/(.*) + dest: /owl-bot-staging/$1/$2 + +begin-after-commit-hash: 6a5da3f1274b088752f074da5bc9e30bd1beb27e + diff --git a/.gitignore b/.gitignore index b9daa52..b4243ce 100644 --- a/.gitignore +++ b/.gitignore @@ -50,8 +50,10 @@ docs.metadata # Virtual environment env/ + +# Test logs coverage.xml -sponge_log.xml +*sponge_log.xml # System test environment variables. system_tests/local_test_setup diff --git a/.kokoro/build.sh b/.kokoro/build.sh index dd67ef5..d2be238 100755 --- a/.kokoro/build.sh +++ b/.kokoro/build.sh @@ -40,6 +40,16 @@ python3 -m pip uninstall --yes --quiet nox-automation python3 -m pip install --upgrade --quiet nox python3 -m nox --version +# If this is a continuous build, send the test log to the FlakyBot. +# See https://github.com/googleapis/repo-automation-bots/tree/master/packages/flakybot. +if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]]; then + cleanup() { + chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot + $KOKORO_GFILE_DIR/linux_amd64/flakybot + } + trap cleanup EXIT HUP +fi + # If NOX_SESSION is set, it only runs the specified session, # otherwise run all the sessions. if [[ -n "${NOX_SESSION:-}" ]]; then diff --git a/.kokoro/samples/python3.6/periodic-head.cfg b/.kokoro/samples/python3.6/periodic-head.cfg new file mode 100644 index 0000000..f9cfcd3 --- /dev/null +++ b/.kokoro/samples/python3.6/periodic-head.cfg @@ -0,0 +1,11 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-pubsub/.kokoro/test-samples-against-head.sh" +} diff --git a/.kokoro/samples/python3.7/periodic-head.cfg b/.kokoro/samples/python3.7/periodic-head.cfg new file mode 100644 index 0000000..f9cfcd3 --- /dev/null +++ b/.kokoro/samples/python3.7/periodic-head.cfg @@ -0,0 +1,11 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-pubsub/.kokoro/test-samples-against-head.sh" +} diff --git a/.kokoro/samples/python3.8/periodic-head.cfg b/.kokoro/samples/python3.8/periodic-head.cfg new file mode 100644 index 0000000..f9cfcd3 --- /dev/null +++ b/.kokoro/samples/python3.8/periodic-head.cfg @@ -0,0 +1,11 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +env_vars: { + key: "INSTALL_LIBRARY_FROM_SOURCE" + value: "True" +} + +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/python-pubsub/.kokoro/test-samples-against-head.sh" +} diff --git a/.kokoro/test-samples-against-head.sh b/.kokoro/test-samples-against-head.sh new file mode 100755 index 0000000..97a5f49 --- /dev/null +++ b/.kokoro/test-samples-against-head.sh @@ -0,0 +1,28 @@ +#!/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. + +# A customized test runner for samples. +# +# For periodic builds, you can specify this file for testing against head. + +# `-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-channel + +exec .kokoro/test-samples-impl.sh diff --git a/.kokoro/test-samples-impl.sh b/.kokoro/test-samples-impl.sh new file mode 100755 index 0000000..cf5de74 --- /dev/null +++ b/.kokoro/test-samples-impl.sh @@ -0,0 +1,102 @@ +#!/bin/bash +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# 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 + +# 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 FlakyBot. + # See https://github.com/googleapis/repo-automation-bots/tree/master/packages/flakybot. + if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then + chmod +x $KOKORO_GFILE_DIR/linux_amd64/flakybot + $KOKORO_GFILE_DIR/linux_amd64/flakybot + 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/.kokoro/test-samples.sh b/.kokoro/test-samples.sh index 7653933..deac97c 100755 --- a/.kokoro/test-samples.sh +++ b/.kokoro/test-samples.sh @@ -13,6 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +# The default test runner for samples. +# +# For periodic builds, we rewinds the repo to the latest release, and +# run test-samples-impl.sh. # `-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 @@ -24,87 +28,19 @@ cd github/python-channel # Run periodic samples tests at latest release if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then + # preserving the test runner implementation. + cp .kokoro/test-samples-impl.sh "${TMPDIR}/test-samples-impl.sh" + echo "--- IMPORTANT IMPORTANT IMPORTANT ---" + echo "Now we rewind the repo back to the latest release..." 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 + echo "The current head is: " + echo $(git rev-parse --verify HEAD) + echo "--- IMPORTANT IMPORTANT IMPORTANT ---" + # move back the test runner implementation if there's no file. + if [ ! -f .kokoro/test-samples-impl.sh ]; then + cp "${TMPDIR}/test-samples-impl.sh" .kokoro/test-samples-impl.sh fi +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" +exec .kokoro/test-samples-impl.sh diff --git a/.kokoro/trampoline_v2.sh b/.kokoro/trampoline_v2.sh index 719bcd5..4af6cdc 100755 --- a/.kokoro/trampoline_v2.sh +++ b/.kokoro/trampoline_v2.sh @@ -159,7 +159,7 @@ if [[ -n "${KOKORO_BUILD_ID:-}" ]]; then "KOKORO_GITHUB_COMMIT" "KOKORO_GITHUB_PULL_REQUEST_NUMBER" "KOKORO_GITHUB_PULL_REQUEST_COMMIT" - # For Build Cop Bot + # For FlakyBot "KOKORO_GITHUB_COMMIT_URL" "KOKORO_GITHUB_PULL_REQUEST_URL" ) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a9024b1..32302e4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,6 +12,6 @@ repos: hooks: - id: black - repo: https://gitlab.com/pycqa/flake8 - rev: 3.8.4 + rev: 3.9.0 hooks: - id: flake8 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c1bf49..8150a57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +### [0.2.1](https://www.github.com/googleapis/python-channel/compare/v0.2.0...v0.2.1) (2021-04-07) + + +### Bug Fixes + +* BREAKING deprecate TransferableSkus fields ([#14](https://www.github.com/googleapis/python-channel/issues/14)) ([0d3b493](https://www.github.com/googleapis/python-channel/commit/0d3b4939cdae196ea9b0edc00e13f61d7d71777d)) + ## [0.2.0](https://www.github.com/googleapis/python-channel/compare/v0.1.0...v0.2.0) (2021-02-11) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index a99fdc5..e083f9c 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -70,9 +70,14 @@ We use `nox `__ to instrument our tests. - To test your changes, run unit tests with ``nox``:: $ nox -s unit-2.7 - $ nox -s unit-3.7 + $ nox -s unit-3.8 $ ... +- Args to pytest can be passed through the nox command separated by a `--`. For + example, to run a single test:: + + $ nox -s unit-3.8 -- -k + .. note:: The unit tests and system tests are described in the @@ -93,8 +98,12 @@ On Debian/Ubuntu:: ************ Coding Style ************ +- We use the automatic code formatter ``black``. You can run it using + the nox session ``blacken``. This will eliminate many lint errors. Run via:: + + $ nox -s blacken -- PEP8 compliance, with exceptions defined in the linter configuration. +- PEP8 compliance is required, with exceptions defined in the linter configuration. If you have ``nox`` installed, you can test that you have not introduced any non-compliant code via:: @@ -133,13 +142,18 @@ Running System Tests - To run system tests, you can execute:: - $ nox -s system-3.7 + # Run all system tests + $ nox -s system-3.8 $ nox -s system-2.7 + # Run a single system test + $ nox -s system-3.8 -- -k + + .. note:: System tests are only configured to run under Python 2.7 and - Python 3.7. For expediency, we do not run them in older versions + Python 3.8. For expediency, we do not run them in older versions of Python 3. This alone will not run the tests. You'll need to change some local diff --git a/MANIFEST.in b/MANIFEST.in index e9e29d1..e783f4c 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -16,10 +16,10 @@ # Generated by synthtool. DO NOT EDIT! include README.rst LICENSE -recursive-include google *.json *.proto +recursive-include google *.json *.proto py.typed 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 +prune scripts/readme-gen diff --git a/google/cloud/channel_v1/services/cloud_channel_service/async_client.py b/google/cloud/channel_v1/services/cloud_channel_service/async_client.py index cd80746..dc16a3e 100644 --- a/google/cloud/channel_v1/services/cloud_channel_service/async_client.py +++ b/google/cloud/channel_v1/services/cloud_channel_service/async_client.py @@ -127,8 +127,36 @@ class CloudChannelServiceAsyncClient: CloudChannelServiceClient.parse_common_location_path ) - from_service_account_info = CloudChannelServiceClient.from_service_account_info - from_service_account_file = CloudChannelServiceClient.from_service_account_file + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CloudChannelServiceAsyncClient: The constructed client. + """ + return CloudChannelServiceClient.from_service_account_info.__func__(CloudChannelServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + CloudChannelServiceAsyncClient: The constructed client. + """ + return CloudChannelServiceClient.from_service_account_file.__func__(CloudChannelServiceAsyncClient, filename, *args, **kwargs) # type: ignore + from_service_account_json = from_service_account_file @property @@ -370,14 +398,15 @@ async def check_cloud_identity_accounts_exist( - INVALID_ARGUMENT: Missing or invalid required parameters in the request. - INVALID_VALUE: Invalid domain value in the request. - - NOT_FOUND: If there is no - [CloudIdentityCustomerAccount][google.cloud.channel.v1.CloudIdentityCustomerAccount] - customer for the domain specified in the request. Return Value: List of [CloudIdentityCustomerAccount][google.cloud.channel.v1.CloudIdentityCustomerAccount] - resources if any exist for the domain, otherwise an error is - returned. + resources for the domain. List may be empty. + + Note: in the v1alpha1 version of the API, a NOT_FOUND error is + returned if no + [CloudIdentityCustomerAccount][google.cloud.channel.v1.CloudIdentityCustomerAccount] + resources match the domain. Args: request (:class:`google.cloud.channel_v1.types.CheckCloudIdentityAccountsExistRequest`): @@ -433,19 +462,13 @@ async def create_customer( Possible Error Codes: - .. raw:: html + - PERMISSION_DENIED: If the reseller account making the request + and the reseller account being queried for are different. + - INVALID_ARGUMENT: It can happen in following scenarios - -
    -
  • PERMISSION_DENIED: If the reseller account making the request and the - reseller account being queried for are different.
  • -
  • INVALID_ARGUMENT: -
      -
    • Missing or invalid required parameters in the request.
    • -
    • Domain field value doesn't match the domain specified in primary - email.
    • -
    -
  • -
+ - Missing or invalid required parameters in the request. + - Domain field value doesn't match the domain specified in + primary email. Return Value: If successful, the newly created [Customer][google.cloud.channel.v1.Customer] resource, otherwise @@ -813,20 +836,16 @@ async def list_transferable_skus( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED, due to one of the following reasons: -
      -
    • If the customer doesn't belong to the reseller and no auth token, - or an invalid auth token is supplied.
    • If the reseller account - making the request and the reseller account being queried for are - different.
    • -
    -
  • -
  • INVALID_ARGUMENT: Missing or invalid required parameters in the - request.
  • -
+ - PERMISSION_DENIED: Appears because of one of the following - + + - The customer doesn't belong to the reseller and no auth + token. + - The supplied auth token is invalid. + - The reseller account making the request and the queries + reseller account are different. + + - INVALID_ARGUMENT: Missing or invalid required parameters in + the request. Return Value: List of [TransferableSku][google.cloud.channel.v1.TransferableSku] for @@ -901,11 +920,13 @@ async def list_transferable_offers( Possible Error Codes: - - PERMISSION_DENIED, due to one of the following reasons: (a) - If the customer doesn't belong to the reseller and no auth - token or invalid auth token is supplied. (b) If the reseller - account making the request and the reseller account being - queried for are different. + - PERMISSION_DENIED: Appears because of one of the following: + + - If the customer doesn't belong to the reseller and no auth + token or invalid auth token is supplied. + - If the reseller account making the request and the + reseller account being queried for are different. + - INVALID_ARGUMENT: Missing or invalid required parameters in the request. @@ -1039,50 +1060,47 @@ async def create_entitlement( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED: If the customer doesn't belong to the reseller. -
  • INVALID_ARGUMENT:
      -
    • Missing or invalid required parameters in the request.
    • -
    • Cannot purchase an entitlement if there is already an - entitlement for customer, for a SKU from the same product family.
    • -
    • INVALID_VALUE: Offer passed in isn't valid. Make sure OfferId is - valid. If it is valid, then contact Google Channel support for further - troubleshooting.
    • -
    -
  • -
  • NOT_FOUND: If the customer or offer resource is not found for the - reseller.
  • -
  • ALREADY_EXISTS: This failure can happen in the following cases: -
      -
    • If the SKU has been already purchased for the customer.
    • -
    • If the customer's primary email already exists. In this case retry - after changing the customer's primary contact email. -
    • -
    -
  • -
  • CONDITION_NOT_MET or FAILED_PRECONDITION: This - failure can happen in the following cases: -
      -
    • Purchasing a SKU that requires domain verification and the - domain has not been verified.
    • -
    • Purchasing an Add-On SKU like Vault or Drive without purchasing - the pre-requisite SKU, such as Google Workspace Business Starter.
    • -
    • Applicable only for developer accounts: reseller and resold - domain. Must meet the following domain naming requirements: -
        -
      • Domain names must start with goog-test.
      • -
      • Resold domain names must include the reseller domain.
      • -
      -
    • -
    -
  • -
  • INTERNAL: Any non-user error related to a technical issue in the - backend. Contact Cloud Channel Support in this case.
  • -
  • UNKNOWN: Any non-user error related to a technical issue in the - backend. Contact Cloud Channel Support in this case.
  • -
+ - PERMISSION_DENIED: If the customer doesn't belong to the + reseller. + - INVALID_ARGUMENT: It can happen in below scenarios - + + - Missing or invalid required parameters in the request. + - Cannot purchase an entitlement if there is already an + entitlement for customer, for a SKU from the same product + family. + - INVALID_VALUE: Offer passed in isn't valid. Make sure + OfferId is valid. If it is valid, then contact Google + Channel support for further troubleshooting. + + - NOT_FOUND: If the customer or offer resource is not found for + the reseller. + - ALREADY_EXISTS: This failure can happen in the following + cases: + + - If the SKU has been already purchased for the customer. + - If the customer's primary email already exists. In this + case retry after changing the customer's primary contact + email. + + - CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can + happen in the following cases: + + - Purchasing a SKU that requires domain verification and the + domain has not been verified. + - Purchasing an Add-On SKU like Vault or Drive without + purchasing the pre-requisite SKU, such as Google Workspace + Business Starter. + - Applicable only for developer accounts: reseller and + resold domain. Must meet the following domain naming + requirements: + + - Domain names must start with goog-test. + - Resold domain names must include the reseller domain. + + - INTERNAL: Any non-user error related to a technical issue in + the backend. Contact Cloud Channel Support in this case. + - UNKNOWN: Any non-user error related to a technical issue in + the backend. Contact Cloud Channel Support in this case. Return Value: Long Running Operation ID. @@ -1784,35 +1802,36 @@ async def transfer_entitlements( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED: If the customer doesn't belong to the - reseller.
  • INVALID_ARGUMENT: Missing or invalid required - parameters in the request.
  • NOT_FOUND: If the customer or offer - resource is not found for the reseller.
  • ALREADY_EXISTS: If the - SKU has been already transferred for the customer.
  • - CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can happen in the - following cases:
      -
    • Transferring a SKU that requires domain verification and the - domain has not been verified.
    • -
    • Transferring an Add-On SKU like Vault or Drive without transferring - the pre-requisite SKU, such as G Suite Basic
    • Applicable only for - developer accounts: reseller and resold domain must follow the domain - naming convention as follows: -
        -
      • Domain names must start with goog-test.
      • -
      • Resold domain names must include the reseller domain.
      • -
      -
    • -
    • All transferring entitlements must be specified.
    • -
    -
  • -
  • INTERNAL: Any non-user error related to a technical issue in the - backend. Please contact Cloud Channel Support in this case.
  • -
  • UNKNOWN: Any non-user error related to a technical issue in the - backend. Please contact Cloud Channel Support in this case.
  • -
+ - PERMISSION_DENIED: If the customer doesn't belong to the + reseller. + - INVALID_ARGUMENT: Missing or invalid required parameters in + the request. + - NOT_FOUND: If the customer or offer resource is not found for + the reseller. + - ALREADY_EXISTS: If the SKU has been already transferred for + the customer. + - CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can + happen in the following cases: + + - Transferring a SKU that requires domain verification and + the domain has not been verified. + - Transferring an Add-On SKU like Vault or Drive without + transferring the pre-requisite SKU, such as G Suite Basic. + - Applicable only for developer accounts: reseller and + resold domain must follow the domain naming convention as + follows: + + - Domain names must start with goog-test. + - Resold domain names must include the reseller domain. + + - All transferring entitlements must be specified. + + - INTERNAL: Any non-user error related to a technical issue in + the backend. Please contact Cloud Channel Support in this + case. + - UNKNOWN: Any non-user error related to a technical issue in + the backend. Please contact Cloud Channel Support in this + case. Return Value: Long Running Operation ID. @@ -1885,37 +1904,34 @@ async def transfer_entitlements_to_google( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED: If the customer doesn't belong to the reseller. -
  • INVALID_ARGUMENT: Missing or invalid required parameters in the - request.
  • -
  • NOT_FOUND: If the customer or offer resource is not found - for the reseller.
  • -
  • ALREADY_EXISTS: If the SKU has been already - transferred for the customer.
  • -
  • CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can happen in - the following cases: -
      -
    • Transferring a SKU that requires domain verification and the - domain has not been verified.
    • -
    • Transferring an Add-On SKU like Vault or Drive without purchasing - the pre-requisite SKU, such as G Suite Basic
    • Applicable only for - developer accounts: reseller and resold domain must follow the domain - naming convention as follows: -
        -
      • Domain names must start with goog-test.
      • -
      • Resold domain names must include the reseller domain.
      • -
      -
    • -
    -
  • -
  • INTERNAL: Any non-user error related to a technical issue in the - backend. Please contact Cloud Channel Support in this case.
  • -
  • UNKNOWN: Any non-user error related to a technical issue in the - backend. Please contact Cloud Channel Support in this case.
  • -
+ - PERMISSION_DENIED: If the customer doesn't belong to the + reseller. + - INVALID_ARGUMENT: Missing or invalid required parameters in + the request. + - NOT_FOUND: If the customer or offer resource is not found for + the reseller. + - ALREADY_EXISTS: If the SKU has been already transferred for + the customer. + - CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can + happen in the following cases: + + - Transferring a SKU that requires domain verification and + the domain has not been verified. + - Transferring an Add-On SKU like Vault or Drive without + purchasing the pre-requisite SKU, such as G Suite Basic. + - Applicable only for developer accounts: reseller and + resold domain must follow the domain naming convention as + follows: + + - Domain names must start with goog-test. + - Resold domain names must include the reseller domain. + + - INTERNAL: Any non-user error related to a technical issue in + the backend. Please contact Cloud Channel Support in this + case. + - UNKNOWN: Any non-user error related to a technical issue in + the backend. Please contact Cloud Channel Support in this + case. Return Value: Long Running Operation ID. @@ -2219,25 +2235,20 @@ async def update_channel_partner_link( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED: If the reseller account making the request and the - reseller account being queried for are different.
  • -
  • INVALID_ARGUMENT: -
      -
    • Missing or invalid required parameters in the request.
    • -
    • Updating link state from invited to active or suspended.
    • -
    • Sending reseller_cloud_identity_id, invite_url or name in update - mask.
    • -
    -
  • -
  • NOT_FOUND: ChannelPartnerLink resource not found.
  • -
  • INTERNAL: Any non-user error related to a technical issue in the - backend. In this case, contact Cloud Channel support.
  • -
  • UNKNOWN: Any non-user error related to a technical issue in the - backend. In this case, contact Cloud Channel support.
  • -
+ - PERMISSION_DENIED: If the reseller account making the request + and the reseller account being queried for are different. + - INVALID_ARGUMENT: It can happen in following scenarios - + + - Missing or invalid required parameters in the request. + - Updating link state from invited to active or suspended. + - Sending reseller_cloud_identity_id, invite_url or name in + update mask. + + - NOT_FOUND: ChannelPartnerLink resource not found. + - INTERNAL: Any non-user error related to a technical issue in + the backend. In this case, contact Cloud Channel support. + - UNKNOWN: Any non-user error related to a technical issue in + the backend. In this case, contact Cloud Channel support. Return Value: If successful, the updated [ChannelPartnerLink][google.cloud.channel.v1.ChannelPartnerLink] diff --git a/google/cloud/channel_v1/services/cloud_channel_service/client.py b/google/cloud/channel_v1/services/cloud_channel_service/client.py index 0bb610f..e818cc9 100644 --- a/google/cloud/channel_v1/services/cloud_channel_service/client.py +++ b/google/cloud/channel_v1/services/cloud_channel_service/client.py @@ -611,14 +611,15 @@ def check_cloud_identity_accounts_exist( - INVALID_ARGUMENT: Missing or invalid required parameters in the request. - INVALID_VALUE: Invalid domain value in the request. - - NOT_FOUND: If there is no - [CloudIdentityCustomerAccount][google.cloud.channel.v1.CloudIdentityCustomerAccount] - customer for the domain specified in the request. Return Value: List of [CloudIdentityCustomerAccount][google.cloud.channel.v1.CloudIdentityCustomerAccount] - resources if any exist for the domain, otherwise an error is - returned. + resources for the domain. List may be empty. + + Note: in the v1alpha1 version of the API, a NOT_FOUND error is + returned if no + [CloudIdentityCustomerAccount][google.cloud.channel.v1.CloudIdentityCustomerAccount] + resources match the domain. Args: request (google.cloud.channel_v1.types.CheckCloudIdentityAccountsExistRequest): @@ -677,19 +678,13 @@ def create_customer( Possible Error Codes: - .. raw:: html + - PERMISSION_DENIED: If the reseller account making the request + and the reseller account being queried for are different. + - INVALID_ARGUMENT: It can happen in following scenarios - -
    -
  • PERMISSION_DENIED: If the reseller account making the request and the - reseller account being queried for are different.
  • -
  • INVALID_ARGUMENT: -
      -
    • Missing or invalid required parameters in the request.
    • -
    • Domain field value doesn't match the domain specified in primary - email.
    • -
    -
  • -
+ - Missing or invalid required parameters in the request. + - Domain field value doesn't match the domain specified in + primary email. Return Value: If successful, the newly created [Customer][google.cloud.channel.v1.Customer] resource, otherwise @@ -1062,20 +1057,16 @@ def list_transferable_skus( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED, due to one of the following reasons: -
      -
    • If the customer doesn't belong to the reseller and no auth token, - or an invalid auth token is supplied.
    • If the reseller account - making the request and the reseller account being queried for are - different.
    • -
    -
  • -
  • INVALID_ARGUMENT: Missing or invalid required parameters in the - request.
  • -
+ - PERMISSION_DENIED: Appears because of one of the following - + + - The customer doesn't belong to the reseller and no auth + token. + - The supplied auth token is invalid. + - The reseller account making the request and the queries + reseller account are different. + + - INVALID_ARGUMENT: Missing or invalid required parameters in + the request. Return Value: List of [TransferableSku][google.cloud.channel.v1.TransferableSku] for @@ -1151,11 +1142,13 @@ def list_transferable_offers( Possible Error Codes: - - PERMISSION_DENIED, due to one of the following reasons: (a) - If the customer doesn't belong to the reseller and no auth - token or invalid auth token is supplied. (b) If the reseller - account making the request and the reseller account being - queried for are different. + - PERMISSION_DENIED: Appears because of one of the following: + + - If the customer doesn't belong to the reseller and no auth + token or invalid auth token is supplied. + - If the reseller account making the request and the + reseller account being queried for are different. + - INVALID_ARGUMENT: Missing or invalid required parameters in the request. @@ -1291,50 +1284,47 @@ def create_entitlement( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED: If the customer doesn't belong to the reseller. -
  • INVALID_ARGUMENT:
      -
    • Missing or invalid required parameters in the request.
    • -
    • Cannot purchase an entitlement if there is already an - entitlement for customer, for a SKU from the same product family.
    • -
    • INVALID_VALUE: Offer passed in isn't valid. Make sure OfferId is - valid. If it is valid, then contact Google Channel support for further - troubleshooting.
    • -
    -
  • -
  • NOT_FOUND: If the customer or offer resource is not found for the - reseller.
  • -
  • ALREADY_EXISTS: This failure can happen in the following cases: -
      -
    • If the SKU has been already purchased for the customer.
    • -
    • If the customer's primary email already exists. In this case retry - after changing the customer's primary contact email. -
    • -
    -
  • -
  • CONDITION_NOT_MET or FAILED_PRECONDITION: This - failure can happen in the following cases: -
      -
    • Purchasing a SKU that requires domain verification and the - domain has not been verified.
    • -
    • Purchasing an Add-On SKU like Vault or Drive without purchasing - the pre-requisite SKU, such as Google Workspace Business Starter.
    • -
    • Applicable only for developer accounts: reseller and resold - domain. Must meet the following domain naming requirements: -
        -
      • Domain names must start with goog-test.
      • -
      • Resold domain names must include the reseller domain.
      • -
      -
    • -
    -
  • -
  • INTERNAL: Any non-user error related to a technical issue in the - backend. Contact Cloud Channel Support in this case.
  • -
  • UNKNOWN: Any non-user error related to a technical issue in the - backend. Contact Cloud Channel Support in this case.
  • -
+ - PERMISSION_DENIED: If the customer doesn't belong to the + reseller. + - INVALID_ARGUMENT: It can happen in below scenarios - + + - Missing or invalid required parameters in the request. + - Cannot purchase an entitlement if there is already an + entitlement for customer, for a SKU from the same product + family. + - INVALID_VALUE: Offer passed in isn't valid. Make sure + OfferId is valid. If it is valid, then contact Google + Channel support for further troubleshooting. + + - NOT_FOUND: If the customer or offer resource is not found for + the reseller. + - ALREADY_EXISTS: This failure can happen in the following + cases: + + - If the SKU has been already purchased for the customer. + - If the customer's primary email already exists. In this + case retry after changing the customer's primary contact + email. + + - CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can + happen in the following cases: + + - Purchasing a SKU that requires domain verification and the + domain has not been verified. + - Purchasing an Add-On SKU like Vault or Drive without + purchasing the pre-requisite SKU, such as Google Workspace + Business Starter. + - Applicable only for developer accounts: reseller and + resold domain. Must meet the following domain naming + requirements: + + - Domain names must start with goog-test. + - Resold domain names must include the reseller domain. + + - INTERNAL: Any non-user error related to a technical issue in + the backend. Contact Cloud Channel Support in this case. + - UNKNOWN: Any non-user error related to a technical issue in + the backend. Contact Cloud Channel Support in this case. Return Value: Long Running Operation ID. @@ -2044,35 +2034,36 @@ def transfer_entitlements( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED: If the customer doesn't belong to the - reseller.
  • INVALID_ARGUMENT: Missing or invalid required - parameters in the request.
  • NOT_FOUND: If the customer or offer - resource is not found for the reseller.
  • ALREADY_EXISTS: If the - SKU has been already transferred for the customer.
  • - CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can happen in the - following cases:
      -
    • Transferring a SKU that requires domain verification and the - domain has not been verified.
    • -
    • Transferring an Add-On SKU like Vault or Drive without transferring - the pre-requisite SKU, such as G Suite Basic
    • Applicable only for - developer accounts: reseller and resold domain must follow the domain - naming convention as follows: -
        -
      • Domain names must start with goog-test.
      • -
      • Resold domain names must include the reseller domain.
      • -
      -
    • -
    • All transferring entitlements must be specified.
    • -
    -
  • -
  • INTERNAL: Any non-user error related to a technical issue in the - backend. Please contact Cloud Channel Support in this case.
  • -
  • UNKNOWN: Any non-user error related to a technical issue in the - backend. Please contact Cloud Channel Support in this case.
  • -
+ - PERMISSION_DENIED: If the customer doesn't belong to the + reseller. + - INVALID_ARGUMENT: Missing or invalid required parameters in + the request. + - NOT_FOUND: If the customer or offer resource is not found for + the reseller. + - ALREADY_EXISTS: If the SKU has been already transferred for + the customer. + - CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can + happen in the following cases: + + - Transferring a SKU that requires domain verification and + the domain has not been verified. + - Transferring an Add-On SKU like Vault or Drive without + transferring the pre-requisite SKU, such as G Suite Basic. + - Applicable only for developer accounts: reseller and + resold domain must follow the domain naming convention as + follows: + + - Domain names must start with goog-test. + - Resold domain names must include the reseller domain. + + - All transferring entitlements must be specified. + + - INTERNAL: Any non-user error related to a technical issue in + the backend. Please contact Cloud Channel Support in this + case. + - UNKNOWN: Any non-user error related to a technical issue in + the backend. Please contact Cloud Channel Support in this + case. Return Value: Long Running Operation ID. @@ -2146,37 +2137,34 @@ def transfer_entitlements_to_google( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED: If the customer doesn't belong to the reseller. -
  • INVALID_ARGUMENT: Missing or invalid required parameters in the - request.
  • -
  • NOT_FOUND: If the customer or offer resource is not found - for the reseller.
  • -
  • ALREADY_EXISTS: If the SKU has been already - transferred for the customer.
  • -
  • CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can happen in - the following cases: -
      -
    • Transferring a SKU that requires domain verification and the - domain has not been verified.
    • -
    • Transferring an Add-On SKU like Vault or Drive without purchasing - the pre-requisite SKU, such as G Suite Basic
    • Applicable only for - developer accounts: reseller and resold domain must follow the domain - naming convention as follows: -
        -
      • Domain names must start with goog-test.
      • -
      • Resold domain names must include the reseller domain.
      • -
      -
    • -
    -
  • -
  • INTERNAL: Any non-user error related to a technical issue in the - backend. Please contact Cloud Channel Support in this case.
  • -
  • UNKNOWN: Any non-user error related to a technical issue in the - backend. Please contact Cloud Channel Support in this case.
  • -
+ - PERMISSION_DENIED: If the customer doesn't belong to the + reseller. + - INVALID_ARGUMENT: Missing or invalid required parameters in + the request. + - NOT_FOUND: If the customer or offer resource is not found for + the reseller. + - ALREADY_EXISTS: If the SKU has been already transferred for + the customer. + - CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can + happen in the following cases: + + - Transferring a SKU that requires domain verification and + the domain has not been verified. + - Transferring an Add-On SKU like Vault or Drive without + purchasing the pre-requisite SKU, such as G Suite Basic. + - Applicable only for developer accounts: reseller and + resold domain must follow the domain naming convention as + follows: + + - Domain names must start with goog-test. + - Resold domain names must include the reseller domain. + + - INTERNAL: Any non-user error related to a technical issue in + the backend. Please contact Cloud Channel Support in this + case. + - UNKNOWN: Any non-user error related to a technical issue in + the backend. Please contact Cloud Channel Support in this + case. Return Value: Long Running Operation ID. @@ -2490,25 +2478,20 @@ def update_channel_partner_link( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED: If the reseller account making the request and the - reseller account being queried for are different.
  • -
  • INVALID_ARGUMENT: -
      -
    • Missing or invalid required parameters in the request.
    • -
    • Updating link state from invited to active or suspended.
    • -
    • Sending reseller_cloud_identity_id, invite_url or name in update - mask.
    • -
    -
  • -
  • NOT_FOUND: ChannelPartnerLink resource not found.
  • -
  • INTERNAL: Any non-user error related to a technical issue in the - backend. In this case, contact Cloud Channel support.
  • -
  • UNKNOWN: Any non-user error related to a technical issue in the - backend. In this case, contact Cloud Channel support.
  • -
+ - PERMISSION_DENIED: If the reseller account making the request + and the reseller account being queried for are different. + - INVALID_ARGUMENT: It can happen in following scenarios - + + - Missing or invalid required parameters in the request. + - Updating link state from invited to active or suspended. + - Sending reseller_cloud_identity_id, invite_url or name in + update mask. + + - NOT_FOUND: ChannelPartnerLink resource not found. + - INTERNAL: Any non-user error related to a technical issue in + the backend. In this case, contact Cloud Channel support. + - UNKNOWN: Any non-user error related to a technical issue in + the backend. In this case, contact Cloud Channel support. Return Value: If successful, the updated [ChannelPartnerLink][google.cloud.channel.v1.ChannelPartnerLink] diff --git a/google/cloud/channel_v1/services/cloud_channel_service/pagers.py b/google/cloud/channel_v1/services/cloud_channel_service/pagers.py index 10516b4..c1e19c6 100644 --- a/google/cloud/channel_v1/services/cloud_channel_service/pagers.py +++ b/google/cloud/channel_v1/services/cloud_channel_service/pagers.py @@ -15,7 +15,16 @@ # limitations under the License. # -from typing import Any, AsyncIterable, Awaitable, Callable, Iterable, Sequence, Tuple +from typing import ( + Any, + AsyncIterable, + Awaitable, + Callable, + Iterable, + Sequence, + Tuple, + Optional, +) from google.cloud.channel_v1.types import channel_partner_links from google.cloud.channel_v1.types import customers diff --git a/google/cloud/channel_v1/services/cloud_channel_service/transports/base.py b/google/cloud/channel_v1/services/cloud_channel_service/transports/base.py index 638837c..eb5e22c 100644 --- a/google/cloud/channel_v1/services/cloud_channel_service/transports/base.py +++ b/google/cloud/channel_v1/services/cloud_channel_service/transports/base.py @@ -73,10 +73,10 @@ def __init__( scope (Optional[Sequence[str]]): A list of scopes. quota_project_id (Optional[str]): An optional project to use for billing and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + 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. @@ -84,6 +84,9 @@ def __init__( host += ":443" self._host = host + # Save the scopes. + self._scopes = scopes or self.AUTH_SCOPES + # If no credentials are provided, then determine the appropriate # defaults. if credentials and credentials_file: @@ -93,20 +96,17 @@ def __init__( if credentials_file is not None: credentials, _ = auth.load_credentials_from_file( - credentials_file, scopes=scopes, quota_project_id=quota_project_id + credentials_file, scopes=self._scopes, quota_project_id=quota_project_id ) elif credentials is None: credentials, _ = auth.default( - scopes=scopes, quota_project_id=quota_project_id + scopes=self._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 = { diff --git a/google/cloud/channel_v1/services/cloud_channel_service/transports/grpc.py b/google/cloud/channel_v1/services/cloud_channel_service/transports/grpc.py index 7ef0a39..34e8a20 100644 --- a/google/cloud/channel_v1/services/cloud_channel_service/transports/grpc.py +++ b/google/cloud/channel_v1/services/cloud_channel_service/transports/grpc.py @@ -140,7 +140,10 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -148,70 +151,50 @@ def __init__( warnings.warn("client_cert_source is deprecated", DeprecationWarning) if channel: - # Sanity check: Ensure that channel and credentials are not both - # provided. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. self._grpc_channel = channel self._ssl_channel_credentials = None - elif api_mtls_endpoint: - 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, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials else: - host = host if ":" in host else host + ":443" + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) - if client_cert_source_for_mtls and not ssl_channel_credentials: - cert, key = client_cert_source_for_mtls() - self._ssl_channel_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -219,18 +202,8 @@ def __init__( ], ) - self._stubs = {} # type: Dict[str, Callable] - self._operations_client = None - - # 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, - ) + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @classmethod def create_channel( @@ -244,7 +217,7 @@ def create_channel( ) -> grpc.Channel: """Create and return a gRPC channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If @@ -394,14 +367,15 @@ def check_cloud_identity_accounts_exist( - INVALID_ARGUMENT: Missing or invalid required parameters in the request. - INVALID_VALUE: Invalid domain value in the request. - - NOT_FOUND: If there is no - [CloudIdentityCustomerAccount][google.cloud.channel.v1.CloudIdentityCustomerAccount] - customer for the domain specified in the request. Return Value: List of [CloudIdentityCustomerAccount][google.cloud.channel.v1.CloudIdentityCustomerAccount] - resources if any exist for the domain, otherwise an error is - returned. + resources for the domain. List may be empty. + + Note: in the v1alpha1 version of the API, a NOT_FOUND error is + returned if no + [CloudIdentityCustomerAccount][google.cloud.channel.v1.CloudIdentityCustomerAccount] + resources match the domain. Returns: Callable[[~.CheckCloudIdentityAccountsExistRequest], @@ -434,19 +408,13 @@ def create_customer( Possible Error Codes: - .. raw:: html + - PERMISSION_DENIED: If the reseller account making the request + and the reseller account being queried for are different. + - INVALID_ARGUMENT: It can happen in following scenarios - -
    -
  • PERMISSION_DENIED: If the reseller account making the request and the - reseller account being queried for are different.
  • -
  • INVALID_ARGUMENT: -
      -
    • Missing or invalid required parameters in the request.
    • -
    • Domain field value doesn't match the domain specified in primary - email.
    • -
    -
  • -
+ - Missing or invalid required parameters in the request. + - Domain field value doesn't match the domain specified in + primary email. Return Value: If successful, the newly created [Customer][google.cloud.channel.v1.Customer] resource, otherwise @@ -652,20 +620,16 @@ def list_transferable_skus( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED, due to one of the following reasons: -
      -
    • If the customer doesn't belong to the reseller and no auth token, - or an invalid auth token is supplied.
    • If the reseller account - making the request and the reseller account being queried for are - different.
    • -
    -
  • -
  • INVALID_ARGUMENT: Missing or invalid required parameters in the - request.
  • -
+ - PERMISSION_DENIED: Appears because of one of the following - + + - The customer doesn't belong to the reseller and no auth + token. + - The supplied auth token is invalid. + - The reseller account making the request and the queries + reseller account are different. + + - INVALID_ARGUMENT: Missing or invalid required parameters in + the request. Return Value: List of [TransferableSku][google.cloud.channel.v1.TransferableSku] for @@ -708,11 +672,13 @@ def list_transferable_offers( Possible Error Codes: - - PERMISSION_DENIED, due to one of the following reasons: (a) - If the customer doesn't belong to the reseller and no auth - token or invalid auth token is supplied. (b) If the reseller - account making the request and the reseller account being - queried for are different. + - PERMISSION_DENIED: Appears because of one of the following: + + - If the customer doesn't belong to the reseller and no auth + token or invalid auth token is supplied. + - If the reseller account making the request and the + reseller account being queried for are different. + - INVALID_ARGUMENT: Missing or invalid required parameters in the request. @@ -787,50 +753,47 @@ def create_entitlement( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED: If the customer doesn't belong to the reseller. -
  • INVALID_ARGUMENT:
      -
    • Missing or invalid required parameters in the request.
    • -
    • Cannot purchase an entitlement if there is already an - entitlement for customer, for a SKU from the same product family.
    • -
    • INVALID_VALUE: Offer passed in isn't valid. Make sure OfferId is - valid. If it is valid, then contact Google Channel support for further - troubleshooting.
    • -
    -
  • -
  • NOT_FOUND: If the customer or offer resource is not found for the - reseller.
  • -
  • ALREADY_EXISTS: This failure can happen in the following cases: -
      -
    • If the SKU has been already purchased for the customer.
    • -
    • If the customer's primary email already exists. In this case retry - after changing the customer's primary contact email. -
    • -
    -
  • -
  • CONDITION_NOT_MET or FAILED_PRECONDITION: This - failure can happen in the following cases: -
      -
    • Purchasing a SKU that requires domain verification and the - domain has not been verified.
    • -
    • Purchasing an Add-On SKU like Vault or Drive without purchasing - the pre-requisite SKU, such as Google Workspace Business Starter.
    • -
    • Applicable only for developer accounts: reseller and resold - domain. Must meet the following domain naming requirements: -
        -
      • Domain names must start with goog-test.
      • -
      • Resold domain names must include the reseller domain.
      • -
      -
    • -
    -
  • -
  • INTERNAL: Any non-user error related to a technical issue in the - backend. Contact Cloud Channel Support in this case.
  • -
  • UNKNOWN: Any non-user error related to a technical issue in the - backend. Contact Cloud Channel Support in this case.
  • -
+ - PERMISSION_DENIED: If the customer doesn't belong to the + reseller. + - INVALID_ARGUMENT: It can happen in below scenarios - + + - Missing or invalid required parameters in the request. + - Cannot purchase an entitlement if there is already an + entitlement for customer, for a SKU from the same product + family. + - INVALID_VALUE: Offer passed in isn't valid. Make sure + OfferId is valid. If it is valid, then contact Google + Channel support for further troubleshooting. + + - NOT_FOUND: If the customer or offer resource is not found for + the reseller. + - ALREADY_EXISTS: This failure can happen in the following + cases: + + - If the SKU has been already purchased for the customer. + - If the customer's primary email already exists. In this + case retry after changing the customer's primary contact + email. + + - CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can + happen in the following cases: + + - Purchasing a SKU that requires domain verification and the + domain has not been verified. + - Purchasing an Add-On SKU like Vault or Drive without + purchasing the pre-requisite SKU, such as Google Workspace + Business Starter. + - Applicable only for developer accounts: reseller and + resold domain. Must meet the following domain naming + requirements: + + - Domain names must start with goog-test. + - Resold domain names must include the reseller domain. + + - INTERNAL: Any non-user error related to a technical issue in + the backend. Contact Cloud Channel Support in this case. + - UNKNOWN: Any non-user error related to a technical issue in + the backend. Contact Cloud Channel Support in this case. Return Value: Long Running Operation ID. @@ -1227,35 +1190,36 @@ def transfer_entitlements( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED: If the customer doesn't belong to the - reseller.
  • INVALID_ARGUMENT: Missing or invalid required - parameters in the request.
  • NOT_FOUND: If the customer or offer - resource is not found for the reseller.
  • ALREADY_EXISTS: If the - SKU has been already transferred for the customer.
  • - CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can happen in the - following cases:
      -
    • Transferring a SKU that requires domain verification and the - domain has not been verified.
    • -
    • Transferring an Add-On SKU like Vault or Drive without transferring - the pre-requisite SKU, such as G Suite Basic
    • Applicable only for - developer accounts: reseller and resold domain must follow the domain - naming convention as follows: -
        -
      • Domain names must start with goog-test.
      • -
      • Resold domain names must include the reseller domain.
      • -
      -
    • -
    • All transferring entitlements must be specified.
    • -
    -
  • -
  • INTERNAL: Any non-user error related to a technical issue in the - backend. Please contact Cloud Channel Support in this case.
  • -
  • UNKNOWN: Any non-user error related to a technical issue in the - backend. Please contact Cloud Channel Support in this case.
  • -
+ - PERMISSION_DENIED: If the customer doesn't belong to the + reseller. + - INVALID_ARGUMENT: Missing or invalid required parameters in + the request. + - NOT_FOUND: If the customer or offer resource is not found for + the reseller. + - ALREADY_EXISTS: If the SKU has been already transferred for + the customer. + - CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can + happen in the following cases: + + - Transferring a SKU that requires domain verification and + the domain has not been verified. + - Transferring an Add-On SKU like Vault or Drive without + transferring the pre-requisite SKU, such as G Suite Basic. + - Applicable only for developer accounts: reseller and + resold domain must follow the domain naming convention as + follows: + + - Domain names must start with goog-test. + - Resold domain names must include the reseller domain. + + - All transferring entitlements must be specified. + + - INTERNAL: Any non-user error related to a technical issue in + the backend. Please contact Cloud Channel Support in this + case. + - UNKNOWN: Any non-user error related to a technical issue in + the backend. Please contact Cloud Channel Support in this + case. Return Value: Long Running Operation ID. @@ -1293,37 +1257,34 @@ def transfer_entitlements_to_google( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED: If the customer doesn't belong to the reseller. -
  • INVALID_ARGUMENT: Missing or invalid required parameters in the - request.
  • -
  • NOT_FOUND: If the customer or offer resource is not found - for the reseller.
  • -
  • ALREADY_EXISTS: If the SKU has been already - transferred for the customer.
  • -
  • CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can happen in - the following cases: -
      -
    • Transferring a SKU that requires domain verification and the - domain has not been verified.
    • -
    • Transferring an Add-On SKU like Vault or Drive without purchasing - the pre-requisite SKU, such as G Suite Basic
    • Applicable only for - developer accounts: reseller and resold domain must follow the domain - naming convention as follows: -
        -
      • Domain names must start with goog-test.
      • -
      • Resold domain names must include the reseller domain.
      • -
      -
    • -
    -
  • -
  • INTERNAL: Any non-user error related to a technical issue in the - backend. Please contact Cloud Channel Support in this case.
  • -
  • UNKNOWN: Any non-user error related to a technical issue in the - backend. Please contact Cloud Channel Support in this case.
  • -
+ - PERMISSION_DENIED: If the customer doesn't belong to the + reseller. + - INVALID_ARGUMENT: Missing or invalid required parameters in + the request. + - NOT_FOUND: If the customer or offer resource is not found for + the reseller. + - ALREADY_EXISTS: If the SKU has been already transferred for + the customer. + - CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can + happen in the following cases: + + - Transferring a SKU that requires domain verification and + the domain has not been verified. + - Transferring an Add-On SKU like Vault or Drive without + purchasing the pre-requisite SKU, such as G Suite Basic. + - Applicable only for developer accounts: reseller and + resold domain must follow the domain naming convention as + follows: + + - Domain names must start with goog-test. + - Resold domain names must include the reseller domain. + + - INTERNAL: Any non-user error related to a technical issue in + the backend. Please contact Cloud Channel Support in this + case. + - UNKNOWN: Any non-user error related to a technical issue in + the backend. Please contact Cloud Channel Support in this + case. Return Value: Long Running Operation ID. @@ -1508,25 +1469,20 @@ def update_channel_partner_link( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED: If the reseller account making the request and the - reseller account being queried for are different.
  • -
  • INVALID_ARGUMENT: -
      -
    • Missing or invalid required parameters in the request.
    • -
    • Updating link state from invited to active or suspended.
    • -
    • Sending reseller_cloud_identity_id, invite_url or name in update - mask.
    • -
    -
  • -
  • NOT_FOUND: ChannelPartnerLink resource not found.
  • -
  • INTERNAL: Any non-user error related to a technical issue in the - backend. In this case, contact Cloud Channel support.
  • -
  • UNKNOWN: Any non-user error related to a technical issue in the - backend. In this case, contact Cloud Channel support.
  • -
+ - PERMISSION_DENIED: If the reseller account making the request + and the reseller account being queried for are different. + - INVALID_ARGUMENT: It can happen in following scenarios - + + - Missing or invalid required parameters in the request. + - Updating link state from invited to active or suspended. + - Sending reseller_cloud_identity_id, invite_url or name in + update mask. + + - NOT_FOUND: ChannelPartnerLink resource not found. + - INTERNAL: Any non-user error related to a technical issue in + the backend. In this case, contact Cloud Channel support. + - UNKNOWN: Any non-user error related to a technical issue in + the backend. In this case, contact Cloud Channel support. Return Value: If successful, the updated [ChannelPartnerLink][google.cloud.channel.v1.ChannelPartnerLink] diff --git a/google/cloud/channel_v1/services/cloud_channel_service/transports/grpc_asyncio.py b/google/cloud/channel_v1/services/cloud_channel_service/transports/grpc_asyncio.py index 51b6913..b086617 100644 --- a/google/cloud/channel_v1/services/cloud_channel_service/transports/grpc_asyncio.py +++ b/google/cloud/channel_v1/services/cloud_channel_service/transports/grpc_asyncio.py @@ -95,7 +95,7 @@ def create_channel( ) -> aio.Channel: """Create and return a gRPC AsyncIO channel object. Args: - address (Optional[str]): The host for the channel to use. + host (Optional[str]): The host for the channel to use. credentials (Optional[~.Credentials]): The authorization credentials to attach to requests. These credentials identify this application to the service. If @@ -173,10 +173,10 @@ def __init__( ignored if ``channel`` or ``ssl_channel_credentials`` is provided. quota_project_id (Optional[str]): An optional project to use for billing and quota. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing + 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: @@ -185,7 +185,10 @@ def __init__( google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` and ``credentials_file`` are passed. """ + self._grpc_channel = None self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + self._operations_client = None if api_mtls_endpoint: warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) @@ -193,70 +196,50 @@ def __init__( warnings.warn("client_cert_source is deprecated", DeprecationWarning) if channel: - # Sanity check: Ensure that channel and credentials are not both - # provided. + # Ignore credentials if a channel was passed. credentials = False - # If a channel was explicitly provided, set it. self._grpc_channel = channel self._ssl_channel_credentials = None - elif api_mtls_endpoint: - 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, - options=[ - ("grpc.max_send_message_length", -1), - ("grpc.max_receive_message_length", -1), - ], - ) - self._ssl_channel_credentials = ssl_credentials else: - host = host if ":" in host else host + ":443" + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials - if credentials is None: - credentials, _ = auth.default( - scopes=self.AUTH_SCOPES, quota_project_id=quota_project_id - ) + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) - if client_cert_source_for_mtls and not ssl_channel_credentials: - cert, key = client_cert_source_for_mtls() - self._ssl_channel_credentials = grpc.ssl_channel_credentials( - certificate_chain=cert, private_key=key - ) + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + ) - # create a new channel. The provided one is ignored. + if not self._grpc_channel: self._grpc_channel = type(self).create_channel( - host, - credentials=credentials, + self._host, + credentials=self._credentials, credentials_file=credentials_file, + scopes=self._scopes, ssl_credentials=self._ssl_channel_credentials, - scopes=scopes or self.AUTH_SCOPES, quota_project_id=quota_project_id, options=[ ("grpc.max_send_message_length", -1), @@ -264,18 +247,8 @@ def __init__( ], ) - # 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 = {} - self._operations_client = None + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) @property def grpc_channel(self) -> aio.Channel: @@ -402,14 +375,15 @@ def check_cloud_identity_accounts_exist( - INVALID_ARGUMENT: Missing or invalid required parameters in the request. - INVALID_VALUE: Invalid domain value in the request. - - NOT_FOUND: If there is no - [CloudIdentityCustomerAccount][google.cloud.channel.v1.CloudIdentityCustomerAccount] - customer for the domain specified in the request. Return Value: List of [CloudIdentityCustomerAccount][google.cloud.channel.v1.CloudIdentityCustomerAccount] - resources if any exist for the domain, otherwise an error is - returned. + resources for the domain. List may be empty. + + Note: in the v1alpha1 version of the API, a NOT_FOUND error is + returned if no + [CloudIdentityCustomerAccount][google.cloud.channel.v1.CloudIdentityCustomerAccount] + resources match the domain. Returns: Callable[[~.CheckCloudIdentityAccountsExistRequest], @@ -442,19 +416,13 @@ def create_customer( Possible Error Codes: - .. raw:: html + - PERMISSION_DENIED: If the reseller account making the request + and the reseller account being queried for are different. + - INVALID_ARGUMENT: It can happen in following scenarios - -
    -
  • PERMISSION_DENIED: If the reseller account making the request and the - reseller account being queried for are different.
  • -
  • INVALID_ARGUMENT: -
      -
    • Missing or invalid required parameters in the request.
    • -
    • Domain field value doesn't match the domain specified in primary - email.
    • -
    -
  • -
+ - Missing or invalid required parameters in the request. + - Domain field value doesn't match the domain specified in + primary email. Return Value: If successful, the newly created [Customer][google.cloud.channel.v1.Customer] resource, otherwise @@ -667,20 +635,16 @@ def list_transferable_skus( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED, due to one of the following reasons: -
      -
    • If the customer doesn't belong to the reseller and no auth token, - or an invalid auth token is supplied.
    • If the reseller account - making the request and the reseller account being queried for are - different.
    • -
    -
  • -
  • INVALID_ARGUMENT: Missing or invalid required parameters in the - request.
  • -
+ - PERMISSION_DENIED: Appears because of one of the following - + + - The customer doesn't belong to the reseller and no auth + token. + - The supplied auth token is invalid. + - The reseller account making the request and the queries + reseller account are different. + + - INVALID_ARGUMENT: Missing or invalid required parameters in + the request. Return Value: List of [TransferableSku][google.cloud.channel.v1.TransferableSku] for @@ -724,11 +688,13 @@ def list_transferable_offers( Possible Error Codes: - - PERMISSION_DENIED, due to one of the following reasons: (a) - If the customer doesn't belong to the reseller and no auth - token or invalid auth token is supplied. (b) If the reseller - account making the request and the reseller account being - queried for are different. + - PERMISSION_DENIED: Appears because of one of the following: + + - If the customer doesn't belong to the reseller and no auth + token or invalid auth token is supplied. + - If the reseller account making the request and the + reseller account being queried for are different. + - INVALID_ARGUMENT: Missing or invalid required parameters in the request. @@ -803,50 +769,47 @@ def create_entitlement( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED: If the customer doesn't belong to the reseller. -
  • INVALID_ARGUMENT:
      -
    • Missing or invalid required parameters in the request.
    • -
    • Cannot purchase an entitlement if there is already an - entitlement for customer, for a SKU from the same product family.
    • -
    • INVALID_VALUE: Offer passed in isn't valid. Make sure OfferId is - valid. If it is valid, then contact Google Channel support for further - troubleshooting.
    • -
    -
  • -
  • NOT_FOUND: If the customer or offer resource is not found for the - reseller.
  • -
  • ALREADY_EXISTS: This failure can happen in the following cases: -
      -
    • If the SKU has been already purchased for the customer.
    • -
    • If the customer's primary email already exists. In this case retry - after changing the customer's primary contact email. -
    • -
    -
  • -
  • CONDITION_NOT_MET or FAILED_PRECONDITION: This - failure can happen in the following cases: -
      -
    • Purchasing a SKU that requires domain verification and the - domain has not been verified.
    • -
    • Purchasing an Add-On SKU like Vault or Drive without purchasing - the pre-requisite SKU, such as Google Workspace Business Starter.
    • -
    • Applicable only for developer accounts: reseller and resold - domain. Must meet the following domain naming requirements: -
        -
      • Domain names must start with goog-test.
      • -
      • Resold domain names must include the reseller domain.
      • -
      -
    • -
    -
  • -
  • INTERNAL: Any non-user error related to a technical issue in the - backend. Contact Cloud Channel Support in this case.
  • -
  • UNKNOWN: Any non-user error related to a technical issue in the - backend. Contact Cloud Channel Support in this case.
  • -
+ - PERMISSION_DENIED: If the customer doesn't belong to the + reseller. + - INVALID_ARGUMENT: It can happen in below scenarios - + + - Missing or invalid required parameters in the request. + - Cannot purchase an entitlement if there is already an + entitlement for customer, for a SKU from the same product + family. + - INVALID_VALUE: Offer passed in isn't valid. Make sure + OfferId is valid. If it is valid, then contact Google + Channel support for further troubleshooting. + + - NOT_FOUND: If the customer or offer resource is not found for + the reseller. + - ALREADY_EXISTS: This failure can happen in the following + cases: + + - If the SKU has been already purchased for the customer. + - If the customer's primary email already exists. In this + case retry after changing the customer's primary contact + email. + + - CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can + happen in the following cases: + + - Purchasing a SKU that requires domain verification and the + domain has not been verified. + - Purchasing an Add-On SKU like Vault or Drive without + purchasing the pre-requisite SKU, such as Google Workspace + Business Starter. + - Applicable only for developer accounts: reseller and + resold domain. Must meet the following domain naming + requirements: + + - Domain names must start with goog-test. + - Resold domain names must include the reseller domain. + + - INTERNAL: Any non-user error related to a technical issue in + the backend. Contact Cloud Channel Support in this case. + - UNKNOWN: Any non-user error related to a technical issue in + the backend. Contact Cloud Channel Support in this case. Return Value: Long Running Operation ID. @@ -1249,35 +1212,36 @@ def transfer_entitlements( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED: If the customer doesn't belong to the - reseller.
  • INVALID_ARGUMENT: Missing or invalid required - parameters in the request.
  • NOT_FOUND: If the customer or offer - resource is not found for the reseller.
  • ALREADY_EXISTS: If the - SKU has been already transferred for the customer.
  • - CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can happen in the - following cases:
      -
    • Transferring a SKU that requires domain verification and the - domain has not been verified.
    • -
    • Transferring an Add-On SKU like Vault or Drive without transferring - the pre-requisite SKU, such as G Suite Basic
    • Applicable only for - developer accounts: reseller and resold domain must follow the domain - naming convention as follows: -
        -
      • Domain names must start with goog-test.
      • -
      • Resold domain names must include the reseller domain.
      • -
      -
    • -
    • All transferring entitlements must be specified.
    • -
    -
  • -
  • INTERNAL: Any non-user error related to a technical issue in the - backend. Please contact Cloud Channel Support in this case.
  • -
  • UNKNOWN: Any non-user error related to a technical issue in the - backend. Please contact Cloud Channel Support in this case.
  • -
+ - PERMISSION_DENIED: If the customer doesn't belong to the + reseller. + - INVALID_ARGUMENT: Missing or invalid required parameters in + the request. + - NOT_FOUND: If the customer or offer resource is not found for + the reseller. + - ALREADY_EXISTS: If the SKU has been already transferred for + the customer. + - CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can + happen in the following cases: + + - Transferring a SKU that requires domain verification and + the domain has not been verified. + - Transferring an Add-On SKU like Vault or Drive without + transferring the pre-requisite SKU, such as G Suite Basic. + - Applicable only for developer accounts: reseller and + resold domain must follow the domain naming convention as + follows: + + - Domain names must start with goog-test. + - Resold domain names must include the reseller domain. + + - All transferring entitlements must be specified. + + - INTERNAL: Any non-user error related to a technical issue in + the backend. Please contact Cloud Channel Support in this + case. + - UNKNOWN: Any non-user error related to a technical issue in + the backend. Please contact Cloud Channel Support in this + case. Return Value: Long Running Operation ID. @@ -1317,37 +1281,34 @@ def transfer_entitlements_to_google( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED: If the customer doesn't belong to the reseller. -
  • INVALID_ARGUMENT: Missing or invalid required parameters in the - request.
  • -
  • NOT_FOUND: If the customer or offer resource is not found - for the reseller.
  • -
  • ALREADY_EXISTS: If the SKU has been already - transferred for the customer.
  • -
  • CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can happen in - the following cases: -
      -
    • Transferring a SKU that requires domain verification and the - domain has not been verified.
    • -
    • Transferring an Add-On SKU like Vault or Drive without purchasing - the pre-requisite SKU, such as G Suite Basic
    • Applicable only for - developer accounts: reseller and resold domain must follow the domain - naming convention as follows: -
        -
      • Domain names must start with goog-test.
      • -
      • Resold domain names must include the reseller domain.
      • -
      -
    • -
    -
  • -
  • INTERNAL: Any non-user error related to a technical issue in the - backend. Please contact Cloud Channel Support in this case.
  • -
  • UNKNOWN: Any non-user error related to a technical issue in the - backend. Please contact Cloud Channel Support in this case.
  • -
+ - PERMISSION_DENIED: If the customer doesn't belong to the + reseller. + - INVALID_ARGUMENT: Missing or invalid required parameters in + the request. + - NOT_FOUND: If the customer or offer resource is not found for + the reseller. + - ALREADY_EXISTS: If the SKU has been already transferred for + the customer. + - CONDITION_NOT_MET or FAILED_PRECONDITION: This failure can + happen in the following cases: + + - Transferring a SKU that requires domain verification and + the domain has not been verified. + - Transferring an Add-On SKU like Vault or Drive without + purchasing the pre-requisite SKU, such as G Suite Basic. + - Applicable only for developer accounts: reseller and + resold domain must follow the domain naming convention as + follows: + + - Domain names must start with goog-test. + - Resold domain names must include the reseller domain. + + - INTERNAL: Any non-user error related to a technical issue in + the backend. Please contact Cloud Channel Support in this + case. + - UNKNOWN: Any non-user error related to a technical issue in + the backend. Please contact Cloud Channel Support in this + case. Return Value: Long Running Operation ID. @@ -1533,25 +1494,20 @@ def update_channel_partner_link( Possible Error Codes: - .. raw:: html - -
    -
  • PERMISSION_DENIED: If the reseller account making the request and the - reseller account being queried for are different.
  • -
  • INVALID_ARGUMENT: -
      -
    • Missing or invalid required parameters in the request.
    • -
    • Updating link state from invited to active or suspended.
    • -
    • Sending reseller_cloud_identity_id, invite_url or name in update - mask.
    • -
    -
  • -
  • NOT_FOUND: ChannelPartnerLink resource not found.
  • -
  • INTERNAL: Any non-user error related to a technical issue in the - backend. In this case, contact Cloud Channel support.
  • -
  • UNKNOWN: Any non-user error related to a technical issue in the - backend. In this case, contact Cloud Channel support.
  • -
+ - PERMISSION_DENIED: If the reseller account making the request + and the reseller account being queried for are different. + - INVALID_ARGUMENT: It can happen in following scenarios - + + - Missing or invalid required parameters in the request. + - Updating link state from invited to active or suspended. + - Sending reseller_cloud_identity_id, invite_url or name in + update mask. + + - NOT_FOUND: ChannelPartnerLink resource not found. + - INTERNAL: Any non-user error related to a technical issue in + the backend. In this case, contact Cloud Channel support. + - UNKNOWN: Any non-user error related to a technical issue in + the backend. In this case, contact Cloud Channel support. Return Value: If successful, the updated [ChannelPartnerLink][google.cloud.channel.v1.ChannelPartnerLink] diff --git a/google/cloud/channel_v1/types/__init__.py b/google/cloud/channel_v1/types/__init__.py index 3acdc3a..e0de3c6 100644 --- a/google/cloud/channel_v1/types/__init__.py +++ b/google/cloud/channel_v1/types/__init__.py @@ -15,110 +15,110 @@ # limitations under the License. # -from .common import ( - EduData, - CloudIdentityInfo, - Value, - AdminUser, -) from .channel_partner_links import ( ChannelPartnerLink, - ChannelPartnerLinkView, ChannelPartnerLinkState, + ChannelPartnerLinkView, +) +from .common import ( + AdminUser, + CloudIdentityInfo, + EduData, + Value, ) from .customers import ( - Customer, ContactInfo, + Customer, ) -from .products import ( - Product, - Sku, - MarketingInfo, - Media, - MediaType, +from .entitlements import ( + AssociationInfo, + CommitmentSettings, + Entitlement, + Parameter, + ProvisionedService, + RenewalSettings, + TransferableSku, + TransferEligibility, + TrialSettings, ) from .offers import ( - Offer, - ParameterDefinition, Constraints, CustomerConstraints, + Offer, + ParameterDefinition, + Period, Plan, - PriceByResource, Price, + PriceByResource, PricePhase, PriceTier, - Period, - PromotionalOrderType, PaymentPlan, PaymentType, - ResourceType, PeriodType, -) -from .entitlements import ( - Entitlement, - Parameter, - AssociationInfo, - ProvisionedService, - CommitmentSettings, - RenewalSettings, - TrialSettings, - TransferableSku, - TransferEligibility, + PromotionalOrderType, + ResourceType, ) from .operations import OperationMetadata +from .products import ( + MarketingInfo, + Media, + Product, + Sku, + MediaType, +) from .service import ( + ActivateEntitlementRequest, + CancelEntitlementRequest, + ChangeOfferRequest, + ChangeParametersRequest, + ChangeRenewalSettingsRequest, CheckCloudIdentityAccountsExistRequest, - CloudIdentityCustomerAccount, CheckCloudIdentityAccountsExistResponse, - ListCustomersRequest, - ListCustomersResponse, - GetCustomerRequest, + CloudIdentityCustomerAccount, + CreateChannelPartnerLinkRequest, CreateCustomerRequest, - UpdateCustomerRequest, + CreateEntitlementRequest, DeleteCustomerRequest, - ProvisionCloudIdentityRequest, - ListEntitlementsRequest, - ListEntitlementsResponse, - ListTransferableSkusRequest, - ListTransferableSkusResponse, - ListTransferableOffersRequest, - ListTransferableOffersResponse, - TransferableOffer, + GetChannelPartnerLinkRequest, + GetCustomerRequest, GetEntitlementRequest, ListChannelPartnerLinksRequest, ListChannelPartnerLinksResponse, - GetChannelPartnerLinkRequest, - CreateChannelPartnerLinkRequest, - UpdateChannelPartnerLinkRequest, - CreateEntitlementRequest, - TransferEntitlementsRequest, - TransferEntitlementsResponse, - TransferEntitlementsToGoogleRequest, - ChangeParametersRequest, - ChangeRenewalSettingsRequest, - ChangeOfferRequest, - StartPaidServiceRequest, - CancelEntitlementRequest, - SuspendEntitlementRequest, - ActivateEntitlementRequest, - ListProductsRequest, - ListProductsResponse, - ListSkusRequest, - ListSkusResponse, + ListCustomersRequest, + ListCustomersResponse, + ListEntitlementsRequest, + ListEntitlementsResponse, ListOffersRequest, ListOffersResponse, - ListPurchasableSkusRequest, - ListPurchasableSkusResponse, - PurchasableSku, + ListProductsRequest, + ListProductsResponse, ListPurchasableOffersRequest, ListPurchasableOffersResponse, + ListPurchasableSkusRequest, + ListPurchasableSkusResponse, + ListSkusRequest, + ListSkusResponse, + ListSubscribersRequest, + ListSubscribersResponse, + ListTransferableOffersRequest, + ListTransferableOffersResponse, + ListTransferableSkusRequest, + ListTransferableSkusResponse, + ProvisionCloudIdentityRequest, PurchasableOffer, + PurchasableSku, RegisterSubscriberRequest, RegisterSubscriberResponse, + StartPaidServiceRequest, + SuspendEntitlementRequest, + TransferableOffer, + TransferEntitlementsRequest, + TransferEntitlementsResponse, + TransferEntitlementsToGoogleRequest, UnregisterSubscriberRequest, UnregisterSubscriberResponse, - ListSubscribersRequest, - ListSubscribersResponse, + UpdateChannelPartnerLinkRequest, + UpdateCustomerRequest, ) from .subscriber_event import ( CustomerEvent, @@ -127,97 +127,97 @@ ) __all__ = ( - "EduData", - "CloudIdentityInfo", - "Value", - "AdminUser", "ChannelPartnerLink", - "ChannelPartnerLinkView", "ChannelPartnerLinkState", - "Customer", + "ChannelPartnerLinkView", + "AdminUser", + "CloudIdentityInfo", + "EduData", + "Value", "ContactInfo", - "Product", - "Sku", - "MarketingInfo", - "Media", - "MediaType", - "Offer", - "ParameterDefinition", + "Customer", + "AssociationInfo", + "CommitmentSettings", + "Entitlement", + "Parameter", + "ProvisionedService", + "RenewalSettings", + "TransferableSku", + "TransferEligibility", + "TrialSettings", "Constraints", "CustomerConstraints", + "Offer", + "ParameterDefinition", + "Period", "Plan", - "PriceByResource", "Price", + "PriceByResource", "PricePhase", "PriceTier", - "Period", - "PromotionalOrderType", "PaymentPlan", "PaymentType", - "ResourceType", "PeriodType", - "Entitlement", - "Parameter", - "AssociationInfo", - "ProvisionedService", - "CommitmentSettings", - "RenewalSettings", - "TrialSettings", - "TransferableSku", - "TransferEligibility", + "PromotionalOrderType", + "ResourceType", "OperationMetadata", + "MarketingInfo", + "Media", + "Product", + "Sku", + "MediaType", + "ActivateEntitlementRequest", + "CancelEntitlementRequest", + "ChangeOfferRequest", + "ChangeParametersRequest", + "ChangeRenewalSettingsRequest", "CheckCloudIdentityAccountsExistRequest", - "CloudIdentityCustomerAccount", "CheckCloudIdentityAccountsExistResponse", - "ListCustomersRequest", - "ListCustomersResponse", - "GetCustomerRequest", + "CloudIdentityCustomerAccount", + "CreateChannelPartnerLinkRequest", "CreateCustomerRequest", - "UpdateCustomerRequest", + "CreateEntitlementRequest", "DeleteCustomerRequest", - "ProvisionCloudIdentityRequest", - "ListEntitlementsRequest", - "ListEntitlementsResponse", - "ListTransferableSkusRequest", - "ListTransferableSkusResponse", - "ListTransferableOffersRequest", - "ListTransferableOffersResponse", - "TransferableOffer", + "GetChannelPartnerLinkRequest", + "GetCustomerRequest", "GetEntitlementRequest", "ListChannelPartnerLinksRequest", "ListChannelPartnerLinksResponse", - "GetChannelPartnerLinkRequest", - "CreateChannelPartnerLinkRequest", - "UpdateChannelPartnerLinkRequest", - "CreateEntitlementRequest", - "TransferEntitlementsRequest", - "TransferEntitlementsResponse", - "TransferEntitlementsToGoogleRequest", - "ChangeParametersRequest", - "ChangeRenewalSettingsRequest", - "ChangeOfferRequest", - "StartPaidServiceRequest", - "CancelEntitlementRequest", - "SuspendEntitlementRequest", - "ActivateEntitlementRequest", - "ListProductsRequest", - "ListProductsResponse", - "ListSkusRequest", - "ListSkusResponse", + "ListCustomersRequest", + "ListCustomersResponse", + "ListEntitlementsRequest", + "ListEntitlementsResponse", "ListOffersRequest", "ListOffersResponse", - "ListPurchasableSkusRequest", - "ListPurchasableSkusResponse", - "PurchasableSku", + "ListProductsRequest", + "ListProductsResponse", "ListPurchasableOffersRequest", "ListPurchasableOffersResponse", + "ListPurchasableSkusRequest", + "ListPurchasableSkusResponse", + "ListSkusRequest", + "ListSkusResponse", + "ListSubscribersRequest", + "ListSubscribersResponse", + "ListTransferableOffersRequest", + "ListTransferableOffersResponse", + "ListTransferableSkusRequest", + "ListTransferableSkusResponse", + "ProvisionCloudIdentityRequest", "PurchasableOffer", + "PurchasableSku", "RegisterSubscriberRequest", "RegisterSubscriberResponse", + "StartPaidServiceRequest", + "SuspendEntitlementRequest", + "TransferableOffer", + "TransferEntitlementsRequest", + "TransferEntitlementsResponse", + "TransferEntitlementsToGoogleRequest", "UnregisterSubscriberRequest", "UnregisterSubscriberResponse", - "ListSubscribersRequest", - "ListSubscribersResponse", + "UpdateChannelPartnerLinkRequest", + "UpdateCustomerRequest", "CustomerEvent", "EntitlementEvent", "SubscriberEvent", diff --git a/google/cloud/channel_v1/types/customers.py b/google/cloud/channel_v1/types/customers.py index 0568feb..c788211 100644 --- a/google/cloud/channel_v1/types/customers.py +++ b/google/cloud/channel_v1/types/customers.py @@ -41,7 +41,8 @@ class Customer(proto.Message): org_postal_address (google.type.postal_address_pb2.PostalAddress): Required. Address of the organization of the customer entity. Region and zip codes are - required to enforce US laws and embargoes. + required to enforce US laws and embargoes. Valid + address lines are required for all customers. Language code is discarded. Use the Customer- level language code to set the customer's language. diff --git a/google/cloud/channel_v1/types/entitlements.py b/google/cloud/channel_v1/types/entitlements.py index ffd6999..0099224 100644 --- a/google/cloud/channel_v1/types/entitlements.py +++ b/google/cloud/channel_v1/types/entitlements.py @@ -22,7 +22,6 @@ from google.cloud.channel_v1.types import offers from google.cloud.channel_v1.types import products from google.protobuf import timestamp_pb2 as timestamp # type: ignore -from google.protobuf import wrappers_pb2 as wrappers # type: ignore __protobuf__ = proto.module( @@ -270,11 +269,6 @@ class TransferableSku(proto.Message): not own. Read-only. Attributes: - is_commitment (google.protobuf.wrappers_pb2.BoolValue): - Whether a transferable SKU is commitment- - ased or not. - commitment_end_timestamp (google.protobuf.timestamp_pb2.Timestamp): - Commitment end timestamp. transfer_eligibility (google.cloud.channel_v1.types.TransferEligibility): Describes the transfer eligibility of a SKU. sku (google.cloud.channel_v1.types.Sku): @@ -282,12 +276,6 @@ class TransferableSku(proto.Message): resource as specified in the Offer. """ - is_commitment = proto.Field(proto.MESSAGE, number=6, message=wrappers.BoolValue,) - - commitment_end_timestamp = proto.Field( - proto.MESSAGE, number=7, message=timestamp.Timestamp, - ) - transfer_eligibility = proto.Field( proto.MESSAGE, number=9, message="TransferEligibility", ) diff --git a/google/cloud/channel_v1/types/offers.py b/google/cloud/channel_v1/types/offers.py index 0aa8b91..8685084 100644 --- a/google/cloud/channel_v1/types/offers.py +++ b/google/cloud/channel_v1/types/offers.py @@ -259,6 +259,10 @@ class Plan(proto.Message): regular pricing goes into effect when trial period ends, or if paid service is started before the end of the trial period. + billing_account (str): + Reseller Billing account to charge after an + offer transaction. Only present for Google Cloud + Platform offers. """ payment_plan = proto.Field(proto.ENUM, number=1, enum="PaymentPlan",) @@ -269,6 +273,8 @@ class Plan(proto.Message): trial_period = proto.Field(proto.MESSAGE, number=4, message="Period",) + billing_account = proto.Field(proto.STRING, number=5) + class PriceByResource(proto.Message): r"""Represents price by resource type. diff --git a/google/cloud/channel_v1/types/service.py b/google/cloud/channel_v1/types/service.py index 47e6e12..819bf70 100644 --- a/google/cloud/channel_v1/types/service.py +++ b/google/cloud/channel_v1/types/service.py @@ -646,10 +646,6 @@ class CreateChannelPartnerLinkRequest(proto.Message): Required. The channel partner link to create. Either channel_partner_link.reseller_cloud_identity_id or domain can be used to create a link. - domain (str): - Optional. The invited partner's domain. Either domain or - channel_partner_link.reseller_cloud_identity_id can be used - to create a link. """ parent = proto.Field(proto.STRING, number=1) @@ -658,8 +654,6 @@ class CreateChannelPartnerLinkRequest(proto.Message): proto.MESSAGE, number=2, message=gcc_channel_partner_links.ChannelPartnerLink, ) - domain = proto.Field(proto.STRING, number=3) - class UpdateChannelPartnerLinkRequest(proto.Message): r"""Request message for diff --git a/noxfile.py b/noxfile.py index 70d9c13..af50a60 100644 --- a/noxfile.py +++ b/noxfile.py @@ -18,6 +18,7 @@ from __future__ import absolute_import import os +import pathlib import shutil import nox @@ -30,6 +31,8 @@ SYSTEM_TEST_PYTHON_VERSIONS = ["3.8"] UNIT_TEST_PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9"] +CURRENT_DIRECTORY = pathlib.Path(__file__).parent.absolute() + # 'docfx' is excluded since it only needs to run in 'docs-presubmit' nox.options.sessions = [ "unit", @@ -41,6 +44,9 @@ "docs", ] +# Error if a python version is missing +nox.options.error_on_missing_interpreters = True + @nox.session(python=DEFAULT_PYTHON_VERSION) def lint(session): @@ -81,18 +87,21 @@ def lint_setup_py(session): def default(session): # Install all test dependencies, then install this package in-place. - session.install("asyncmock", "pytest-asyncio") - session.install( - "mock", "pytest", "pytest-cov", + constraints_path = str( + CURRENT_DIRECTORY / "testing" / f"constraints-{session.python}.txt" ) + session.install("asyncmock", "pytest-asyncio", "-c", constraints_path) - session.install("-e", ".") + session.install("mock", "pytest", "pytest-cov", "-c", constraints_path) + + session.install("-e", ".", "-c", constraints_path) # Run py.test against the unit tests. session.run( "py.test", "--quiet", + f"--junitxml=unit_{session.python}_sponge_log.xml", "--cov=google/cloud", "--cov=tests/unit", "--cov-append", @@ -113,6 +122,9 @@ def unit(session): @nox.session(python=SYSTEM_TEST_PYTHON_VERSIONS) def system(session): """Run the system test suite.""" + constraints_path = str( + CURRENT_DIRECTORY / "testing" / f"constraints-{session.python}.txt" + ) system_test_path = os.path.join("tests", "system.py") system_test_folder_path = os.path.join("tests", "system") @@ -122,6 +134,9 @@ def system(session): # 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") + # Install pyopenssl for mTLS testing. + if os.environ.get("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") == "true": + session.install("pyopenssl") system_test_exists = os.path.exists(system_test_path) system_test_folder_exists = os.path.exists(system_test_folder_path) @@ -134,16 +149,26 @@ 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("-e", ".") + session.install("mock", "pytest", "google-cloud-testutils", "-c", constraints_path) + session.install("-e", ".", "-c", constraints_path) # Run py.test against the system tests. if system_test_exists: - session.run("py.test", "--quiet", system_test_path, *session.posargs) + session.run( + "py.test", + "--quiet", + f"--junitxml=system_{session.python}_sponge_log.xml", + system_test_path, + *session.posargs, + ) if system_test_folder_exists: - session.run("py.test", "--quiet", system_test_folder_path, *session.posargs) + session.run( + "py.test", + "--quiet", + f"--junitxml=system_{session.python}_sponge_log.xml", + system_test_folder_path, + *session.posargs, + ) @nox.session(python=DEFAULT_PYTHON_VERSION) @@ -186,9 +211,7 @@ 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") + session.install("sphinx", "alabaster", "recommonmark", "gcp-sphinx-docfx-yaml") shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True) session.run( diff --git a/synth.py b/owlbot.py similarity index 82% rename from synth.py rename to owlbot.py index a496823..0dc6b49 100644 --- a/synth.py +++ b/owlbot.py @@ -20,21 +20,14 @@ import synthtool.gcp as gcp from synthtool.languages import python -gapic = gcp.GAPICBazel() common = gcp.CommonTemplates() # ---------------------------------------------------------------------------- # Generate channel GAPIC layer # ---------------------------------------------------------------------------- -versions = ["v1"] -for version in versions: - library = gapic.py_library( - service="channel", - version=version, - bazel_target=f"//google/cloud/channel/{version}:channel-{version}-py", - ) - +for library in s.get_staging_dirs("v1"): s.move(library, excludes=["setup.py", "README.rst", "docs/index.rst"]) +s.remove_staging_dirs() # ---------------------------------------------------------------------------- # Add templated files @@ -45,4 +38,4 @@ templated_files, excludes=[".coveragerc"] # the microgenerator has a good coveragerc file ) -s.shell.run(["nox", "-s", "blacken"], hide_output=False) \ No newline at end of file +s.shell.run(["nox", "-s", "blacken"], hide_output=False) diff --git a/renovate.json b/renovate.json index 4fa9493..f08bc22 100644 --- a/renovate.json +++ b/renovate.json @@ -1,5 +1,6 @@ { "extends": [ "config:base", ":preserveSemverRanges" - ] + ], + "ignorePaths": [".pre-commit-config.yaml"] } diff --git a/scripts/fixup_channel_v1_keywords.py b/scripts/fixup_channel_v1_keywords.py index 2e11568..7324026 100644 --- a/scripts/fixup_channel_v1_keywords.py +++ b/scripts/fixup_channel_v1_keywords.py @@ -47,7 +47,7 @@ class channelCallTransformer(cst.CSTTransformer): 'change_parameters': ('name', 'parameters', 'request_id', 'purchase_order_id', ), 'change_renewal_settings': ('name', 'renewal_settings', 'request_id', ), 'check_cloud_identity_accounts_exist': ('parent', 'domain', ), - 'create_channel_partner_link': ('parent', 'channel_partner_link', 'domain', ), + 'create_channel_partner_link': ('parent', 'channel_partner_link', ), 'create_customer': ('parent', 'customer', ), 'create_entitlement': ('parent', 'entitlement', 'request_id', ), 'delete_customer': ('name', ), diff --git a/setup.py b/setup.py index 04f061e..92b6c5f 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ import os import setuptools # type: ignore -version = "0.2.0" +version = "0.2.1" package_root = os.path.abspath(os.path.dirname(__file__)) diff --git a/synth.metadata b/synth.metadata deleted file mode 100644 index 53c3236..0000000 --- a/synth.metadata +++ /dev/null @@ -1,142 +0,0 @@ -{ - "sources": [ - { - "git": { - "name": ".", - "remote": "https://github.com/googleapis/python-channel.git", - "sha": "0d25fa6ad0e3fac43b7473523393c22cbd157129" - } - }, - { - "git": { - "name": "googleapis", - "remote": "https://github.com/googleapis/googleapis.git", - "sha": "6ef9eaea379fc1cc0355e06a5a20b594543ee693", - "internalRef": "355059873" - } - }, - { - "git": { - "name": "synthtool", - "remote": "https://github.com/googleapis/synthtool.git", - "sha": "778d8beae28d6d87eb01fdc839a4b4d966ed2ebe" - } - }, - { - "git": { - "name": "synthtool", - "remote": "https://github.com/googleapis/synthtool.git", - "sha": "778d8beae28d6d87eb01fdc839a4b4d966ed2ebe" - } - } - ], - "destinations": [ - { - "client": { - "source": "googleapis", - "apiName": "channel", - "apiVersion": "v1", - "language": "python", - "generator": "bazel" - } - } - ], - "generatedFiles": [ - ".coveragerc", - ".flake8", - ".github/CONTRIBUTING.md", - ".github/ISSUE_TEMPLATE/bug_report.md", - ".github/ISSUE_TEMPLATE/feature_request.md", - ".github/ISSUE_TEMPLATE/support_request.md", - ".github/PULL_REQUEST_TEMPLATE.md", - ".github/header-checker-lint.yml", - ".github/release-please.yml", - ".github/snippet-bot.yml", - ".gitignore", - ".kokoro/build.sh", - ".kokoro/continuous/common.cfg", - ".kokoro/continuous/continuous.cfg", - ".kokoro/docker/docs/Dockerfile", - ".kokoro/docker/docs/fetch_gpg_keys.sh", - ".kokoro/docs/common.cfg", - ".kokoro/docs/docs-presubmit.cfg", - ".kokoro/docs/docs.cfg", - ".kokoro/populate-secrets.sh", - ".kokoro/presubmit/common.cfg", - ".kokoro/presubmit/presubmit.cfg", - ".kokoro/publish-docs.sh", - ".kokoro/release.sh", - ".kokoro/release/common.cfg", - ".kokoro/release/release.cfg", - ".kokoro/samples/lint/common.cfg", - ".kokoro/samples/lint/continuous.cfg", - ".kokoro/samples/lint/periodic.cfg", - ".kokoro/samples/lint/presubmit.cfg", - ".kokoro/samples/python3.6/common.cfg", - ".kokoro/samples/python3.6/continuous.cfg", - ".kokoro/samples/python3.6/periodic.cfg", - ".kokoro/samples/python3.6/presubmit.cfg", - ".kokoro/samples/python3.7/common.cfg", - ".kokoro/samples/python3.7/continuous.cfg", - ".kokoro/samples/python3.7/periodic.cfg", - ".kokoro/samples/python3.7/presubmit.cfg", - ".kokoro/samples/python3.8/common.cfg", - ".kokoro/samples/python3.8/continuous.cfg", - ".kokoro/samples/python3.8/periodic.cfg", - ".kokoro/samples/python3.8/presubmit.cfg", - ".kokoro/test-samples.sh", - ".kokoro/trampoline.sh", - ".kokoro/trampoline_v2.sh", - ".pre-commit-config.yaml", - ".trampolinerc", - "CODE_OF_CONDUCT.md", - "CONTRIBUTING.rst", - "LICENSE", - "MANIFEST.in", - "docs/_static/custom.css", - "docs/_templates/layout.html", - "docs/channel_v1/cloud_channel_service.rst", - "docs/channel_v1/services.rst", - "docs/channel_v1/types.rst", - "docs/conf.py", - "docs/multiprocessing.rst", - "google/cloud/channel/__init__.py", - "google/cloud/channel/py.typed", - "google/cloud/channel_v1/__init__.py", - "google/cloud/channel_v1/py.typed", - "google/cloud/channel_v1/services/__init__.py", - "google/cloud/channel_v1/services/cloud_channel_service/__init__.py", - "google/cloud/channel_v1/services/cloud_channel_service/async_client.py", - "google/cloud/channel_v1/services/cloud_channel_service/client.py", - "google/cloud/channel_v1/services/cloud_channel_service/pagers.py", - "google/cloud/channel_v1/services/cloud_channel_service/transports/__init__.py", - "google/cloud/channel_v1/services/cloud_channel_service/transports/base.py", - "google/cloud/channel_v1/services/cloud_channel_service/transports/grpc.py", - "google/cloud/channel_v1/services/cloud_channel_service/transports/grpc_asyncio.py", - "google/cloud/channel_v1/types/__init__.py", - "google/cloud/channel_v1/types/channel_partner_links.py", - "google/cloud/channel_v1/types/common.py", - "google/cloud/channel_v1/types/customers.py", - "google/cloud/channel_v1/types/entitlements.py", - "google/cloud/channel_v1/types/offers.py", - "google/cloud/channel_v1/types/operations.py", - "google/cloud/channel_v1/types/products.py", - "google/cloud/channel_v1/types/service.py", - "google/cloud/channel_v1/types/subscriber_event.py", - "mypy.ini", - "noxfile.py", - "renovate.json", - "scripts/decrypt-secrets.sh", - "scripts/fixup_channel_v1_keywords.py", - "scripts/readme-gen/readme_gen.py", - "scripts/readme-gen/templates/README.tmpl.rst", - "scripts/readme-gen/templates/auth.tmpl.rst", - "scripts/readme-gen/templates/auth_api_key.tmpl.rst", - "scripts/readme-gen/templates/install_deps.tmpl.rst", - "scripts/readme-gen/templates/install_portaudio.tmpl.rst", - "setup.cfg", - "testing/.gitignore", - "tests/unit/gapic/channel_v1/__init__.py", - "tests/unit/gapic/channel_v1/test_cloud_channel_service.py" - ] -} \ No newline at end of file diff --git a/testing/constraints-3.10.txt b/testing/constraints-3.10.txt new file mode 100644 index 0000000..e69de29 diff --git a/testing/constraints-3.11.txt b/testing/constraints-3.11.txt new file mode 100644 index 0000000..e69de29 diff --git a/testing/constraints-3.6.txt b/testing/constraints-3.6.txt new file mode 100644 index 0000000..650f2c5 --- /dev/null +++ b/testing/constraints-3.6.txt @@ -0,0 +1,23 @@ +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This constraints file is used to check that lower bounds +# are correct in setup.py +# List *all* library dependencies and extras in this file. +# Pin the version to the lower bound. +# +# e.g., if setup.py has "foo >= 1.14.0, < 2.0.0dev", +# Then this file should have foo==1.14.0 +google-api-core==1.22.2 +proto-plus==1.4.0 diff --git a/testing/constraints-3.7.txt b/testing/constraints-3.7.txt new file mode 100644 index 0000000..da93009 --- /dev/null +++ b/testing/constraints-3.7.txt @@ -0,0 +1,2 @@ +# This constraints file is left inentionally empty +# so the latest version of dependencies is installed \ No newline at end of file diff --git a/testing/constraints-3.8.txt b/testing/constraints-3.8.txt new file mode 100644 index 0000000..da93009 --- /dev/null +++ b/testing/constraints-3.8.txt @@ -0,0 +1,2 @@ +# This constraints file is left inentionally empty +# so the latest version of dependencies is installed \ No newline at end of file diff --git a/testing/constraints-3.9.txt b/testing/constraints-3.9.txt new file mode 100644 index 0000000..da93009 --- /dev/null +++ b/testing/constraints-3.9.txt @@ -0,0 +1,2 @@ +# This constraints file is left inentionally empty +# so the latest version of dependencies is installed \ No newline at end of file diff --git a/tests/unit/gapic/channel_v1/__init__.py b/tests/unit/gapic/channel_v1/__init__.py index 8b13789..42ffdf2 100644 --- a/tests/unit/gapic/channel_v1/__init__.py +++ b/tests/unit/gapic/channel_v1/__init__.py @@ -1 +1,16 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/tests/unit/gapic/channel_v1/test_cloud_channel_service.py b/tests/unit/gapic/channel_v1/test_cloud_channel_service.py index 1772cc1..a593db5 100644 --- a/tests/unit/gapic/channel_v1/test_cloud_channel_service.py +++ b/tests/unit/gapic/channel_v1/test_cloud_channel_service.py @@ -104,15 +104,19 @@ def test__get_default_mtls_endpoint(): ) -def test_cloud_channel_service_client_from_service_account_info(): +@pytest.mark.parametrize( + "client_class", [CloudChannelServiceClient, CloudChannelServiceAsyncClient,] +) +def test_cloud_channel_service_client_from_service_account_info(client_class): creds = credentials.AnonymousCredentials() with mock.patch.object( service_account.Credentials, "from_service_account_info" ) as factory: factory.return_value = creds info = {"valid": True} - client = CloudChannelServiceClient.from_service_account_info(info) + client = client_class.from_service_account_info(info) assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "cloudchannel.googleapis.com:443" @@ -128,9 +132,11 @@ def test_cloud_channel_service_client_from_service_account_file(client_class): factory.return_value = creds client = client_class.from_service_account_file("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) client = client_class.from_service_account_json("dummy/file/path.json") assert client.transport._credentials == creds + assert isinstance(client, client_class) assert client.transport._host == "cloudchannel.googleapis.com:443" @@ -515,6 +521,22 @@ def test_list_customers_from_dict(): test_list_customers(request_type=dict) +def test_list_customers_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_customers), "__call__") as call: + client.list_customers() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ListCustomersRequest() + + @pytest.mark.asyncio async def test_list_customers_async( transport: str = "grpc_asyncio", request_type=service.ListCustomersRequest @@ -801,6 +823,22 @@ def test_get_customer_from_dict(): test_get_customer(request_type=dict) +def test_get_customer_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_customer), "__call__") as call: + client.get_customer() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.GetCustomerRequest() + + @pytest.mark.asyncio async def test_get_customer_async( transport: str = "grpc_asyncio", request_type=service.GetCustomerRequest @@ -1014,6 +1052,24 @@ def test_check_cloud_identity_accounts_exist_from_dict(): test_check_cloud_identity_accounts_exist(request_type=dict) +def test_check_cloud_identity_accounts_exist_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.check_cloud_identity_accounts_exist), "__call__" + ) as call: + client.check_cloud_identity_accounts_exist() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.CheckCloudIdentityAccountsExistRequest() + + @pytest.mark.asyncio async def test_check_cloud_identity_accounts_exist_async( transport: str = "grpc_asyncio", @@ -1165,6 +1221,22 @@ def test_create_customer_from_dict(): test_create_customer(request_type=dict) +def test_create_customer_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_customer), "__call__") as call: + client.create_customer() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.CreateCustomerRequest() + + @pytest.mark.asyncio async def test_create_customer_async( transport: str = "grpc_asyncio", request_type=service.CreateCustomerRequest @@ -1329,6 +1401,22 @@ def test_update_customer_from_dict(): test_update_customer(request_type=dict) +def test_update_customer_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_customer), "__call__") as call: + client.update_customer() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.UpdateCustomerRequest() + + @pytest.mark.asyncio async def test_update_customer_async( transport: str = "grpc_asyncio", request_type=service.UpdateCustomerRequest @@ -1474,6 +1562,22 @@ def test_delete_customer_from_dict(): test_delete_customer(request_type=dict) +def test_delete_customer_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_customer), "__call__") as call: + client.delete_customer() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.DeleteCustomerRequest() + + @pytest.mark.asyncio async def test_delete_customer_async( transport: str = "grpc_asyncio", request_type=service.DeleteCustomerRequest @@ -1662,6 +1766,24 @@ def test_provision_cloud_identity_from_dict(): test_provision_cloud_identity(request_type=dict) +def test_provision_cloud_identity_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.provision_cloud_identity), "__call__" + ) as call: + client.provision_cloud_identity() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ProvisionCloudIdentityRequest() + + @pytest.mark.asyncio async def test_provision_cloud_identity_async( transport: str = "grpc_asyncio", request_type=service.ProvisionCloudIdentityRequest @@ -1796,6 +1918,24 @@ def test_list_entitlements_from_dict(): test_list_entitlements(request_type=dict) +def test_list_entitlements_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_entitlements), "__call__" + ) as call: + client.list_entitlements() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ListEntitlementsRequest() + + @pytest.mark.asyncio async def test_list_entitlements_async( transport: str = "grpc_asyncio", request_type=service.ListEntitlementsRequest @@ -2082,6 +2222,24 @@ def test_list_transferable_skus_from_dict(): test_list_transferable_skus(request_type=dict) +def test_list_transferable_skus_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_transferable_skus), "__call__" + ) as call: + client.list_transferable_skus() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ListTransferableSkusRequest() + + @pytest.mark.asyncio async def test_list_transferable_skus_async( transport: str = "grpc_asyncio", request_type=service.ListTransferableSkusRequest @@ -2394,6 +2552,24 @@ def test_list_transferable_offers_from_dict(): test_list_transferable_offers(request_type=dict) +def test_list_transferable_offers_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_transferable_offers), "__call__" + ) as call: + client.list_transferable_offers() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ListTransferableOffersRequest() + + @pytest.mark.asyncio async def test_list_transferable_offers_async( transport: str = "grpc_asyncio", request_type=service.ListTransferableOffersRequest @@ -2722,6 +2898,22 @@ def test_get_entitlement_from_dict(): test_get_entitlement(request_type=dict) +def test_get_entitlement_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_entitlement), "__call__") as call: + client.get_entitlement() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.GetEntitlementRequest() + + @pytest.mark.asyncio async def test_get_entitlement_async( transport: str = "grpc_asyncio", request_type=service.GetEntitlementRequest @@ -2867,6 +3059,24 @@ def test_create_entitlement_from_dict(): test_create_entitlement(request_type=dict) +def test_create_entitlement_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_entitlement), "__call__" + ) as call: + client.create_entitlement() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.CreateEntitlementRequest() + + @pytest.mark.asyncio async def test_create_entitlement_async( transport: str = "grpc_asyncio", request_type=service.CreateEntitlementRequest @@ -2996,6 +3206,24 @@ def test_change_parameters_from_dict(): test_change_parameters(request_type=dict) +def test_change_parameters_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.change_parameters), "__call__" + ) as call: + client.change_parameters() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ChangeParametersRequest() + + @pytest.mark.asyncio async def test_change_parameters_async( transport: str = "grpc_asyncio", request_type=service.ChangeParametersRequest @@ -3125,6 +3353,24 @@ def test_change_renewal_settings_from_dict(): test_change_renewal_settings(request_type=dict) +def test_change_renewal_settings_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.change_renewal_settings), "__call__" + ) as call: + client.change_renewal_settings() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ChangeRenewalSettingsRequest() + + @pytest.mark.asyncio async def test_change_renewal_settings_async( transport: str = "grpc_asyncio", request_type=service.ChangeRenewalSettingsRequest @@ -3250,6 +3496,22 @@ def test_change_offer_from_dict(): test_change_offer(request_type=dict) +def test_change_offer_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.change_offer), "__call__") as call: + client.change_offer() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ChangeOfferRequest() + + @pytest.mark.asyncio async def test_change_offer_async( transport: str = "grpc_asyncio", request_type=service.ChangeOfferRequest @@ -3373,6 +3635,24 @@ def test_start_paid_service_from_dict(): test_start_paid_service(request_type=dict) +def test_start_paid_service_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.start_paid_service), "__call__" + ) as call: + client.start_paid_service() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.StartPaidServiceRequest() + + @pytest.mark.asyncio async def test_start_paid_service_async( transport: str = "grpc_asyncio", request_type=service.StartPaidServiceRequest @@ -3502,6 +3782,24 @@ def test_suspend_entitlement_from_dict(): test_suspend_entitlement(request_type=dict) +def test_suspend_entitlement_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.suspend_entitlement), "__call__" + ) as call: + client.suspend_entitlement() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.SuspendEntitlementRequest() + + @pytest.mark.asyncio async def test_suspend_entitlement_async( transport: str = "grpc_asyncio", request_type=service.SuspendEntitlementRequest @@ -3631,6 +3929,24 @@ def test_cancel_entitlement_from_dict(): test_cancel_entitlement(request_type=dict) +def test_cancel_entitlement_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.cancel_entitlement), "__call__" + ) as call: + client.cancel_entitlement() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.CancelEntitlementRequest() + + @pytest.mark.asyncio async def test_cancel_entitlement_async( transport: str = "grpc_asyncio", request_type=service.CancelEntitlementRequest @@ -3760,6 +4076,24 @@ def test_activate_entitlement_from_dict(): test_activate_entitlement(request_type=dict) +def test_activate_entitlement_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.activate_entitlement), "__call__" + ) as call: + client.activate_entitlement() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ActivateEntitlementRequest() + + @pytest.mark.asyncio async def test_activate_entitlement_async( transport: str = "grpc_asyncio", request_type=service.ActivateEntitlementRequest @@ -3889,6 +4223,24 @@ def test_transfer_entitlements_from_dict(): test_transfer_entitlements(request_type=dict) +def test_transfer_entitlements_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.transfer_entitlements), "__call__" + ) as call: + client.transfer_entitlements() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.TransferEntitlementsRequest() + + @pytest.mark.asyncio async def test_transfer_entitlements_async( transport: str = "grpc_asyncio", request_type=service.TransferEntitlementsRequest @@ -4018,6 +4370,24 @@ def test_transfer_entitlements_to_google_from_dict(): test_transfer_entitlements_to_google(request_type=dict) +def test_transfer_entitlements_to_google_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.transfer_entitlements_to_google), "__call__" + ) as call: + client.transfer_entitlements_to_google() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.TransferEntitlementsToGoogleRequest() + + @pytest.mark.asyncio async def test_transfer_entitlements_to_google_async( transport: str = "grpc_asyncio", @@ -4153,6 +4523,24 @@ def test_list_channel_partner_links_from_dict(): test_list_channel_partner_links(request_type=dict) +def test_list_channel_partner_links_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_channel_partner_links), "__call__" + ) as call: + client.list_channel_partner_links() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ListChannelPartnerLinksRequest() + + @pytest.mark.asyncio async def test_list_channel_partner_links_async( transport: str = "grpc_asyncio", request_type=service.ListChannelPartnerLinksRequest @@ -4481,6 +4869,24 @@ def test_get_channel_partner_link_from_dict(): test_get_channel_partner_link(request_type=dict) +def test_get_channel_partner_link_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_channel_partner_link), "__call__" + ) as call: + client.get_channel_partner_link() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.GetChannelPartnerLinkRequest() + + @pytest.mark.asyncio async def test_get_channel_partner_link_async( transport: str = "grpc_asyncio", request_type=service.GetChannelPartnerLinkRequest @@ -4643,6 +5049,24 @@ def test_create_channel_partner_link_from_dict(): test_create_channel_partner_link(request_type=dict) +def test_create_channel_partner_link_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.create_channel_partner_link), "__call__" + ) as call: + client.create_channel_partner_link() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.CreateChannelPartnerLinkRequest() + + @pytest.mark.asyncio async def test_create_channel_partner_link_async( transport: str = "grpc_asyncio", @@ -4806,6 +5230,24 @@ def test_update_channel_partner_link_from_dict(): test_update_channel_partner_link(request_type=dict) +def test_update_channel_partner_link_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_channel_partner_link), "__call__" + ) as call: + client.update_channel_partner_link() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.UpdateChannelPartnerLinkRequest() + + @pytest.mark.asyncio async def test_update_channel_partner_link_async( transport: str = "grpc_asyncio", @@ -4955,6 +5397,22 @@ def test_list_products_from_dict(): test_list_products(request_type=dict) +def test_list_products_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_products), "__call__") as call: + client.list_products() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ListProductsRequest() + + @pytest.mark.asyncio async def test_list_products_async( transport: str = "grpc_asyncio", request_type=service.ListProductsRequest @@ -5151,6 +5609,22 @@ def test_list_skus_from_dict(): test_list_skus(request_type=dict) +def test_list_skus_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_skus), "__call__") as call: + client.list_skus() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ListSkusRequest() + + @pytest.mark.asyncio async def test_list_skus_async( transport: str = "grpc_asyncio", request_type=service.ListSkusRequest @@ -5387,6 +5861,22 @@ def test_list_offers_from_dict(): test_list_offers(request_type=dict) +def test_list_offers_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_offers), "__call__") as call: + client.list_offers() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ListOffersRequest() + + @pytest.mark.asyncio async def test_list_offers_async( transport: str = "grpc_asyncio", request_type=service.ListOffersRequest @@ -5635,6 +6125,24 @@ def test_list_purchasable_skus_from_dict(): test_list_purchasable_skus(request_type=dict) +def test_list_purchasable_skus_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_purchasable_skus), "__call__" + ) as call: + client.list_purchasable_skus() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ListPurchasableSkusRequest() + + @pytest.mark.asyncio async def test_list_purchasable_skus_async( transport: str = "grpc_asyncio", request_type=service.ListPurchasableSkusRequest @@ -5931,6 +6439,24 @@ def test_list_purchasable_offers_from_dict(): test_list_purchasable_offers(request_type=dict) +def test_list_purchasable_offers_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_purchasable_offers), "__call__" + ) as call: + client.list_purchasable_offers() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ListPurchasableOffersRequest() + + @pytest.mark.asyncio async def test_list_purchasable_offers_async( transport: str = "grpc_asyncio", request_type=service.ListPurchasableOffersRequest @@ -6237,6 +6763,24 @@ def test_register_subscriber_from_dict(): test_register_subscriber(request_type=dict) +def test_register_subscriber_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.register_subscriber), "__call__" + ) as call: + client.register_subscriber() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.RegisterSubscriberRequest() + + @pytest.mark.asyncio async def test_register_subscriber_async( transport: str = "grpc_asyncio", request_type=service.RegisterSubscriberRequest @@ -6371,6 +6915,24 @@ def test_unregister_subscriber_from_dict(): test_unregister_subscriber(request_type=dict) +def test_unregister_subscriber_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.unregister_subscriber), "__call__" + ) as call: + client.unregister_subscriber() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.UnregisterSubscriberRequest() + + @pytest.mark.asyncio async def test_unregister_subscriber_async( transport: str = "grpc_asyncio", request_type=service.UnregisterSubscriberRequest @@ -6511,6 +7073,22 @@ def test_list_subscribers_from_dict(): test_list_subscribers(request_type=dict) +def test_list_subscribers_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = CloudChannelServiceClient( + credentials=credentials.AnonymousCredentials(), transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_subscribers), "__call__") as call: + client.list_subscribers() + call.assert_called() + _, args, _ = call.mock_calls[0] + + assert args[0] == service.ListSubscribersRequest() + + @pytest.mark.asyncio async def test_list_subscribers_async( transport: str = "grpc_asyncio", request_type=service.ListSubscribersRequest